diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..381442a4a --- /dev/null +++ b/.clang-format @@ -0,0 +1,119 @@ +--- +Language: Cpp +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignEscapedNewlines: Right +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 0 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^(<|"(gtest|isl|json)/)' + Priority: 1 + - Regex: '.*' + Priority: 2 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '$' +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 100 +PointerAlignment: Right +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 2 +UseTab: Never +... diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..cfbd4066f --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.tar.gz filter=lfs diff=lfs merge=lfs -text \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 24599fcab..96c288ce0 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,3 +1,8 @@ + +Checklist: + +- [ ] I added a summary of any user-facing changes (compared to the last release) in the `changelog-entries/.md`. +- [ ] I will remember to squash-and-merge, providing a useful summary of the changes of this PR. diff --git a/.github/workflows/check-markdown.yml b/.github/workflows/check-markdown.yml deleted file mode 100644 index 63a0df9ad..000000000 --- a/.github/workflows/check-markdown.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: Lint docs -on: [push, pull_request] -jobs: - check_md: - runs-on: ubuntu-latest - steps: - - name: Check out repository - uses: actions/checkout@v2 - - name: Lint markdown files (markdownlint) - uses: articulate/actions-markdownlint@v1 - with: - config: .markdownlint.json - files: '.' - ignore: changelog-entries diff --git a/.github/workflows/check-pep8.yml b/.github/workflows/check-pep8.yml deleted file mode 100644 index cc74941b8..000000000 --- a/.github/workflows/check-pep8.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: autopep8 -on: push -jobs: - autopep8: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: autopep8 - id: autopep8 - uses: peter-evans/autopep8@v1 - with: - args: --recursive --diff --aggressive --aggressive --exit-code --ignore E402 --max-line-length 120 . - - name: Fail if autopep8 made changes - if: ${{ steps.autopep8.outputs.exit-code == 2 }} - run: exit 1 diff --git a/.github/workflows/check-scripts.yaml b/.github/workflows/check-scripts.yaml deleted file mode 100644 index 5ced647ff..000000000 --- a/.github/workflows/check-scripts.yaml +++ /dev/null @@ -1,14 +0,0 @@ -name: Check scripts -on: [push, pull_request] -jobs: - check_scripts: - runs-on: ubuntu-latest - steps: - - name: Check out repository - uses: actions/checkout@v2 - - run: bash tools/check.sh - - run: bash tools/check-size.sh - - name: Run ShellCheck - uses: ludeeus/action-shellcheck@master - env: - SHELLCHECK_OPTS: -e SC1091 diff --git a/.github/workflows/check-style.yml b/.github/workflows/check-style.yml new file mode 100644 index 000000000..172ab06bf --- /dev/null +++ b/.github/workflows/check-style.yml @@ -0,0 +1,37 @@ +name: Check style +on: + push: + branches: + - master + - develop + pull_request: + branches: + - master + - develop +jobs: + check_style: + runs-on: ubuntu-latest + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + - name: Setup python + uses: actions/setup-python@v5 + with: + python-version: '3.10' + check-latest: true + - name: Install pre-commit + run: pip install pre-commit + - name: Run checks + run: pre-commit run -a -v + - name: Git status + if: always() + run: | + echo -e '### Status\n```text' >> $GITHUB_STEP_SUMMARY + git status | tee -a $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + - name: Full diff + if: always() + run: | + echo -e '### Diff\n```diff' >> $GITHUB_STEP_SUMMARY + git diff | tee -a $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/generate_reference_results_manual.yml b/.github/workflows/generate_reference_results_manual.yml new file mode 100644 index 000000000..bca10cf4a --- /dev/null +++ b/.github/workflows/generate_reference_results_manual.yml @@ -0,0 +1,31 @@ +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 + loglevel: + description: 'loglevel 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 }} + loglevel: ${{ inputs.loglevel }} \ No newline at end of file diff --git a/.github/workflows/generate_reference_results_workflow.yml b/.github/workflows/generate_reference_results_workflow.yml new file mode 100644 index 000000000..cf79320c6 --- /dev/null +++ b/.github/workflows/generate_reference_results_workflow.yml @@ -0,0 +1,71 @@ +name: Generate reference results workflow +on: + workflow_call: + 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 + loglevel: + description: 'loglevel used for the systemtests' + default: 'INFO' + required: true + type: string +jobs: + generate_reference_results: + runs-on: [self-hosted, linux, x64, precice-tests-vm] + steps: + - name: Display a quick job summary + run: | + echo "Initiated by: ${{ github.actor }}" + echo "Running generate_reference_results.py --log-level ${{inputs.loglevel}}" + echo "Using Ref: ${{ inputs.from_ref }}" + echo "Commit message on success: ${{ inputs.commit_msg }}" + - name: Move LFS URL to local LFS server + run: | + /home/precice/runners_root/scripts/make_lfs_local.sh + - name: 'Cleanup the folder' + # The first rf -rf ./* removes all non hidden files + # The second rf -rf ./.??* removes all hidden files (but not . and ..) + run: | + ls -la ./ + rm -rf ./* + rm -rf ./.??* + ls -la ./ + - name: Check out Tutorials for systest + uses: actions/checkout@v4 + with: + ref: ${{ inputs.from_ref }} + lfs: true + fetch-depth: 0 + - name: Install Python dependencies + run: | + pip install --user -r tools/tests/requirements.txt + - 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" + python $GENERATE_REF_RESULTS --log-level=${{inputs.loglevel}} + cd ../../ + - name: Create commit + if: success() + run: | + git checkout ${{ inputs.from_ref }} + git add ./*/*/*.tar.gz + git add ./*/*.tar.gz + git add ./*/*.metadata + git commit -m "${{inputs.commit_msg}}" + git push + - name: Upload artifacts for debugging + if: failure() + uses: actions/upload-artifact@v3 + with: + name: runs + path: | + runs/* diff --git a/.github/workflows/run_testsuite_manual.yml b/.github/workflows/run_testsuite_manual.yml new file mode 100644 index 000000000..89f712c1c --- /dev/null +++ b/.github/workflows/run_testsuite_manual.yml @@ -0,0 +1,45 @@ +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 + systests_branch: + description: 'Branch to take the systest from' + default: 'develop' + required: true + type: string + loglevel: + description: 'loglevel 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: 'FALSE' + 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 }} + systests_branch: ${{ inputs.systests_branch }} + loglevel: ${{ inputs.loglevel }} + upload_artifacts: ${{ inputs.upload_artifacts }} diff --git a/.github/workflows/run_testsuite_workflow.yml b/.github/workflows/run_testsuite_workflow.yml new file mode 100644 index 000000000..884171ce7 --- /dev/null +++ b/.github/workflows/run_testsuite_workflow.yml @@ -0,0 +1,73 @@ +name: Run Testsuite reusable workflow +on: + workflow_call: + inputs: + suites: + description: 'Comma seperated testsuites to execute' + required: true + type: string + build_args: + description: 'Build arguments' + required: false + type: string + systests_branch: + description: 'Branch to take the systest from' + default: 'develop' + required: true + type: string + loglevel: + description: 'loglevel used for the systemtests' + default: 'INFO' + required: false + type: string + upload_artifacts: + description: 'TRUE or FALSE (Default: FALSE -> Upload only when the workflow fails)' + default: 'FALSE' + type: string +jobs: + run_testsuite: + runs-on: [self-hosted, linux, x64, precice-tests-vm] + steps: + - name: Display a quick job summary + run: | + echo "Initiated by: ${{ github.actor }}" + echo "Running systemtests --build_args=${{inputs.build_args}} --suites=${{ inputs.suites}}" + echo "Systemtests branch: ${{ inputs.systests_branch }}" + echo "Uploading the runs folder on success: ${{ inputs.upload_artifacts }}" + - name: Move LFS URL to local LFS server + run: | + /home/precice/runners_root/scripts/make_lfs_local.sh + - name: 'Cleanup the folder' + run: | + ls -la ./ + rm -rf ./* + rm -rf ./.??* + ls -la ./ + - name: Check out Tutorials for systest + uses: actions/checkout@v4 + with: + repository: precice/tutorials + ref: ${{ inputs.systests_branch }} + lfs: true + fetch-depth: 0 + - name: Map remote branches to local ones + run: | + /home/precice/runners_root/scripts/map_origin_to_local.sh ./ + - name: Install Python dependencies + run: | + pip install --user -r tools/tests/requirements.txt + - name: Run tests + run: | + cd tools/tests + python systemtests.py --build_args=${{ inputs.build_args}} --suites=${{ inputs.suites}} --log-level=${{ inputs.loglevel}} + cd ../../ + - name: Archive run files + if: ${{ failure() || inputs.upload_artifacts == 'TRUE' }} + uses: actions/upload-artifact@v4 + with: + name: runs + path: | + runs/* + - name: tidy up the docker + run: | + docker network prune -f diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..e94e6645e --- /dev/null +++ b/.gitignore @@ -0,0 +1,112 @@ +# Check which files are ignored with: git status --ignored . +# or, to also see which pattern matches: git check-ignore -v **/* +# To deep-clean: git clean -idx . + +# In case there are tutorial-specific rules, add a separate .gitignore in the corresponding directory, +# but prefer adding general rules here, if possible. + +# General log files +*.log +out + +# Common result files +*.vtk +*.vtu +*.pvd + +# preCICE +precice-profiling/ +precice-run/ +core +precice-*-events.json + +# C++ +*.o +*.so +.out +build/ + +# Python +.venv/ +__pycache__/ +*.pyc + +# Rust +Cargo.lock +target/ + +# OpenFOAM +0.*/ +[1-9]*/ +!0/ +functionObjectProperties +*/phi* +*/meshPhi* +processor*/ +history +**/constant/polyMesh/ +postProcessing/ +*.foam +*.OpenFOAM +dynamicCode + +# CalculiX +spooles.out +dummy +*.12d +*.cvg +*.dat +*.frd +*.sta +*.eig +*.rout + +# code_aster +*.mess +*.resu +*.rmed +REPE_OUT/ + +# SU2 +restart_flow_*.dat +forces_breakdown.dat +surface_flow_*.csv +history_*.csv + +# ASTE +result.stats.json +fine_mesh +coarse_mesh +mapped + +# deal.II +linear_elasticity +nonlinear_elasticity + +# DUNE +dune-env/ + +# DuMuX +dumux/ +dumux-phasefield/ +dumux-adapter/ +dune-* +*/build-cmake/ +install* + +# FEniCS covered by .vtk +# Nutils covered by .vtk + +# System tests +runs/ + +# General editor and OS files +.vscode +*.DS_STORE +.idea +*.bak +*~ +.cproject +.project +.settings/ +*.swp diff --git a/.lfsconfig b/.lfsconfig new file mode 100644 index 000000000..727badd6d --- /dev/null +++ b/.lfsconfig @@ -0,0 +1,2 @@ +[lfs] + url = http://precice-tests.informatik.uni-stuttgart.de/precice/tutorials.git/info/lfs \ No newline at end of file diff --git a/.markdownlint.json b/.markdownlint.json index e12067088..979cb2852 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -1,4 +1,5 @@ { "MD013": false, - "MD033": false + "MD033": false, + "MD034": false } diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..4280facc6 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,58 @@ +repos: +# Official repo for default hooks +- repo: https://github.com/precice/precice-pre-commit-hooks + rev: 'v3.3' + hooks: + - id: format-precice-config +- repo: https://github.com/igorshubovych/markdownlint-cli + rev: v0.30.0 + hooks: + - id: markdownlint + exclude: | + (?x)^( + changelog-entries| + .github/pull_request_template.md + )$ + - id: markdownlint-fix + exclude: | + (?x)^( + changelog-entries| + .github/pull_request_template.md + )$ +- repo: https://github.com/hhatto/autopep8 + rev: v2.0.4 + hooks: + - id: autopep8 + args: [ --in-place, --exit-code, --aggressive, --ignore=E402, --max-line-length=120 ] +- repo: https://github.com/pre-commit/mirrors-clang-format + rev: 'v14.0.6' + hooks: + - id: clang-format + exclude: '\.json$' +- repo: https://github.com/koalaman/shellcheck-precommit + rev: v0.10.0 + hooks: + - id: shellcheck + args: [ --external-sources, --exclude=SC1091 ] +- repo: local + hooks: + - id: check-image-naming + name: check image names + language: python + entry: tools/check-image-names.py + files: ".*/images/.*" + - id: check-size + name: check sizes + language: script + entry: tools/check-size.sh + pass_filenames: false + - id: check-names + name: check file names + language: script + entry: tools/check.sh + pass_filenames: false + - id: check-links-to-precice + name: check links to precice.org + language: script + entry: tools/check-links-to-precice.sh + types_or: ["markdown", "html"] diff --git a/CHANGELOG.md b/CHANGELOG.md index b886f1ba1..7e257ba1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,112 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). -## [Unreleased] +## [v202404.0] 2024-04-16 + +### Added + +New tutorials: + +- Added new multi-scale tutorial [two-scale heat conduction](https://precice.org/tutorials-two-scale-heat-conduction.html) with Nutils [#343](https://github.com/precice/tutorials/pull/343) and DuMuX [#376](https://github.com/precice/tutorials/pull/376), using the new [Micro Manager](https://precice.org/tooling-micro-manager-overview.html). +- Added new [flow around controlled moving cylinder](https://precice.org/tutorials-flow-around-controlled-moving-cylinder.html) tutorial, using the new [FMI runner](https://precice.org/tooling-fmi-runner.html) [#474](https://github.com/precice/tutorials/pull/474). +- Added new two-phase FSI tutorial [breaking dam with flexible pillar 2D](https://precice.org/tutorials-breaking-dam-2d.html) with OpenFOAM (interFoam) and CalculiX [#279](https://github.com/precice/tutorials/pull/279). +- Added new flow coupling tutorials [#326](https://github.com/precice/tutorials/pull/326): + - [Partitioned flow over a backwards-facing step](https://precice.org/tutorials-partitioned-backwards-facing-step.html) + - [Partitioned flow over a heated plate](https://precice.org/tutorials-flow-over-heated-plate-partitioned-flow.html) + - [Partitioned pipe: two-phase](https://precice.org/tutorials-partitioned-pipe-two-phase.html) ([#418](https://github.com/precice/tutorials/pull/418)) +- Added new volume coupling cases/tutorials with OpenFOAM: + - Added an OpenFOAM case in the [channel transport](https://precice.org/tutorials-channel-transport.html) tutorial [#315](https://github.com/precice/tutorials/pull/315). + - Added a new tutorial [volume-coupled flow](https://precice.org/tutorials-volume-coupled-flow.html) [#350](https://github.com/precice/tutorials/pull/350). +- Added overlapping Schwarz (Dirichlet-Dirichlet coupling) variants for the [oscillator](https://precice.org/tutorials-oscillator-overlap.html) [#391](https://github.com/precice/tutorials/pull/391) and for the [partitioned heat conduction](https://precice.org/tutorials-partitioned-heat-conduction-overlap.html) tutorials. + +New solver options in existing tutorials: + +- Added FMU participant options for the [oscillator](https://precice.org/tutorials-oscillator.html) tutorial [#466](https://github.com/precice/tutorials/pull/466). +- Added an SU2 case in the [flow over a heated plate](https://precice.org/tutorials-flow-over-heated-plate.html) tutorial [da7a149](https://github.com/precice/tutorials/commit/da7a1494f5c36b4ef509daf2a43bfee42fb32d9d). +- Added new solver options in the [perpendicular flap](https://precice.org/tutorials-perpendicular-flap.html) tutorial: + - `solid-nutils` [#433](https://github.com/precice/tutorials/pull/433) + - `fluid-fake` [#472](https://github.com/precice/tutorials/pull/472), only meant for debugging of solid participants +- Added a Rust-based solver in the [elastic tube 1D](https://precice.org/tutorials-elastic-tube-1d.html) tutorial [#435](https://github.com/precice/tutorials/pull/435). + +General and documentation-related changes: + +- Added automatic logging in the run scripts [#479](https://github.com/precice/tutorials/pull/479). +- Added a `.gitignore` and extended the clean-up scripts [#477](https://github.com/precice/tutorials/pull/477). +- Added visualizations of the preCICE configuration file in every tutorial [#514](https://github.com/precice/tutorials/pull/514). +- Added a list of exact Debian package links in the [quickstart](https://precice.org/quickstart.html) tutorial, to reduce cases of users installing the wrong package for their system. Now referring users to releases instead of the master branches of the Git repositories. + +Developer-facing changes: + +- Added on-demand system regression tests (multiple pull requests, starting from [#347](https://github.com/precice/tutorials/pull/347)). +- Added reference results, in the context of the system regression tests, hosted in an external Git LFS server [#419](https://github.com/precice/tutorials/pull/419). +- Added a pre-commit hook for preCICE configuration file formatting, and more [1d22c1](https://github.com/precice/tutorials/commit/1d22c1f61d7b13624973408c4bda7031b69adb5b), [#478](https://github.com/precice/tutorials/pull/478). + +### Changed + +General updates: + +- Updated all example codes and configuration files to preCICE v3 (see the [porting guide](https://precice.org/couple-your-code-porting-v2-3.html)). preCICE v2 is not supported anymore. This has happened in various pull requests. +- Updated the SU2 configuration in the [perpendicular flap](https://precice.org/tutorials-perpendicular-flap.html) tutorial, for the updated SU2 adapter [da7a149](https://github.com/precice/tutorials/commit/da7a1494f5c36b4ef509daf2a43bfee42fb32d9d). +- Updated the suggested OpenFOAM version in the [Quickstart](https://precice.org/quickstart.html) to OpenFOAM v2312. +- Updated the documentation images for several tutorials, including [perpendicular flap](https://precice.org/tutorials-perpendicular-flap.html) ([#507](https://github.com/precice/tutorials/pull/507), now including reference watchpoint files), [heat exchanger: simplified](https://precice.org/tutorials-heat-exchanger-simplified.html) ([#327](https://github.com/precice/tutorials/pull/327) and [#513](https://github.com/precice/tutorials/pull/513)), [elastic tube 3d](https://precice.org/tutorials-elastic-tube-3d.html) ([#509](https://github.com/precice/tutorials/pull/509)), [multiple perpendicular flaps](https://precice.org/tutorials-multiple-perpendicular-flaps.html) ([#511](https://github.com/precice/tutorials/pull/511)), and more. + +Restructured: + +- Modified the following cases to fit the directory structure defined in the now extended [contributing guidelines](https://precice.org/community-contribute-to-precice.html#contributing-tutorials) ([#461](https://github.com/precice/tutorials/issues/461)): + - [Oscillator](https://precice.org/tutorials-oscillator.html) + - [Partitioned heat conduction](https://precice.org/tutorials-partitioned-heat-conduction.html) + - [Partitioned heat condiction: Complex](https://precice.org/tutorials-partitioned-heat-conduction-complex.html) + - [Partitioned heat condiction: Direct mesh access](https://precice.org/tutorials-partitioned-heat-conduction-direct.html) + - [Volume-coupled diffusion](https://precice.org/tutorials-volume-coupled-diffusion.html) + +Dependency and workflow updates: + +- Modified the [Turek-Hron FSI3](https://precice.org/tutorials-turek-hron-fsi3.html) and the [partitioned heat conduction](https://precice.org/tutorials-partitioned-heat-conduction.html) OpenFOAM cases to compute the parabolic inlet profiles using a coded boundary condition, dropping the dependency on groovyBC / swak4Foam [#428](https://github.com/precice/tutorials/pull/428) (added via [a688fa](https://github.com/precice/tutorials/commit/a688fa7db044efbb72ddab7dc0bece522a5ff1e5)). +- Modified the run scripts so that Nutils is now installed automatically in a virtual environment in all related tutorials [#439](https://github.com/precice/tutorials/pull/439). Similarly for DUNE-FEM [#470](https://github.com/precice/tutorials/pull/470). +- Modified the run scripts so that C++ solvers in the elastic-tube-1d tutorial are now built automatically [#330](https://github.com/precice/tutorials/pull/330). + +Improvements and bug fixes: + +- Modified all [partitioned heat conduction](https://precice.org/tutorials-partitioned-heat-conduction.html) tutorials (including the basic, complex, and direct mesh access variants): + - Modified the configuration file to use the waveform iteration (time interpolation) feature [#281](https://github.com/precice/tutorials/pull/281). + - Modified the preCICE configuration to use a (simpler) nearest-neighbor mapping [#382](https://github.com/precice/tutorials/pull/382). + - Modified all cases and solvers to use the same value of `beta` from 1.3 to 1.2 [#379](https://github.com/precice/tutorials/pull/379). + - Modified the FEniCS solvers to apply boundary conditions at the right time [#383](https://github.com/precice/tutorials/pull/383). + - Modified the FEniCS solver of the basic case to use higher-order implicit Runge-Kutta methods [#415](https://github.com/precice/tutorials/pull/415). + - Modified the OpenFOAM solver to output error estimations [#449](https://github.com/precice/tutorials/pull/449). +- Modified the [partitioned pipe](https://precice.org/tutorials-partitioned-pipe.html) tutorial: + - Modified the OpenFOAM cases to use the new custom boundary conditions [#326](https://github.com/precice/tutorials/pull/326). + - Removed the unused `PressureGradient` and `VelocityGradient` coupling data [#384](https://github.com/precice/tutorials/pull/384). +- Modified the [oscillator](https://precice.org/tutorials-oscillator.html) tutorial to use higher-order time stepping schemes. +- Modified the [elastic tube 1d](https://precice.org/tutorials-elastic-tube-1d.html) tutorial to export and plot watchpoints [#438](https://github.com/precice/tutorials/pull/438). +- Modified the configuration of the [flow over a heated plate: two meshes](https://precice.org/tutorials-flow-over-heated-plate-two-meshes.html) tutorial: + - The CalculiX domain now has the same thickness as the OpenFOAM domain [#487](https://github.com/precice/tutorials/pull/487). + - Removed an unused mesh [#390](https://github.com/precice/tutorials/pull/390). + +## [v202211.0] 2022-11-21 + +### Added + +- Added an [ASTE tutorial](https://precice.org/tutorials-aste-turbine.html) [#244](https://github.com/precice/tutorials/pull/244). +- Added an [oscillator tutorial](https://precice.org/tutorials-oscillator.html) with Python [#297](https://github.com/precice/tutorials/pull/297). +- Added a uni-directional volume-coupled [channel transport tutorial](https://precice.org/tutorials-channel-transport.html) [#269](https://github.com/precice/tutorials/pull/269). +- Added a volume-coupled [channel transport with chemical reactions tutorial](https://precice.org/tutorials-channel-transport-reaction.html) [#278](https://github.com/precice/tutorials/pull/278). +- Added a [partitioned heat conduction using direct mesh access tutorial](https://precice.org/tutorials-partitioned-heat-conduction-direct.html) [#299](https://github.com/precice/tutorials/pull/299). +- Added a [simplified heat exchanger tutorial](https://precice.org/tutorials-heat-exchanger-simplified.html) [#301](https://github.com/precice/tutorials/pull/301). +- Added a solid-openfoam and a solid-solids4foam case for the perpendicular-flap tutorial [#286](https://github.com/precice/tutorials/pull/286). +- Added a dune-fem case for the flow-over-heated-plate tutorial [#274](https://github.com/precice/tutorials/pull/274). +- Added a CalculiX case for the flow-over-heated-plate tutorial [#271](https://github.com/precice/tutorials/pull/271). +- Added a modal dynamic simulation option for the CalculiX case of the perpendicular-flap tutorial [#284](https://github.com/precice/tutorials/pull/284). +- Added a CI workflow to automatically update the website every time there are new documentation changes [#267](https://github.com/precice/tutorials/pull/267) +- Added a gitignore for code and binaries [#290](https://github.com/precice/tutorials/pull/290). +- Added more documentation [#264](https://github.com/precice/tutorials/pull/264), [#265](https://github.com/precice/tutorials/pull/265), [#266](https://github.com/precice/tutorials/pull/266) and fixed some typos [#285](https://github.com/precice/tutorials/pull/285). + +### Changed + +- Adapted the multiple-perpendicular-flaps tutorial to a [new naming convention](https://precice.org/community-contribute-to-precice.html#contributing-tutorials) for tutorials with multiple participants [#303](https://github.com/precice/tutorials/pull/303). +- Adapted the material properties of the FEniCS case in elastic-tube-3d to match the CalculiX case results [#259](https://github.com/precice/tutorials/issues/259). +- Adapted the solid case of the Quickstart tutorial to work with the Intel oneAPI C++ compiler [#291](https://github.com/precice/tutorials/pull/291). +- Made the Nutils case of the partitioned heat conduction tutorial compatible with Nutils versions 6 to 8 [#295](https://github.com/precice/tutorials/pull/295), [#298](https://github.com/precice/tutorials/pull/298). ## [v202202.0] 2022-02-09 diff --git a/README.md b/README.md index a80f1f0a8..f866e01ea 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,13 @@ # preCICE tutorials +> [!IMPORTANT] +> This repository is aimed for development purposes and the default branch is `develop`. If you want to use the tutorials, switch to the [`master` branch](https://github.com/precice/tutorials/tree/master) or download the latest [release](https://github.com/precice/tutorials/releases). + This repository contains ready-to-run tutorial cases for the coupling library [preCICE](https://precice.org/). The purpose of these cases is not to teach you how to use preCICE from scratch, but to serve as starting points for setting up similar simulation cases, as well as test cases. Read more on our [preCICE tutorials](https://precice.org/tutorials.html) documentation section. As a general rule, you can start each participant from inside their `/-` using `./run.sh`. Look into these short scripts and copy the parts you need for your new case. Before running again, execute the cleaning scripts you can find at each level, to clean from this point and deeper. Contributions to this repository are very welcome. Please refer to the page [Contribute to preCICE](https://precice.org/community-contribute-to-precice.html) for a few guidelines and hints to help you in this direction. + +Note that we use [Git LFS](https://git-lfs.com/) to version reference results. These will appear as seemingly empty files containing URLs if you don't have Git LFS installed (optional, mainly useful for our system tests). diff --git a/aste-turbine/.gitignore b/aste-turbine/.gitignore new file mode 100644 index 000000000..aedebb0a6 --- /dev/null +++ b/aste-turbine/.gitignore @@ -0,0 +1,2 @@ +meshes.tar.gz +meshes/ diff --git a/aste-turbine/README.md b/aste-turbine/README.md new file mode 100644 index 000000000..d875508bb --- /dev/null +++ b/aste-turbine/README.md @@ -0,0 +1,69 @@ +--- +title: ASTE (artificial solver testing environment) wind turbine blade tutorial +permalink: tutorials-aste-turbine.html +keywords: ASTE, mapping, data mapping, mapping configuration, turbine +summary: This tutorial is an example case for ASTE, where we investigate different preCICE mappings using ASTE. +--- + +{% include note.html content="Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/aste-turbine). Read how in the [tutorials introduction](https://precice.org/tutorials.html)." %} + +If you are completely new to ASTE have a look at our [ASTE documentation](https://precice.org/tooling-aste.html). This tutorial shows how to setup a mapping between two (artificial) meshes using preCICE and ASTE in parallel. The executed mapping can be investigated in terms of accuracy as well as runtime. + +## Setup + +Our example consists of a wind turbine blade geometry, which was triangulated using different refinement levels. The mesh files are stored in [this GitLab repository](https://gitlab.lrz.de/precice/precice2-ref-paper-setup) and correspond to the mesh files used for the mapping tests of our [version 2 reference paper](https://doi.org/10.12688/openreseurope.14445.1). The mesh files are automatically downloaded when the `run.sh` script is executed. In this example setup, we map the mesh `0.01.vtk` (left side of the figure) to the mesh `0.006.vtk` (right side of the figure). + +![Turbine setup](images/tutorials-aste-turbine-setup.png) + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-aste-turbine-precice-config.png) + +## Running the tutorial + +All necessary steps in order to run the mapping setup are summarized in the `run.sh` script. Have a look at the comments in the run script in order to understand what is happening. In particular, the script executes the following steps: + +1. Download the mesh files and extract them in the `meshes` directory. This step is only executed when running the script for the first time. For our example, we only use two of the downloaded meshes. The tutorial can easily be modified to employ different meshes. +2. Generate input data for our mapping problem. As described in the [ASTE documentation](https://precice.org/tooling-aste.html#precice-aste-evaluate), the python script `precice-aste-evaluate` evaluates a test function and stores the results on a mesh. Here, we select Franke's function, evaluate it on the input mesh `0.01.vtk`, and store the results on a mesh called `input_mesh.vtu`. Use `precice-aste-evaluate --list-functions` to get a complete list of available test functions and their definitions. +3. Partition meshes. We want to execute the mapping in parallel. To this end, we need to partition our mesh files so that each rank receives its own mesh file. The python script `precice-aste-partition` partitions a given mesh in a specified number of pieces (here two for the input mesh and two for the output mesh). +4. Execute the actual mapping. We start two instances of `precice-aste-run`, which is the ASTE core module interfacing with preCICE, to emulate two participants. Here, we map the data from the coarse input mesh to the fine output mesh. We store the mesh and data per rank in files `mapped/mapped...` with data called `InterpolatedData`. +5. Join scattered mesh files. The python script `precice-aste-join` joins the results into one large mesh file `result.vtu`. +6. Investigate accuracy of mapping configuration. We use `precice-aste-evaluate` again. This time, we use the `--diff` flag in order to compute the error between our test function and the mapped data. We store the difference data (`Error`) on the result mesh (`result.vtu`) as well, which allows us to visualize the error distribution, e.g., using `ParaView`. `precice-aste-evaluate` also prints several global error measures to the console: + +```bash +---[ASTE-Evaluate] INFO : Vertex count 9588 +---[ASTE-Evaluate] INFO : Relative l2 error 0.002402706834866804 +---[ASTE-Evaluate] INFO : Maximum absolute error per vertex 0.009659755828445804 +---[ASTE-Evaluate] INFO : Maximum signed error per vertex 0.00888725146042224 +---[ASTE-Evaluate] INFO : Minimum absolute error per vertex 0.0 +---[ASTE-Evaluate] INFO : Minimum signed error per vertex -0.009659755828445804 +---[ASTE-Evaluate] INFO : Median absolute error per vertex 0.0011544478395176805 +---[ASTE-Evaluate] INFO : 99th percentile of absolute error per vertex 0.007066025673252374 +---[ASTE-Evaluate] INFO : 95th percentile of absolute error per vertex 0.005206080046631978 +---[ASTE-Evaluate] INFO : 90th percentile of absolute error per vertex 0.004253350142177374 +``` + +This information is additionally stored in a JSON file `result.stats.json` for potential further processing. + +{% note %} +The error measures used here are only useful for consistent mapping configurations, i.e., `constraint="consistent"`. +{% endnote %} + +This tutorial is meant as a starting point to investigate mapping setups. The provided configuration uses a `nearest-neighbor` mapping, but there are other mapping configurations available (commented out) in the `precice-config.xml` file. Example: using the last configuration (`rbf-compact-polynomial-c6` with a dense matrix decomposition) leads to the following error measures: + +```bash +---[ASTE-Evaluate] INFO : Vertex count 3458 +---[ASTE-Evaluate] INFO : Relative l2 error 9.588343106540401e-08 +---[ASTE-Evaluate] INFO : Maximum absolute error per vertex 1.7229951972397295e-06 +---[ASTE-Evaluate] INFO : Maximum signed error per vertex 1.7229951972397295e-06 +---[ASTE-Evaluate] INFO : Minimum absolute error per vertex 3.5638159090467525e-14 +---[ASTE-Evaluate] INFO : Minimum signed error per vertex -1.6968422637542169e-06 +---[ASTE-Evaluate] INFO : Median absolute error per vertex 6.217611314696114e-09 +---[ASTE-Evaluate] INFO : 99th percentile of absolute error per vertex 3.548732313379818e-07 +---[ASTE-Evaluate] INFO : 95th percentile of absolute error per vertex 1.6012309731194814e-07 +---[ASTE-Evaluate] INFO : 90th percentile of absolute error per vertex 8.077894064206796e-08 +``` + +which are clearly better than the ones we got with `nearest-neighbor` mapping above. However, this comes at the cost of a much higher runtime (). diff --git a/aste-turbine/clean-tutorial.sh b/aste-turbine/clean-tutorial.sh new file mode 120000 index 000000000..4713f5092 --- /dev/null +++ b/aste-turbine/clean-tutorial.sh @@ -0,0 +1 @@ +../tools/clean-tutorial-base.sh \ No newline at end of file diff --git a/aste-turbine/clean.sh b/aste-turbine/clean.sh new file mode 100755 index 000000000..a0ff47451 --- /dev/null +++ b/aste-turbine/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../tools/cleaning-tools.sh + +clean_aste . diff --git a/aste-turbine/images/tutorials-aste-turbine-precice-config.png b/aste-turbine/images/tutorials-aste-turbine-precice-config.png new file mode 100644 index 000000000..7ca705790 Binary files /dev/null and b/aste-turbine/images/tutorials-aste-turbine-precice-config.png differ diff --git a/aste-turbine/images/tutorials-aste-turbine-setup.png b/aste-turbine/images/tutorials-aste-turbine-setup.png new file mode 100644 index 000000000..42f8a51d0 Binary files /dev/null and b/aste-turbine/images/tutorials-aste-turbine-setup.png differ diff --git a/aste-turbine/precice-config.xml b/aste-turbine/precice-config.xml new file mode 100644 index 000000000..a606215b7 --- /dev/null +++ b/aste-turbine/precice-config.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aste-turbine/run.sh b/aste-turbine/run.sh new file mode 100755 index 000000000..fb2ebe686 --- /dev/null +++ b/aste-turbine/run.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +set -e -x + +# This script assumes the ASTE binaries and python scripts are in $PATH or ASTE installed on your system + +# Download the meshes +test -f meshes.tar.gz || wget https://gitlab.lrz.de/precice/precice2-ref-paper-setup/-/raw/main/meshes/meshes.tar.gz + +mkdir -p meshes + +# Extract the meshes +test -f meshes/0.006.vtk -a meshes/0.01.vtk || tar -xvf meshes.tar.gz --directory meshes + +# Generate input data for the mapping problem using the predefined Franke's function function +precice-aste-evaluate -m meshes/0.01.vtk -f "franke3d" -d "Franke" -o input_mesh.vtu + +# Decompose both meshes to two procesors +# Choose resolution 0.01 mesh as coarse mesh and partition the mesh using a uniform algorithm +precice-aste-partition -m input_mesh.vtu -n 2 -o coarse_mesh --dir coarse_mesh --algorithm uniform +# Choose resolution 0.006 mesh as coarse mesh and partition the mesh using a meshfree algorithm +precice-aste-partition -m meshes/0.006.vtk -n 2 -o fine_mesh --dir fine_mesh --algorithm meshfree + +# Create results directory of precice-aste-run +mkdir -p mapped + +# Map from coarse mesh to fine mesh, start two ASTE instances, one for each participant +mpirun -n 2 precice-aste-run -p A --mesh coarse_mesh/coarse_mesh --data "Franke" & +mpirun -n 2 precice-aste-run -p B --mesh fine_mesh/fine_mesh --output mapped/mapped --data "InterpolatedData" + +# Join the output files together to result.vtu +precice-aste-join -m mapped/mapped -o result.vtu --recovery fine_mesh/fine_mesh_recovery.json + +# Measure the difference between the original function and the mapped values +# Save into data array called Error +precice-aste-evaluate -m result.vtu -f "franke3d" -d "Error" --diffdata "InterpolatedData" --diff --stats diff --git a/breaking-dam-2d/README.md b/breaking-dam-2d/README.md new file mode 100644 index 000000000..1d5bc6f1a --- /dev/null +++ b/breaking-dam-2d/README.md @@ -0,0 +1,50 @@ +--- +title: Breaking dam with flexible pillar 2D +permalink: tutorials-breaking-dam-2d.html +keywords: FSI, OpenFOAM, CalculiX, IQN-ILS, two-phase flow, interFoam +summary: FSI simulation of a two-dimensional water column striking a flexible wall +--- + +{% note %} +Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/breaking-dam-2d). Read how in the [tutorials introduction](https://precice.org/tutorials.html). +{% endnote %} + +## Setup + +The two-dimensional breaking dam case is a free surface problem. A large column of water comes into contact with a flexible wall, causing the wall to bend and the water to flow over the wall. A no-slip boundary condition is applied at the bottom, the left, and the right boundary, and a zero pressure condition at the top boundary. The image below shows the alpha value (0 is air, 1 is water) and velocity vectors at t=0.6. + +![Breaking dam 2D physics at t=0.595](images/tutorials-breaking-dam-2d-physics.png) + +A similar, but not identical, setup is used in [1]. + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-breaking-dam-2d-precice-config.png) + +## Available solvers + +Fluid participant: + +* OpenFOAM (interFoam). In case you are using a very old OpenFOAM version, you need to adjust the solver to `interDyMFoam` in the `Fluid/system/controlDict` file. For more information, have a look at the [OpenFOAM adapter documentation](https://precice.org/adapter-openfoam-overview.html). + +Solid participant: + +* CalculiX. For more information, have a look at the [CalculiX adapter documentation](https://precice.org/adapter-calculix-overview.html). This is a modified setup of the one used in the `perpendicular-flap` tutorial. + +## Running the simulation + +You can start the simulation by running the script `./run.sh` located in each participant directory. OpenFOAM can be executed in parallel using `run.sh -parallel`. The default setting uses 4 MPI ranks. + +## Post-processing + +You can visualize the results using ParaView or `cgx` (for native CalculiX results files) as usual. See some [visualization hints for CalculiX results](https://precice.org/tutorials.html#visualizing-calculix-results). + +{% disclaimer %} +This offering is not approved or endorsed by OpenCFD Limited, producer and distributor of the OpenFOAM software via www.openfoam.com, and owner of the OPENFOAM® and OpenCFD® trade marks. +{% enddisclaimer %} + +## References + +[1] K. Davis, M. Schulte, B. Uekermann. [Enhancing Quasi-Newton Acceleration for Fluid-Structure Interaction](https://doi.org/10.3390/mca27030040). Mathematical and Computational Applications. 2022; 27(3):40 diff --git a/breaking-dam-2d/clean-tutorial.sh b/breaking-dam-2d/clean-tutorial.sh new file mode 120000 index 000000000..4713f5092 --- /dev/null +++ b/breaking-dam-2d/clean-tutorial.sh @@ -0,0 +1 @@ +../tools/clean-tutorial-base.sh \ No newline at end of file diff --git a/breaking-dam-2d/fluid-openfoam/.gitignore b/breaking-dam-2d/fluid-openfoam/.gitignore new file mode 100644 index 000000000..f761f9e2e --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/.gitignore @@ -0,0 +1 @@ +0/alpha.water diff --git a/breaking-dam-2d/fluid-openfoam/0/U b/breaking-dam-2d/fluid-openfoam/0/U new file mode 100644 index 000000000..56c3738e3 --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/0/U @@ -0,0 +1,47 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + location "0"; + object U; +} + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0 0 0); + +boundaryField +{ + inlet + { + type noSlip; + } + outlet + { + type noSlip; + } + flap + { + type movingWallVelocity; + value uniform (0 0 0); + } + upperWall + { + type pressureInletOutletVelocity; + value uniform (0 0 0); + } + lowerWall + { + type noSlip; + } + front + { + type empty; + } + back + { + type empty; + } +} + diff --git a/breaking-dam-2d/fluid-openfoam/0/alpha.water_orig b/breaking-dam-2d/fluid-openfoam/0/alpha.water_orig new file mode 100644 index 000000000..8505d55f7 --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/0/alpha.water_orig @@ -0,0 +1,51 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object alpha.water; +} + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + + inlet + { + type zeroGradient; + } + + outlet + { + type zeroGradient; + } + + flap + { + type zeroGradient; + } + + upperWall + { + type inletOutlet; + inletValue uniform 0; + value uniform 0; + } + + lowerWall + { + type zeroGradient; + } + + front + { + type empty; + } + back + { + type empty; + } +} diff --git a/breaking-dam-2d/fluid-openfoam/0/p b/breaking-dam-2d/fluid-openfoam/0/p new file mode 100644 index 000000000..5ee452764 --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/0/p @@ -0,0 +1,51 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p; +} + +dimensions [0 2 -2 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + inlet + { + type zeroGradient; + } + + outlet + { + type zeroGradient; + } + + flap + { + type zeroGradient; + } + + upperWall + { + type fixedValue; + value uniform 0; + } + + lowerWall + { + type zeroGradient; + } + + front + { + type empty; + } + + back + { + type empty; + } +} + diff --git a/breaking-dam-2d/fluid-openfoam/0/p_rgh b/breaking-dam-2d/fluid-openfoam/0/p_rgh new file mode 100644 index 000000000..0b8a069be --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/0/p_rgh @@ -0,0 +1,50 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p_rgh; +} + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + inlet + { + type zeroGradient; + } + + outlet + { + type zeroGradient; + } + + flap + { + type zeroGradient; + } + + upperWall + { + type fixedValue; + value uniform 0; + } + + lowerWall + { + type zeroGradient; + } + + front + { + type empty; + } + + back + { + type empty; + } +} diff --git a/breaking-dam-2d/fluid-openfoam/0/phi b/breaking-dam-2d/fluid-openfoam/0/phi new file mode 100644 index 000000000..76730d183 --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/0/phi @@ -0,0 +1,48 @@ +FoamFile +{ + version 2.0; + format ascii; + class surfaceScalarField; + location "0"; + object phi; +} + +dimensions [0 3 -1 0 0 0 0]; + +internalField uniform 0; +boundaryField +{ + inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + flap + { + type calculated; + value uniform 0; + } + upperWall + { + type calculated; + value uniform 0; + } + lowerWall + { + type calculated; + value uniform 0; + } + front + { + type empty; + } + back + { + type empty; + } +} diff --git a/breaking-dam-2d/fluid-openfoam/0/pointDisplacement b/breaking-dam-2d/fluid-openfoam/0/pointDisplacement new file mode 100644 index 000000000..038eccce3 --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/0/pointDisplacement @@ -0,0 +1,55 @@ +FoamFile +{ + version 2.0; + format ascii; + class pointVectorField; + object pointDisplacement; +} + +dimensions [0 1 0 0 0 0 0]; + +internalField uniform (0 0 0); + +boundaryField +{ + inlet + { + //type fixedValue; + //value uniform (0 0 0); + type slip; + } + + outlet + { + //type fixedValue; + //value uniform (0 0 0); + type slip; + } + + flap + { + type fixedValue; + value $internalField; + } + + upperWall + { + type fixedValue; + value uniform (0 0 0); + } + + lowerWall + { + type slip; + } + + front + { + type empty; + } + + back + { + type empty; + } +} diff --git a/breaking-dam-2d/fluid-openfoam/clean.sh b/breaking-dam-2d/fluid-openfoam/clean.sh new file mode 100755 index 000000000..26ff9416d --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/clean.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . +rm -fv 0/alpha.water diff --git a/breaking-dam-2d/fluid-openfoam/constant/dynamicMeshDict b/breaking-dam-2d/fluid-openfoam/constant/dynamicMeshDict new file mode 100644 index 000000000..5c7694898 --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/constant/dynamicMeshDict @@ -0,0 +1,18 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object dynamicMeshDict; +} + +dynamicFvMesh dynamicMotionSolverFvMesh; + +motionSolverLibs ("libfvMotionSolvers.so"); + +solver displacementLaplacian; + +displacementLaplacianCoeffs { + diffusivity quadratic inverseDistance (flap); +} diff --git a/breaking-dam-2d/fluid-openfoam/constant/g b/breaking-dam-2d/fluid-openfoam/constant/g new file mode 100644 index 000000000..e02ac1cbe --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/constant/g @@ -0,0 +1,11 @@ +FoamFile +{ + version 2.0; + format ascii; + class uniformDimensionedVectorField; + location "constant"; + object g; +} + +dimensions [0 1 -2 0 0 0 0]; +value (0 -9.81 0); diff --git a/breaking-dam-2d/fluid-openfoam/constant/transportProperties b/breaking-dam-2d/fluid-openfoam/constant/transportProperties new file mode 100644 index 000000000..2f1cc1d6a --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/constant/transportProperties @@ -0,0 +1,26 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object transportProperties; +} + +phases (water air);//first entry has to correspont to file in 0 -> alpha.water + +water +{ + transportModel Newtonian; //Newtonian fluid assumed + nu [0 2 -1 0 0 0 0] 1e-06; //kinematic viscosity in m^2/s - water + rho [1 -3 0 0 0 0 0] 1000; //density - water +} + +air +{ + transportModel Newtonian; + nu [0 2 -1 0 0 0 0] 1e-05; //kinematic viscosity in m^2/s - air + rho [1 -3 0 0 0 0 0] 1; //density - air +} + +sigma [1 0 -2 0 0 0 0] 0.072; //surface tension of water/air diff --git a/breaking-dam-2d/fluid-openfoam/constant/turbulenceProperties b/breaking-dam-2d/fluid-openfoam/constant/turbulenceProperties new file mode 100644 index 000000000..2c55a8b28 --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/constant/turbulenceProperties @@ -0,0 +1,10 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object turbulenceProperties; +} + +simulationType laminar; diff --git a/breaking-dam-2d/fluid-openfoam/run.sh b/breaking-dam-2d/fluid-openfoam/run.sh new file mode 100755 index 000000000..d1c9bfbd5 --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/run.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +cp 0/alpha.water_orig 0/alpha.water +blockMesh +setFields + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/breaking-dam-2d/fluid-openfoam/system/blockMeshDict b/breaking-dam-2d/fluid-openfoam/system/blockMeshDict new file mode 100644 index 000000000..875f42294 --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/system/blockMeshDict @@ -0,0 +1,145 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +x0 -3.; +x1 -0.05; +x2 0.05; +x3 3.; + +y0 0.; +y1 1.; +y2 4.; + +z0 0; +z1 1; + +vertices +( + ($x0 $y0 $z0 ) // 0 + ($x1 $y0 $z0 ) // 1 + ($x2 $y0 $z0 ) // 2 + ($x3 $y0 $z0 ) // 3 + ($x0 $y1 $z0 ) // 4 + ($x1 $y1 $z0 ) // 5 + ($x2 $y1 $z0 ) // 6 + ($x3 $y1 $z0 ) // 7 + ($x0 $y2 $z0 ) // 8 + ($x1 $y2 $z0 ) // 9 + ($x2 $y2 $z0 ) // 10 + ($x3 $y2 $z0 ) // 11 + + ($x0 $y0 $z1 ) // 12 + ($x1 $y0 $z1 ) // 13 + ($x2 $y0 $z1 ) // 14 + ($x3 $y0 $z1 ) // 15 + ($x0 $y1 $z1 ) // 16 + ($x1 $y1 $z1 ) // 17 + ($x2 $y1 $z1 ) // 18 + ($x3 $y1 $z1 ) // 19 + ($x0 $y2 $z1 ) // 20 + ($x1 $y2 $z1 ) // 21 + ($x2 $y2 $z1 ) // 22 + ($x3 $y2 $z1 ) // 23 +); + +// Grading +h1 30; +h2 3; +v1 15; +v2 30; + +blocks +( + hex ( 0 1 5 4 12 13 17 16 ) + ($h1 $v1 1 ) + simpleGrading (0.5 1 1) + + hex ( 2 3 7 6 14 15 19 18 ) + ($h1 $v1 1) + simpleGrading (2 1 1) + + hex ( 4 5 9 8 16 17 21 20 ) + ($h1 $v2 1) + simpleGrading (0.5 2 1) + + hex ( 5 6 10 9 17 18 22 21 ) + ($h2 $v2 1) + simpleGrading (1 2 1) + + hex ( 6 7 11 10 18 19 23 22 ) + ($h1 $v2 1 ) + simpleGrading (2 2 1) +); + +boundary +( + inlet + { + type patch; + faces + ( + ( 0 4 16 12 ) + ( 4 8 20 16 ) + ); + } + outlet + { + type patch; + faces + ( + ( 3 7 19 15 ) + ( 7 11 23 19 ) + ); + } + flap + { + type wall; + faces + ( + ( 1 5 17 13 ) + ( 5 6 18 17 ) + ( 6 2 14 18 ) + ); + } + upperWall + { + type wall; + faces + ( + ( 8 9 21 20 ) + ( 9 10 22 21 ) + ( 10 11 23 22 ) + ); + } + lowerWall + { + type wall; + faces + ( + ( 0 1 13 12 ) + ( 2 3 15 14 ) + ); + } + frontAndBack + { + type empty; + faces + ( + ( 0 1 5 4 ) + ( 2 3 7 6 ) + ( 4 5 9 8 ) + ( 5 6 10 9 ) + ( 6 7 11 10 ) + ( 12 13 17 16 ) + ( 14 15 19 18 ) + ( 16 17 21 20 ) + ( 17 18 22 21 ) + ( 18 19 23 22 ) + ); + } +); diff --git a/breaking-dam-2d/fluid-openfoam/system/controlDict b/breaking-dam-2d/fluid-openfoam/system/controlDict new file mode 100644 index 000000000..a30e1f0bf --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/system/controlDict @@ -0,0 +1,53 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object controlDict; +} + +application interFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 1; + +deltaT 2e-03; + +writeControl adjustableRunTime; + +writeInterval 2e-03; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable yes; + +adjustTimeStep no; + +maxCo 2; +maxAlphaCo 1; +maxDeltaT 1; + +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + libs ("libpreciceAdapterFunctionObject.so"); + } +} diff --git a/breaking-dam-2d/fluid-openfoam/system/decomposeParDict b/breaking-dam-2d/fluid-openfoam/system/decomposeParDict new file mode 100644 index 000000000..3835af6b5 --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/system/decomposeParDict @@ -0,0 +1,34 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object decomposeParDict; +} + +numberOfSubdomains 4; + +method simple; + +simpleCoeffs +{ + n (4 1 1); + delta 0.001; +} + +hierarchicalCoeffs +{ + n (1 1 1); + delta 0.001; + order xyz; +} + +manualCoeffs +{ + dataFile ""; +} + +distributed no; + +roots ( ); diff --git a/breaking-dam-2d/fluid-openfoam/system/displacementProbe b/breaking-dam-2d/fluid-openfoam/system/displacementProbe new file mode 100644 index 000000000..8a5216fb8 --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/system/displacementProbe @@ -0,0 +1,13 @@ +#includeEtc "caseDicts/postProcessing/probes/probes.cfg" + +type probes; + +probeLocations +( + (0 1.0 0.15) +); + +fields +( + cellDisplacement +); diff --git a/breaking-dam-2d/fluid-openfoam/system/fvSchemes b/breaking-dam-2d/fluid-openfoam/system/fvSchemes new file mode 100644 index 000000000..9970c16da --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/system/fvSchemes @@ -0,0 +1,48 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} + +ddtSchemes +{ + //default Euler; + default CrankNicolson 0.9; +} + +gradSchemes +{ + default Gauss linear; + grad(U) Gauss linear; + grad(alpha) Gauss linear; +} + +divSchemes +{ + div(rhoPhi,U) Gauss linearUpwind grad(U); + div(phi,alpha) Gauss vanLeer; + div(phirb,alpha) Gauss linear; + div(phi,k) Gauss limitedLinear 1; + div(phi,B) Gauss limitedLinear 1; + div(B) Gauss linear; + div(phi,nuTilda) Gauss limitedLinear 1; + div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/breaking-dam-2d/fluid-openfoam/system/fvSolution b/breaking-dam-2d/fluid-openfoam/system/fvSolution new file mode 100644 index 000000000..f77d417ab --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/system/fvSolution @@ -0,0 +1,114 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} + +solvers +{ + "alpha.water.*" + { + nAlphaCorr 1; + nAlphaSubCycles 1; + cAlpha 1; + + MULESCorr yes; + nLimiterIter 5; + + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-8; + relTol 0; + } + + "pcorr.*" + { + solver PCG; + preconditioner + { + preconditioner GAMG; + tolerance 1e-05; + relTol 0; + smoother DICGaussSeidel; + } + tolerance 1e-05; + relTol 0; + maxIter 20; + } + + p_rgh + { + solver GAMG; + tolerance 1e-07; + relTol 0.01; + smoother DIC; + } + + p_rghFinal + { + solver PCG; + preconditioner + { + preconditioner GAMG; + tolerance 1e-07; + relTol 0; + nVcycles 2; + smoother DICGaussSeidel; + nPreSweeps 2; + } + tolerance 1e-07; + relTol 0; + maxIter 20; + } + + "(U|cellDisplacement)" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-6; + relTol 1e-4; + minIter 3; + } + + "(U|cellDisplacement)Final" + { + $U; + relTol 0; + } + + "(U|k)" + { + solver smoothSolver; + smoother GaussSeidel; + tolerance 1e-06; + relTol 0.1; + nSweeps 2; + } + + "(U|k)Final" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-08; + relTol 0; + } +} + +PIMPLE +{ + momentumPredictor no; + nOuterCorrectors 2; + nCorrectors 3; + nNonOrthogonalCorrectors 1; +} + +relaxationFactors +{ + equations + { + ".*" 1; + } +} diff --git a/breaking-dam-2d/fluid-openfoam/system/preciceDict b/breaking-dam-2d/fluid-openfoam/system/preciceDict new file mode 100644 index 000000000..92d739318 --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/system/preciceDict @@ -0,0 +1,39 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Fluid; + +modules (FSI); + +interfaces +{ + Interface1 + { + mesh Fluid-Mesh; + patches (flap); + locations faceCenters; + + readData + ( + Displacement + ); + + writeData + ( + Force + ); + }; +}; + +FSI +{ + rho rho [1 -3 0 0 0 0 0] 1; +} diff --git a/breaking-dam-2d/fluid-openfoam/system/setFieldsDict b/breaking-dam-2d/fluid-openfoam/system/setFieldsDict new file mode 100644 index 000000000..cf346ef48 --- /dev/null +++ b/breaking-dam-2d/fluid-openfoam/system/setFieldsDict @@ -0,0 +1,25 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object setFieldsDict; +} + +defaultFieldValues +( + volScalarFieldValue alpha.water 0 +); + +regions +( + boxToCell + { + box (-3.0 0 0) (-1.0 2.0 1.0); + fieldValues + ( + volScalarFieldValue alpha.water 1 + ); + } +); diff --git a/breaking-dam-2d/images/tutorials-breaking-dam-2d-physics.png b/breaking-dam-2d/images/tutorials-breaking-dam-2d-physics.png new file mode 100644 index 000000000..e2fc4a442 Binary files /dev/null and b/breaking-dam-2d/images/tutorials-breaking-dam-2d-physics.png differ diff --git a/breaking-dam-2d/images/tutorials-breaking-dam-2d-precice-config.png b/breaking-dam-2d/images/tutorials-breaking-dam-2d-precice-config.png new file mode 100644 index 000000000..189bcd57d Binary files /dev/null and b/breaking-dam-2d/images/tutorials-breaking-dam-2d-precice-config.png differ diff --git a/breaking-dam-2d/precice-config.xml b/breaking-dam-2d/precice-config.xml new file mode 100644 index 000000000..6806cda26 --- /dev/null +++ b/breaking-dam-2d/precice-config.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/breaking-dam-2d/solid-calculix/all.msh b/breaking-dam-2d/solid-calculix/all.msh new file mode 100644 index 000000000..7e196a054 --- /dev/null +++ b/breaking-dam-2d/solid-calculix/all.msh @@ -0,0 +1,984 @@ +*NODE, NSET=Nall + 1,5.000000000000e-02,0.000000000000e+00,1.000000000000e+00 + 2,0.000000000000e+00,0.000000000000e+00,1.000000000000e+00 + 3,0.000000000000e+00,8.196721311475e-03,1.000000000000e+00 + 4,5.000000000000e-02,8.196721311475e-03,1.000000000000e+00 + 5,5.000000000000e-02,0.000000000000e+00,0.000000000000e+00 + 6,0.000000000000e+00,0.000000000000e+00,0.000000000000e+00 + 7,0.000000000000e+00,8.196721311475e-03,0.000000000000e+00 + 8,5.000000000000e-02,8.196721311475e-03,0.000000000000e+00 + 9,0.000000000000e+00,1.639344262295e-02,1.000000000000e+00 + 10,5.000000000000e-02,1.639344262295e-02,1.000000000000e+00 + 11,0.000000000000e+00,1.639344262295e-02,0.000000000000e+00 + 12,5.000000000000e-02,1.639344262295e-02,0.000000000000e+00 + 13,0.000000000000e+00,2.459016393443e-02,1.000000000000e+00 + 14,5.000000000000e-02,2.459016393443e-02,1.000000000000e+00 + 15,0.000000000000e+00,2.459016393443e-02,0.000000000000e+00 + 16,5.000000000000e-02,2.459016393443e-02,0.000000000000e+00 + 17,0.000000000000e+00,3.278688524590e-02,1.000000000000e+00 + 18,5.000000000000e-02,3.278688524590e-02,1.000000000000e+00 + 19,0.000000000000e+00,3.278688524590e-02,0.000000000000e+00 + 20,5.000000000000e-02,3.278688524590e-02,0.000000000000e+00 + 21,0.000000000000e+00,4.098360655738e-02,1.000000000000e+00 + 22,5.000000000000e-02,4.098360655738e-02,1.000000000000e+00 + 23,0.000000000000e+00,4.098360655738e-02,0.000000000000e+00 + 24,5.000000000000e-02,4.098360655738e-02,0.000000000000e+00 + 25,0.000000000000e+00,4.918032786885e-02,1.000000000000e+00 + 26,5.000000000000e-02,4.918032786885e-02,1.000000000000e+00 + 27,0.000000000000e+00,4.918032786885e-02,0.000000000000e+00 + 28,5.000000000000e-02,4.918032786885e-02,0.000000000000e+00 + 29,0.000000000000e+00,5.737704918033e-02,1.000000000000e+00 + 30,5.000000000000e-02,5.737704918033e-02,1.000000000000e+00 + 31,0.000000000000e+00,5.737704918033e-02,0.000000000000e+00 + 32,5.000000000000e-02,5.737704918033e-02,0.000000000000e+00 + 33,0.000000000000e+00,6.557377049180e-02,1.000000000000e+00 + 34,5.000000000000e-02,6.557377049180e-02,1.000000000000e+00 + 35,0.000000000000e+00,6.557377049180e-02,0.000000000000e+00 + 36,5.000000000000e-02,6.557377049180e-02,0.000000000000e+00 + 37,0.000000000000e+00,7.377049180328e-02,1.000000000000e+00 + 38,5.000000000000e-02,7.377049180328e-02,1.000000000000e+00 + 39,0.000000000000e+00,7.377049180328e-02,0.000000000000e+00 + 40,5.000000000000e-02,7.377049180328e-02,0.000000000000e+00 + 41,0.000000000000e+00,8.196721311475e-02,1.000000000000e+00 + 42,5.000000000000e-02,8.196721311475e-02,1.000000000000e+00 + 43,0.000000000000e+00,8.196721311475e-02,0.000000000000e+00 + 44,5.000000000000e-02,8.196721311475e-02,0.000000000000e+00 + 45,0.000000000000e+00,9.016393442623e-02,1.000000000000e+00 + 46,5.000000000000e-02,9.016393442623e-02,1.000000000000e+00 + 47,0.000000000000e+00,9.016393442623e-02,0.000000000000e+00 + 48,5.000000000000e-02,9.016393442623e-02,0.000000000000e+00 + 49,0.000000000000e+00,9.836065573770e-02,1.000000000000e+00 + 50,5.000000000000e-02,9.836065573770e-02,1.000000000000e+00 + 51,0.000000000000e+00,9.836065573770e-02,0.000000000000e+00 + 52,5.000000000000e-02,9.836065573770e-02,0.000000000000e+00 + 53,0.000000000000e+00,1.065573770492e-01,1.000000000000e+00 + 54,5.000000000000e-02,1.065573770492e-01,1.000000000000e+00 + 55,0.000000000000e+00,1.065573770492e-01,0.000000000000e+00 + 56,5.000000000000e-02,1.065573770492e-01,0.000000000000e+00 + 57,0.000000000000e+00,1.147540983607e-01,1.000000000000e+00 + 58,5.000000000000e-02,1.147540983607e-01,1.000000000000e+00 + 59,0.000000000000e+00,1.147540983607e-01,0.000000000000e+00 + 60,5.000000000000e-02,1.147540983607e-01,0.000000000000e+00 + 61,0.000000000000e+00,1.229508196721e-01,1.000000000000e+00 + 62,5.000000000000e-02,1.229508196721e-01,1.000000000000e+00 + 63,0.000000000000e+00,1.229508196721e-01,0.000000000000e+00 + 64,5.000000000000e-02,1.229508196721e-01,0.000000000000e+00 + 65,0.000000000000e+00,1.311475409836e-01,1.000000000000e+00 + 66,5.000000000000e-02,1.311475409836e-01,1.000000000000e+00 + 67,0.000000000000e+00,1.311475409836e-01,0.000000000000e+00 + 68,5.000000000000e-02,1.311475409836e-01,0.000000000000e+00 + 69,0.000000000000e+00,1.393442622951e-01,1.000000000000e+00 + 70,5.000000000000e-02,1.393442622951e-01,1.000000000000e+00 + 71,0.000000000000e+00,1.393442622951e-01,0.000000000000e+00 + 72,5.000000000000e-02,1.393442622951e-01,0.000000000000e+00 + 73,0.000000000000e+00,1.475409836066e-01,1.000000000000e+00 + 74,5.000000000000e-02,1.475409836066e-01,1.000000000000e+00 + 75,0.000000000000e+00,1.475409836066e-01,0.000000000000e+00 + 76,5.000000000000e-02,1.475409836066e-01,0.000000000000e+00 + 77,0.000000000000e+00,1.557377049180e-01,1.000000000000e+00 + 78,5.000000000000e-02,1.557377049180e-01,1.000000000000e+00 + 79,0.000000000000e+00,1.557377049180e-01,0.000000000000e+00 + 80,5.000000000000e-02,1.557377049180e-01,0.000000000000e+00 + 81,0.000000000000e+00,1.639344262295e-01,1.000000000000e+00 + 82,5.000000000000e-02,1.639344262295e-01,1.000000000000e+00 + 83,0.000000000000e+00,1.639344262295e-01,0.000000000000e+00 + 84,5.000000000000e-02,1.639344262295e-01,0.000000000000e+00 + 85,0.000000000000e+00,1.721311475410e-01,1.000000000000e+00 + 86,5.000000000000e-02,1.721311475410e-01,1.000000000000e+00 + 87,0.000000000000e+00,1.721311475410e-01,0.000000000000e+00 + 88,5.000000000000e-02,1.721311475410e-01,0.000000000000e+00 + 89,0.000000000000e+00,1.803278688525e-01,1.000000000000e+00 + 90,5.000000000000e-02,1.803278688525e-01,1.000000000000e+00 + 91,0.000000000000e+00,1.803278688525e-01,0.000000000000e+00 + 92,5.000000000000e-02,1.803278688525e-01,0.000000000000e+00 + 93,0.000000000000e+00,1.885245901639e-01,1.000000000000e+00 + 94,5.000000000000e-02,1.885245901639e-01,1.000000000000e+00 + 95,0.000000000000e+00,1.885245901639e-01,0.000000000000e+00 + 96,5.000000000000e-02,1.885245901639e-01,0.000000000000e+00 + 97,0.000000000000e+00,1.967213114754e-01,1.000000000000e+00 + 98,5.000000000000e-02,1.967213114754e-01,1.000000000000e+00 + 99,0.000000000000e+00,1.967213114754e-01,0.000000000000e+00 + 100,5.000000000000e-02,1.967213114754e-01,0.000000000000e+00 + 101,0.000000000000e+00,2.049180327869e-01,1.000000000000e+00 + 102,5.000000000000e-02,2.049180327869e-01,1.000000000000e+00 + 103,0.000000000000e+00,2.049180327869e-01,0.000000000000e+00 + 104,5.000000000000e-02,2.049180327869e-01,0.000000000000e+00 + 105,0.000000000000e+00,2.131147540984e-01,1.000000000000e+00 + 106,5.000000000000e-02,2.131147540984e-01,1.000000000000e+00 + 107,0.000000000000e+00,2.131147540984e-01,0.000000000000e+00 + 108,5.000000000000e-02,2.131147540984e-01,0.000000000000e+00 + 109,0.000000000000e+00,2.213114754098e-01,1.000000000000e+00 + 110,5.000000000000e-02,2.213114754098e-01,1.000000000000e+00 + 111,0.000000000000e+00,2.213114754098e-01,0.000000000000e+00 + 112,5.000000000000e-02,2.213114754098e-01,0.000000000000e+00 + 113,0.000000000000e+00,2.295081967213e-01,1.000000000000e+00 + 114,5.000000000000e-02,2.295081967213e-01,1.000000000000e+00 + 115,0.000000000000e+00,2.295081967213e-01,0.000000000000e+00 + 116,5.000000000000e-02,2.295081967213e-01,0.000000000000e+00 + 117,0.000000000000e+00,2.377049180328e-01,1.000000000000e+00 + 118,5.000000000000e-02,2.377049180328e-01,1.000000000000e+00 + 119,0.000000000000e+00,2.377049180328e-01,0.000000000000e+00 + 120,5.000000000000e-02,2.377049180328e-01,0.000000000000e+00 + 121,0.000000000000e+00,2.459016393443e-01,1.000000000000e+00 + 122,5.000000000000e-02,2.459016393443e-01,1.000000000000e+00 + 123,0.000000000000e+00,2.459016393443e-01,0.000000000000e+00 + 124,5.000000000000e-02,2.459016393443e-01,0.000000000000e+00 + 125,0.000000000000e+00,2.540983606557e-01,1.000000000000e+00 + 126,5.000000000000e-02,2.540983606557e-01,1.000000000000e+00 + 127,0.000000000000e+00,2.540983606557e-01,0.000000000000e+00 + 128,5.000000000000e-02,2.540983606557e-01,0.000000000000e+00 + 129,0.000000000000e+00,2.622950819672e-01,1.000000000000e+00 + 130,5.000000000000e-02,2.622950819672e-01,1.000000000000e+00 + 131,0.000000000000e+00,2.622950819672e-01,0.000000000000e+00 + 132,5.000000000000e-02,2.622950819672e-01,0.000000000000e+00 + 133,0.000000000000e+00,2.704918032787e-01,1.000000000000e+00 + 134,5.000000000000e-02,2.704918032787e-01,1.000000000000e+00 + 135,0.000000000000e+00,2.704918032787e-01,0.000000000000e+00 + 136,5.000000000000e-02,2.704918032787e-01,0.000000000000e+00 + 137,0.000000000000e+00,2.786885245902e-01,1.000000000000e+00 + 138,5.000000000000e-02,2.786885245902e-01,1.000000000000e+00 + 139,0.000000000000e+00,2.786885245902e-01,0.000000000000e+00 + 140,5.000000000000e-02,2.786885245902e-01,0.000000000000e+00 + 141,0.000000000000e+00,2.868852459016e-01,1.000000000000e+00 + 142,5.000000000000e-02,2.868852459016e-01,1.000000000000e+00 + 143,0.000000000000e+00,2.868852459016e-01,0.000000000000e+00 + 144,5.000000000000e-02,2.868852459016e-01,0.000000000000e+00 + 145,0.000000000000e+00,2.950819672131e-01,1.000000000000e+00 + 146,5.000000000000e-02,2.950819672131e-01,1.000000000000e+00 + 147,0.000000000000e+00,2.950819672131e-01,0.000000000000e+00 + 148,5.000000000000e-02,2.950819672131e-01,0.000000000000e+00 + 149,0.000000000000e+00,3.032786885246e-01,1.000000000000e+00 + 150,5.000000000000e-02,3.032786885246e-01,1.000000000000e+00 + 151,0.000000000000e+00,3.032786885246e-01,0.000000000000e+00 + 152,5.000000000000e-02,3.032786885246e-01,0.000000000000e+00 + 153,0.000000000000e+00,3.114754098361e-01,1.000000000000e+00 + 154,5.000000000000e-02,3.114754098361e-01,1.000000000000e+00 + 155,0.000000000000e+00,3.114754098361e-01,0.000000000000e+00 + 156,5.000000000000e-02,3.114754098361e-01,0.000000000000e+00 + 157,0.000000000000e+00,3.196721311475e-01,1.000000000000e+00 + 158,5.000000000000e-02,3.196721311475e-01,1.000000000000e+00 + 159,0.000000000000e+00,3.196721311475e-01,0.000000000000e+00 + 160,5.000000000000e-02,3.196721311475e-01,0.000000000000e+00 + 161,0.000000000000e+00,3.278688524590e-01,1.000000000000e+00 + 162,5.000000000000e-02,3.278688524590e-01,1.000000000000e+00 + 163,0.000000000000e+00,3.278688524590e-01,0.000000000000e+00 + 164,5.000000000000e-02,3.278688524590e-01,0.000000000000e+00 + 165,0.000000000000e+00,3.360655737705e-01,1.000000000000e+00 + 166,5.000000000000e-02,3.360655737705e-01,1.000000000000e+00 + 167,0.000000000000e+00,3.360655737705e-01,0.000000000000e+00 + 168,5.000000000000e-02,3.360655737705e-01,0.000000000000e+00 + 169,0.000000000000e+00,3.442622950820e-01,1.000000000000e+00 + 170,5.000000000000e-02,3.442622950820e-01,1.000000000000e+00 + 171,0.000000000000e+00,3.442622950820e-01,0.000000000000e+00 + 172,5.000000000000e-02,3.442622950820e-01,0.000000000000e+00 + 173,0.000000000000e+00,3.524590163934e-01,1.000000000000e+00 + 174,5.000000000000e-02,3.524590163934e-01,1.000000000000e+00 + 175,0.000000000000e+00,3.524590163934e-01,0.000000000000e+00 + 176,5.000000000000e-02,3.524590163934e-01,0.000000000000e+00 + 177,0.000000000000e+00,3.606557377049e-01,1.000000000000e+00 + 178,5.000000000000e-02,3.606557377049e-01,1.000000000000e+00 + 179,0.000000000000e+00,3.606557377049e-01,0.000000000000e+00 + 180,5.000000000000e-02,3.606557377049e-01,0.000000000000e+00 + 181,0.000000000000e+00,3.688524590164e-01,1.000000000000e+00 + 182,5.000000000000e-02,3.688524590164e-01,1.000000000000e+00 + 183,0.000000000000e+00,3.688524590164e-01,0.000000000000e+00 + 184,5.000000000000e-02,3.688524590164e-01,0.000000000000e+00 + 185,0.000000000000e+00,3.770491803279e-01,1.000000000000e+00 + 186,5.000000000000e-02,3.770491803279e-01,1.000000000000e+00 + 187,0.000000000000e+00,3.770491803279e-01,0.000000000000e+00 + 188,5.000000000000e-02,3.770491803279e-01,0.000000000000e+00 + 189,0.000000000000e+00,3.852459016393e-01,1.000000000000e+00 + 190,5.000000000000e-02,3.852459016393e-01,1.000000000000e+00 + 191,0.000000000000e+00,3.852459016393e-01,0.000000000000e+00 + 192,5.000000000000e-02,3.852459016393e-01,0.000000000000e+00 + 193,0.000000000000e+00,3.934426229508e-01,1.000000000000e+00 + 194,5.000000000000e-02,3.934426229508e-01,1.000000000000e+00 + 195,0.000000000000e+00,3.934426229508e-01,0.000000000000e+00 + 196,5.000000000000e-02,3.934426229508e-01,0.000000000000e+00 + 197,0.000000000000e+00,4.016393442623e-01,1.000000000000e+00 + 198,5.000000000000e-02,4.016393442623e-01,1.000000000000e+00 + 199,0.000000000000e+00,4.016393442623e-01,0.000000000000e+00 + 200,5.000000000000e-02,4.016393442623e-01,0.000000000000e+00 + 201,0.000000000000e+00,4.098360655738e-01,1.000000000000e+00 + 202,5.000000000000e-02,4.098360655738e-01,1.000000000000e+00 + 203,0.000000000000e+00,4.098360655738e-01,0.000000000000e+00 + 204,5.000000000000e-02,4.098360655738e-01,0.000000000000e+00 + 205,0.000000000000e+00,4.180327868852e-01,1.000000000000e+00 + 206,5.000000000000e-02,4.180327868852e-01,1.000000000000e+00 + 207,0.000000000000e+00,4.180327868852e-01,0.000000000000e+00 + 208,5.000000000000e-02,4.180327868852e-01,0.000000000000e+00 + 209,0.000000000000e+00,4.262295081967e-01,1.000000000000e+00 + 210,5.000000000000e-02,4.262295081967e-01,1.000000000000e+00 + 211,0.000000000000e+00,4.262295081967e-01,0.000000000000e+00 + 212,5.000000000000e-02,4.262295081967e-01,0.000000000000e+00 + 213,0.000000000000e+00,4.344262295082e-01,1.000000000000e+00 + 214,5.000000000000e-02,4.344262295082e-01,1.000000000000e+00 + 215,0.000000000000e+00,4.344262295082e-01,0.000000000000e+00 + 216,5.000000000000e-02,4.344262295082e-01,0.000000000000e+00 + 217,0.000000000000e+00,4.426229508197e-01,1.000000000000e+00 + 218,5.000000000000e-02,4.426229508197e-01,1.000000000000e+00 + 219,0.000000000000e+00,4.426229508197e-01,0.000000000000e+00 + 220,5.000000000000e-02,4.426229508197e-01,0.000000000000e+00 + 221,0.000000000000e+00,4.508196721311e-01,1.000000000000e+00 + 222,5.000000000000e-02,4.508196721311e-01,1.000000000000e+00 + 223,0.000000000000e+00,4.508196721311e-01,0.000000000000e+00 + 224,5.000000000000e-02,4.508196721311e-01,0.000000000000e+00 + 225,0.000000000000e+00,4.590163934426e-01,1.000000000000e+00 + 226,5.000000000000e-02,4.590163934426e-01,1.000000000000e+00 + 227,0.000000000000e+00,4.590163934426e-01,0.000000000000e+00 + 228,5.000000000000e-02,4.590163934426e-01,0.000000000000e+00 + 229,0.000000000000e+00,4.672131147541e-01,1.000000000000e+00 + 230,5.000000000000e-02,4.672131147541e-01,1.000000000000e+00 + 231,0.000000000000e+00,4.672131147541e-01,0.000000000000e+00 + 232,5.000000000000e-02,4.672131147541e-01,0.000000000000e+00 + 233,0.000000000000e+00,4.754098360656e-01,1.000000000000e+00 + 234,5.000000000000e-02,4.754098360656e-01,1.000000000000e+00 + 235,0.000000000000e+00,4.754098360656e-01,0.000000000000e+00 + 236,5.000000000000e-02,4.754098360656e-01,0.000000000000e+00 + 237,0.000000000000e+00,4.836065573770e-01,1.000000000000e+00 + 238,5.000000000000e-02,4.836065573770e-01,1.000000000000e+00 + 239,0.000000000000e+00,4.836065573770e-01,0.000000000000e+00 + 240,5.000000000000e-02,4.836065573770e-01,0.000000000000e+00 + 241,0.000000000000e+00,4.918032786885e-01,1.000000000000e+00 + 242,5.000000000000e-02,4.918032786885e-01,1.000000000000e+00 + 243,0.000000000000e+00,4.918032786885e-01,0.000000000000e+00 + 244,5.000000000000e-02,4.918032786885e-01,0.000000000000e+00 + 245,0.000000000000e+00,5.000000000000e-01,1.000000000000e+00 + 246,5.000000000000e-02,5.000000000000e-01,1.000000000000e+00 + 247,0.000000000000e+00,5.000000000000e-01,0.000000000000e+00 + 248,5.000000000000e-02,5.000000000000e-01,0.000000000000e+00 + 249,0.000000000000e+00,5.081967213115e-01,1.000000000000e+00 + 250,5.000000000000e-02,5.081967213115e-01,1.000000000000e+00 + 251,0.000000000000e+00,5.081967213115e-01,0.000000000000e+00 + 252,5.000000000000e-02,5.081967213115e-01,0.000000000000e+00 + 253,0.000000000000e+00,5.163934426230e-01,1.000000000000e+00 + 254,5.000000000000e-02,5.163934426230e-01,1.000000000000e+00 + 255,0.000000000000e+00,5.163934426230e-01,0.000000000000e+00 + 256,5.000000000000e-02,5.163934426230e-01,0.000000000000e+00 + 257,0.000000000000e+00,5.245901639344e-01,1.000000000000e+00 + 258,5.000000000000e-02,5.245901639344e-01,1.000000000000e+00 + 259,0.000000000000e+00,5.245901639344e-01,0.000000000000e+00 + 260,5.000000000000e-02,5.245901639344e-01,0.000000000000e+00 + 261,0.000000000000e+00,5.327868852459e-01,1.000000000000e+00 + 262,5.000000000000e-02,5.327868852459e-01,1.000000000000e+00 + 263,0.000000000000e+00,5.327868852459e-01,0.000000000000e+00 + 264,5.000000000000e-02,5.327868852459e-01,0.000000000000e+00 + 265,0.000000000000e+00,5.409836065574e-01,1.000000000000e+00 + 266,5.000000000000e-02,5.409836065574e-01,1.000000000000e+00 + 267,0.000000000000e+00,5.409836065574e-01,0.000000000000e+00 + 268,5.000000000000e-02,5.409836065574e-01,0.000000000000e+00 + 269,0.000000000000e+00,5.491803278689e-01,1.000000000000e+00 + 270,5.000000000000e-02,5.491803278689e-01,1.000000000000e+00 + 271,0.000000000000e+00,5.491803278689e-01,0.000000000000e+00 + 272,5.000000000000e-02,5.491803278689e-01,0.000000000000e+00 + 273,0.000000000000e+00,5.573770491803e-01,1.000000000000e+00 + 274,5.000000000000e-02,5.573770491803e-01,1.000000000000e+00 + 275,0.000000000000e+00,5.573770491803e-01,0.000000000000e+00 + 276,5.000000000000e-02,5.573770491803e-01,0.000000000000e+00 + 277,0.000000000000e+00,5.655737704918e-01,1.000000000000e+00 + 278,5.000000000000e-02,5.655737704918e-01,1.000000000000e+00 + 279,0.000000000000e+00,5.655737704918e-01,0.000000000000e+00 + 280,5.000000000000e-02,5.655737704918e-01,0.000000000000e+00 + 281,0.000000000000e+00,5.737704918033e-01,1.000000000000e+00 + 282,5.000000000000e-02,5.737704918033e-01,1.000000000000e+00 + 283,0.000000000000e+00,5.737704918033e-01,0.000000000000e+00 + 284,5.000000000000e-02,5.737704918033e-01,0.000000000000e+00 + 285,0.000000000000e+00,5.819672131148e-01,1.000000000000e+00 + 286,5.000000000000e-02,5.819672131148e-01,1.000000000000e+00 + 287,0.000000000000e+00,5.819672131148e-01,0.000000000000e+00 + 288,5.000000000000e-02,5.819672131148e-01,0.000000000000e+00 + 289,0.000000000000e+00,5.901639344262e-01,1.000000000000e+00 + 290,5.000000000000e-02,5.901639344262e-01,1.000000000000e+00 + 291,0.000000000000e+00,5.901639344262e-01,0.000000000000e+00 + 292,5.000000000000e-02,5.901639344262e-01,0.000000000000e+00 + 293,0.000000000000e+00,5.983606557377e-01,1.000000000000e+00 + 294,5.000000000000e-02,5.983606557377e-01,1.000000000000e+00 + 295,0.000000000000e+00,5.983606557377e-01,0.000000000000e+00 + 296,5.000000000000e-02,5.983606557377e-01,0.000000000000e+00 + 297,0.000000000000e+00,6.065573770492e-01,1.000000000000e+00 + 298,5.000000000000e-02,6.065573770492e-01,1.000000000000e+00 + 299,0.000000000000e+00,6.065573770492e-01,0.000000000000e+00 + 300,5.000000000000e-02,6.065573770492e-01,0.000000000000e+00 + 301,0.000000000000e+00,6.147540983607e-01,1.000000000000e+00 + 302,5.000000000000e-02,6.147540983607e-01,1.000000000000e+00 + 303,0.000000000000e+00,6.147540983607e-01,0.000000000000e+00 + 304,5.000000000000e-02,6.147540983607e-01,0.000000000000e+00 + 305,0.000000000000e+00,6.229508196721e-01,1.000000000000e+00 + 306,5.000000000000e-02,6.229508196721e-01,1.000000000000e+00 + 307,0.000000000000e+00,6.229508196721e-01,0.000000000000e+00 + 308,5.000000000000e-02,6.229508196721e-01,0.000000000000e+00 + 309,0.000000000000e+00,6.311475409836e-01,1.000000000000e+00 + 310,5.000000000000e-02,6.311475409836e-01,1.000000000000e+00 + 311,0.000000000000e+00,6.311475409836e-01,0.000000000000e+00 + 312,5.000000000000e-02,6.311475409836e-01,0.000000000000e+00 + 313,0.000000000000e+00,6.393442622951e-01,1.000000000000e+00 + 314,5.000000000000e-02,6.393442622951e-01,1.000000000000e+00 + 315,0.000000000000e+00,6.393442622951e-01,0.000000000000e+00 + 316,5.000000000000e-02,6.393442622951e-01,0.000000000000e+00 + 317,0.000000000000e+00,6.475409836066e-01,1.000000000000e+00 + 318,5.000000000000e-02,6.475409836066e-01,1.000000000000e+00 + 319,0.000000000000e+00,6.475409836066e-01,0.000000000000e+00 + 320,5.000000000000e-02,6.475409836066e-01,0.000000000000e+00 + 321,0.000000000000e+00,6.557377049180e-01,1.000000000000e+00 + 322,5.000000000000e-02,6.557377049180e-01,1.000000000000e+00 + 323,0.000000000000e+00,6.557377049180e-01,0.000000000000e+00 + 324,5.000000000000e-02,6.557377049180e-01,0.000000000000e+00 + 325,0.000000000000e+00,6.639344262295e-01,1.000000000000e+00 + 326,5.000000000000e-02,6.639344262295e-01,1.000000000000e+00 + 327,0.000000000000e+00,6.639344262295e-01,0.000000000000e+00 + 328,5.000000000000e-02,6.639344262295e-01,0.000000000000e+00 + 329,0.000000000000e+00,6.721311475410e-01,1.000000000000e+00 + 330,5.000000000000e-02,6.721311475410e-01,1.000000000000e+00 + 331,0.000000000000e+00,6.721311475410e-01,0.000000000000e+00 + 332,5.000000000000e-02,6.721311475410e-01,0.000000000000e+00 + 333,0.000000000000e+00,6.803278688525e-01,1.000000000000e+00 + 334,5.000000000000e-02,6.803278688525e-01,1.000000000000e+00 + 335,0.000000000000e+00,6.803278688525e-01,0.000000000000e+00 + 336,5.000000000000e-02,6.803278688525e-01,0.000000000000e+00 + 337,0.000000000000e+00,6.885245901639e-01,1.000000000000e+00 + 338,5.000000000000e-02,6.885245901639e-01,1.000000000000e+00 + 339,0.000000000000e+00,6.885245901639e-01,0.000000000000e+00 + 340,5.000000000000e-02,6.885245901639e-01,0.000000000000e+00 + 341,0.000000000000e+00,6.967213114754e-01,1.000000000000e+00 + 342,5.000000000000e-02,6.967213114754e-01,1.000000000000e+00 + 343,0.000000000000e+00,6.967213114754e-01,0.000000000000e+00 + 344,5.000000000000e-02,6.967213114754e-01,0.000000000000e+00 + 345,0.000000000000e+00,7.049180327869e-01,1.000000000000e+00 + 346,5.000000000000e-02,7.049180327869e-01,1.000000000000e+00 + 347,0.000000000000e+00,7.049180327869e-01,0.000000000000e+00 + 348,5.000000000000e-02,7.049180327869e-01,0.000000000000e+00 + 349,0.000000000000e+00,7.131147540984e-01,1.000000000000e+00 + 350,5.000000000000e-02,7.131147540984e-01,1.000000000000e+00 + 351,0.000000000000e+00,7.131147540984e-01,0.000000000000e+00 + 352,5.000000000000e-02,7.131147540984e-01,0.000000000000e+00 + 353,0.000000000000e+00,7.213114754098e-01,1.000000000000e+00 + 354,5.000000000000e-02,7.213114754098e-01,1.000000000000e+00 + 355,0.000000000000e+00,7.213114754098e-01,0.000000000000e+00 + 356,5.000000000000e-02,7.213114754098e-01,0.000000000000e+00 + 357,0.000000000000e+00,7.295081967213e-01,1.000000000000e+00 + 358,5.000000000000e-02,7.295081967213e-01,1.000000000000e+00 + 359,0.000000000000e+00,7.295081967213e-01,0.000000000000e+00 + 360,5.000000000000e-02,7.295081967213e-01,0.000000000000e+00 + 361,0.000000000000e+00,7.377049180328e-01,1.000000000000e+00 + 362,5.000000000000e-02,7.377049180328e-01,1.000000000000e+00 + 363,0.000000000000e+00,7.377049180328e-01,0.000000000000e+00 + 364,5.000000000000e-02,7.377049180328e-01,0.000000000000e+00 + 365,0.000000000000e+00,7.459016393443e-01,1.000000000000e+00 + 366,5.000000000000e-02,7.459016393443e-01,1.000000000000e+00 + 367,0.000000000000e+00,7.459016393443e-01,0.000000000000e+00 + 368,5.000000000000e-02,7.459016393443e-01,0.000000000000e+00 + 369,0.000000000000e+00,7.540983606557e-01,1.000000000000e+00 + 370,5.000000000000e-02,7.540983606557e-01,1.000000000000e+00 + 371,0.000000000000e+00,7.540983606557e-01,0.000000000000e+00 + 372,5.000000000000e-02,7.540983606557e-01,0.000000000000e+00 + 373,0.000000000000e+00,7.622950819672e-01,1.000000000000e+00 + 374,5.000000000000e-02,7.622950819672e-01,1.000000000000e+00 + 375,0.000000000000e+00,7.622950819672e-01,0.000000000000e+00 + 376,5.000000000000e-02,7.622950819672e-01,0.000000000000e+00 + 377,0.000000000000e+00,7.704918032787e-01,1.000000000000e+00 + 378,5.000000000000e-02,7.704918032787e-01,1.000000000000e+00 + 379,0.000000000000e+00,7.704918032787e-01,0.000000000000e+00 + 380,5.000000000000e-02,7.704918032787e-01,0.000000000000e+00 + 381,0.000000000000e+00,7.786885245902e-01,1.000000000000e+00 + 382,5.000000000000e-02,7.786885245902e-01,1.000000000000e+00 + 383,0.000000000000e+00,7.786885245902e-01,0.000000000000e+00 + 384,5.000000000000e-02,7.786885245902e-01,0.000000000000e+00 + 385,0.000000000000e+00,7.868852459016e-01,1.000000000000e+00 + 386,5.000000000000e-02,7.868852459016e-01,1.000000000000e+00 + 387,0.000000000000e+00,7.868852459016e-01,0.000000000000e+00 + 388,5.000000000000e-02,7.868852459016e-01,0.000000000000e+00 + 389,0.000000000000e+00,7.950819672131e-01,1.000000000000e+00 + 390,5.000000000000e-02,7.950819672131e-01,1.000000000000e+00 + 391,0.000000000000e+00,7.950819672131e-01,0.000000000000e+00 + 392,5.000000000000e-02,7.950819672131e-01,0.000000000000e+00 + 393,0.000000000000e+00,8.032786885246e-01,1.000000000000e+00 + 394,5.000000000000e-02,8.032786885246e-01,1.000000000000e+00 + 395,0.000000000000e+00,8.032786885246e-01,0.000000000000e+00 + 396,5.000000000000e-02,8.032786885246e-01,0.000000000000e+00 + 397,0.000000000000e+00,8.114754098361e-01,1.000000000000e+00 + 398,5.000000000000e-02,8.114754098361e-01,1.000000000000e+00 + 399,0.000000000000e+00,8.114754098361e-01,0.000000000000e+00 + 400,5.000000000000e-02,8.114754098361e-01,0.000000000000e+00 + 401,0.000000000000e+00,8.196721311475e-01,1.000000000000e+00 + 402,5.000000000000e-02,8.196721311475e-01,1.000000000000e+00 + 403,0.000000000000e+00,8.196721311475e-01,0.000000000000e+00 + 404,5.000000000000e-02,8.196721311475e-01,0.000000000000e+00 + 405,0.000000000000e+00,8.278688524590e-01,1.000000000000e+00 + 406,5.000000000000e-02,8.278688524590e-01,1.000000000000e+00 + 407,0.000000000000e+00,8.278688524590e-01,0.000000000000e+00 + 408,5.000000000000e-02,8.278688524590e-01,0.000000000000e+00 + 409,0.000000000000e+00,8.360655737705e-01,1.000000000000e+00 + 410,5.000000000000e-02,8.360655737705e-01,1.000000000000e+00 + 411,0.000000000000e+00,8.360655737705e-01,0.000000000000e+00 + 412,5.000000000000e-02,8.360655737705e-01,0.000000000000e+00 + 413,0.000000000000e+00,8.442622950820e-01,1.000000000000e+00 + 414,5.000000000000e-02,8.442622950820e-01,1.000000000000e+00 + 415,0.000000000000e+00,8.442622950820e-01,0.000000000000e+00 + 416,5.000000000000e-02,8.442622950820e-01,0.000000000000e+00 + 417,0.000000000000e+00,8.524590163934e-01,1.000000000000e+00 + 418,5.000000000000e-02,8.524590163934e-01,1.000000000000e+00 + 419,0.000000000000e+00,8.524590163934e-01,0.000000000000e+00 + 420,5.000000000000e-02,8.524590163934e-01,0.000000000000e+00 + 421,0.000000000000e+00,8.606557377049e-01,1.000000000000e+00 + 422,5.000000000000e-02,8.606557377049e-01,1.000000000000e+00 + 423,0.000000000000e+00,8.606557377049e-01,0.000000000000e+00 + 424,5.000000000000e-02,8.606557377049e-01,0.000000000000e+00 + 425,0.000000000000e+00,8.688524590164e-01,1.000000000000e+00 + 426,5.000000000000e-02,8.688524590164e-01,1.000000000000e+00 + 427,0.000000000000e+00,8.688524590164e-01,0.000000000000e+00 + 428,5.000000000000e-02,8.688524590164e-01,0.000000000000e+00 + 429,0.000000000000e+00,8.770491803279e-01,1.000000000000e+00 + 430,5.000000000000e-02,8.770491803279e-01,1.000000000000e+00 + 431,0.000000000000e+00,8.770491803279e-01,0.000000000000e+00 + 432,5.000000000000e-02,8.770491803279e-01,0.000000000000e+00 + 433,0.000000000000e+00,8.852459016393e-01,1.000000000000e+00 + 434,5.000000000000e-02,8.852459016393e-01,1.000000000000e+00 + 435,0.000000000000e+00,8.852459016393e-01,0.000000000000e+00 + 436,5.000000000000e-02,8.852459016393e-01,0.000000000000e+00 + 437,0.000000000000e+00,8.934426229508e-01,1.000000000000e+00 + 438,5.000000000000e-02,8.934426229508e-01,1.000000000000e+00 + 439,0.000000000000e+00,8.934426229508e-01,0.000000000000e+00 + 440,5.000000000000e-02,8.934426229508e-01,0.000000000000e+00 + 441,0.000000000000e+00,9.016393442623e-01,1.000000000000e+00 + 442,5.000000000000e-02,9.016393442623e-01,1.000000000000e+00 + 443,0.000000000000e+00,9.016393442623e-01,0.000000000000e+00 + 444,5.000000000000e-02,9.016393442623e-01,0.000000000000e+00 + 445,0.000000000000e+00,9.098360655738e-01,1.000000000000e+00 + 446,5.000000000000e-02,9.098360655738e-01,1.000000000000e+00 + 447,0.000000000000e+00,9.098360655738e-01,0.000000000000e+00 + 448,5.000000000000e-02,9.098360655738e-01,0.000000000000e+00 + 449,0.000000000000e+00,9.180327868852e-01,1.000000000000e+00 + 450,5.000000000000e-02,9.180327868852e-01,1.000000000000e+00 + 451,0.000000000000e+00,9.180327868852e-01,0.000000000000e+00 + 452,5.000000000000e-02,9.180327868852e-01,0.000000000000e+00 + 453,0.000000000000e+00,9.262295081967e-01,1.000000000000e+00 + 454,5.000000000000e-02,9.262295081967e-01,1.000000000000e+00 + 455,0.000000000000e+00,9.262295081967e-01,0.000000000000e+00 + 456,5.000000000000e-02,9.262295081967e-01,0.000000000000e+00 + 457,0.000000000000e+00,9.344262295082e-01,1.000000000000e+00 + 458,5.000000000000e-02,9.344262295082e-01,1.000000000000e+00 + 459,0.000000000000e+00,9.344262295082e-01,0.000000000000e+00 + 460,5.000000000000e-02,9.344262295082e-01,0.000000000000e+00 + 461,0.000000000000e+00,9.426229508197e-01,1.000000000000e+00 + 462,5.000000000000e-02,9.426229508197e-01,1.000000000000e+00 + 463,0.000000000000e+00,9.426229508197e-01,0.000000000000e+00 + 464,5.000000000000e-02,9.426229508197e-01,0.000000000000e+00 + 465,0.000000000000e+00,9.508196721311e-01,1.000000000000e+00 + 466,5.000000000000e-02,9.508196721311e-01,1.000000000000e+00 + 467,0.000000000000e+00,9.508196721311e-01,0.000000000000e+00 + 468,5.000000000000e-02,9.508196721311e-01,0.000000000000e+00 + 469,0.000000000000e+00,9.590163934426e-01,1.000000000000e+00 + 470,5.000000000000e-02,9.590163934426e-01,1.000000000000e+00 + 471,0.000000000000e+00,9.590163934426e-01,0.000000000000e+00 + 472,5.000000000000e-02,9.590163934426e-01,0.000000000000e+00 + 473,0.000000000000e+00,9.672131147541e-01,1.000000000000e+00 + 474,5.000000000000e-02,9.672131147541e-01,1.000000000000e+00 + 475,0.000000000000e+00,9.672131147541e-01,0.000000000000e+00 + 476,5.000000000000e-02,9.672131147541e-01,0.000000000000e+00 + 477,0.000000000000e+00,9.754098360656e-01,1.000000000000e+00 + 478,5.000000000000e-02,9.754098360656e-01,1.000000000000e+00 + 479,0.000000000000e+00,9.754098360656e-01,0.000000000000e+00 + 480,5.000000000000e-02,9.754098360656e-01,0.000000000000e+00 + 481,0.000000000000e+00,9.836065573770e-01,1.000000000000e+00 + 482,5.000000000000e-02,9.836065573770e-01,1.000000000000e+00 + 483,0.000000000000e+00,9.836065573770e-01,0.000000000000e+00 + 484,5.000000000000e-02,9.836065573770e-01,0.000000000000e+00 + 485,0.000000000000e+00,9.918032786885e-01,1.000000000000e+00 + 486,5.000000000000e-02,9.918032786885e-01,1.000000000000e+00 + 487,0.000000000000e+00,9.918032786885e-01,0.000000000000e+00 + 488,5.000000000000e-02,9.918032786885e-01,0.000000000000e+00 + 489,0.000000000000e+00,1.000000000000e+00,1.000000000000e+00 + 490,5.000000000000e-02,1.000000000000e+00,1.000000000000e+00 + 491,0.000000000000e+00,1.000000000000e+00,0.000000000000e+00 + 492,5.000000000000e-02,1.000000000000e+00,0.000000000000e+00 + 493,-5.000000000000e-02,0.000000000000e+00,1.000000000000e+00 + 494,-5.000000000000e-02,8.196721311475e-03,1.000000000000e+00 + 495,-5.000000000000e-02,0.000000000000e+00,0.000000000000e+00 + 496,-5.000000000000e-02,8.196721311475e-03,0.000000000000e+00 + 497,-5.000000000000e-02,1.639344262295e-02,1.000000000000e+00 + 498,-5.000000000000e-02,1.639344262295e-02,0.000000000000e+00 + 499,-5.000000000000e-02,2.459016393443e-02,1.000000000000e+00 + 500,-5.000000000000e-02,2.459016393443e-02,0.000000000000e+00 + 501,-5.000000000000e-02,3.278688524590e-02,1.000000000000e+00 + 502,-5.000000000000e-02,3.278688524590e-02,0.000000000000e+00 + 503,-5.000000000000e-02,4.098360655738e-02,1.000000000000e+00 + 504,-5.000000000000e-02,4.098360655738e-02,0.000000000000e+00 + 505,-5.000000000000e-02,4.918032786885e-02,1.000000000000e+00 + 506,-5.000000000000e-02,4.918032786885e-02,0.000000000000e+00 + 507,-5.000000000000e-02,5.737704918033e-02,1.000000000000e+00 + 508,-5.000000000000e-02,5.737704918033e-02,0.000000000000e+00 + 509,-5.000000000000e-02,6.557377049180e-02,1.000000000000e+00 + 510,-5.000000000000e-02,6.557377049180e-02,0.000000000000e+00 + 511,-5.000000000000e-02,7.377049180328e-02,1.000000000000e+00 + 512,-5.000000000000e-02,7.377049180328e-02,0.000000000000e+00 + 513,-5.000000000000e-02,8.196721311475e-02,1.000000000000e+00 + 514,-5.000000000000e-02,8.196721311475e-02,0.000000000000e+00 + 515,-5.000000000000e-02,9.016393442623e-02,1.000000000000e+00 + 516,-5.000000000000e-02,9.016393442623e-02,0.000000000000e+00 + 517,-5.000000000000e-02,9.836065573770e-02,1.000000000000e+00 + 518,-5.000000000000e-02,9.836065573770e-02,0.000000000000e+00 + 519,-5.000000000000e-02,1.065573770492e-01,1.000000000000e+00 + 520,-5.000000000000e-02,1.065573770492e-01,0.000000000000e+00 + 521,-5.000000000000e-02,1.147540983607e-01,1.000000000000e+00 + 522,-5.000000000000e-02,1.147540983607e-01,0.000000000000e+00 + 523,-5.000000000000e-02,1.229508196721e-01,1.000000000000e+00 + 524,-5.000000000000e-02,1.229508196721e-01,0.000000000000e+00 + 525,-5.000000000000e-02,1.311475409836e-01,1.000000000000e+00 + 526,-5.000000000000e-02,1.311475409836e-01,0.000000000000e+00 + 527,-5.000000000000e-02,1.393442622951e-01,1.000000000000e+00 + 528,-5.000000000000e-02,1.393442622951e-01,0.000000000000e+00 + 529,-5.000000000000e-02,1.475409836066e-01,1.000000000000e+00 + 530,-5.000000000000e-02,1.475409836066e-01,0.000000000000e+00 + 531,-5.000000000000e-02,1.557377049180e-01,1.000000000000e+00 + 532,-5.000000000000e-02,1.557377049180e-01,0.000000000000e+00 + 533,-5.000000000000e-02,1.639344262295e-01,1.000000000000e+00 + 534,-5.000000000000e-02,1.639344262295e-01,0.000000000000e+00 + 535,-5.000000000000e-02,1.721311475410e-01,1.000000000000e+00 + 536,-5.000000000000e-02,1.721311475410e-01,0.000000000000e+00 + 537,-5.000000000000e-02,1.803278688525e-01,1.000000000000e+00 + 538,-5.000000000000e-02,1.803278688525e-01,0.000000000000e+00 + 539,-5.000000000000e-02,1.885245901639e-01,1.000000000000e+00 + 540,-5.000000000000e-02,1.885245901639e-01,0.000000000000e+00 + 541,-5.000000000000e-02,1.967213114754e-01,1.000000000000e+00 + 542,-5.000000000000e-02,1.967213114754e-01,0.000000000000e+00 + 543,-5.000000000000e-02,2.049180327869e-01,1.000000000000e+00 + 544,-5.000000000000e-02,2.049180327869e-01,0.000000000000e+00 + 545,-5.000000000000e-02,2.131147540984e-01,1.000000000000e+00 + 546,-5.000000000000e-02,2.131147540984e-01,0.000000000000e+00 + 547,-5.000000000000e-02,2.213114754098e-01,1.000000000000e+00 + 548,-5.000000000000e-02,2.213114754098e-01,0.000000000000e+00 + 549,-5.000000000000e-02,2.295081967213e-01,1.000000000000e+00 + 550,-5.000000000000e-02,2.295081967213e-01,0.000000000000e+00 + 551,-5.000000000000e-02,2.377049180328e-01,1.000000000000e+00 + 552,-5.000000000000e-02,2.377049180328e-01,0.000000000000e+00 + 553,-5.000000000000e-02,2.459016393443e-01,1.000000000000e+00 + 554,-5.000000000000e-02,2.459016393443e-01,0.000000000000e+00 + 555,-5.000000000000e-02,2.540983606557e-01,1.000000000000e+00 + 556,-5.000000000000e-02,2.540983606557e-01,0.000000000000e+00 + 557,-5.000000000000e-02,2.622950819672e-01,1.000000000000e+00 + 558,-5.000000000000e-02,2.622950819672e-01,0.000000000000e+00 + 559,-5.000000000000e-02,2.704918032787e-01,1.000000000000e+00 + 560,-5.000000000000e-02,2.704918032787e-01,0.000000000000e+00 + 561,-5.000000000000e-02,2.786885245902e-01,1.000000000000e+00 + 562,-5.000000000000e-02,2.786885245902e-01,0.000000000000e+00 + 563,-5.000000000000e-02,2.868852459016e-01,1.000000000000e+00 + 564,-5.000000000000e-02,2.868852459016e-01,0.000000000000e+00 + 565,-5.000000000000e-02,2.950819672131e-01,1.000000000000e+00 + 566,-5.000000000000e-02,2.950819672131e-01,0.000000000000e+00 + 567,-5.000000000000e-02,3.032786885246e-01,1.000000000000e+00 + 568,-5.000000000000e-02,3.032786885246e-01,0.000000000000e+00 + 569,-5.000000000000e-02,3.114754098361e-01,1.000000000000e+00 + 570,-5.000000000000e-02,3.114754098361e-01,0.000000000000e+00 + 571,-5.000000000000e-02,3.196721311475e-01,1.000000000000e+00 + 572,-5.000000000000e-02,3.196721311475e-01,0.000000000000e+00 + 573,-5.000000000000e-02,3.278688524590e-01,1.000000000000e+00 + 574,-5.000000000000e-02,3.278688524590e-01,0.000000000000e+00 + 575,-5.000000000000e-02,3.360655737705e-01,1.000000000000e+00 + 576,-5.000000000000e-02,3.360655737705e-01,0.000000000000e+00 + 577,-5.000000000000e-02,3.442622950820e-01,1.000000000000e+00 + 578,-5.000000000000e-02,3.442622950820e-01,0.000000000000e+00 + 579,-5.000000000000e-02,3.524590163934e-01,1.000000000000e+00 + 580,-5.000000000000e-02,3.524590163934e-01,0.000000000000e+00 + 581,-5.000000000000e-02,3.606557377049e-01,1.000000000000e+00 + 582,-5.000000000000e-02,3.606557377049e-01,0.000000000000e+00 + 583,-5.000000000000e-02,3.688524590164e-01,1.000000000000e+00 + 584,-5.000000000000e-02,3.688524590164e-01,0.000000000000e+00 + 585,-5.000000000000e-02,3.770491803279e-01,1.000000000000e+00 + 586,-5.000000000000e-02,3.770491803279e-01,0.000000000000e+00 + 587,-5.000000000000e-02,3.852459016393e-01,1.000000000000e+00 + 588,-5.000000000000e-02,3.852459016393e-01,0.000000000000e+00 + 589,-5.000000000000e-02,3.934426229508e-01,1.000000000000e+00 + 590,-5.000000000000e-02,3.934426229508e-01,0.000000000000e+00 + 591,-5.000000000000e-02,4.016393442623e-01,1.000000000000e+00 + 592,-5.000000000000e-02,4.016393442623e-01,0.000000000000e+00 + 593,-5.000000000000e-02,4.098360655738e-01,1.000000000000e+00 + 594,-5.000000000000e-02,4.098360655738e-01,0.000000000000e+00 + 595,-5.000000000000e-02,4.180327868852e-01,1.000000000000e+00 + 596,-5.000000000000e-02,4.180327868852e-01,0.000000000000e+00 + 597,-5.000000000000e-02,4.262295081967e-01,1.000000000000e+00 + 598,-5.000000000000e-02,4.262295081967e-01,0.000000000000e+00 + 599,-5.000000000000e-02,4.344262295082e-01,1.000000000000e+00 + 600,-5.000000000000e-02,4.344262295082e-01,0.000000000000e+00 + 601,-5.000000000000e-02,4.426229508197e-01,1.000000000000e+00 + 602,-5.000000000000e-02,4.426229508197e-01,0.000000000000e+00 + 603,-5.000000000000e-02,4.508196721311e-01,1.000000000000e+00 + 604,-5.000000000000e-02,4.508196721311e-01,0.000000000000e+00 + 605,-5.000000000000e-02,4.590163934426e-01,1.000000000000e+00 + 606,-5.000000000000e-02,4.590163934426e-01,0.000000000000e+00 + 607,-5.000000000000e-02,4.672131147541e-01,1.000000000000e+00 + 608,-5.000000000000e-02,4.672131147541e-01,0.000000000000e+00 + 609,-5.000000000000e-02,4.754098360656e-01,1.000000000000e+00 + 610,-5.000000000000e-02,4.754098360656e-01,0.000000000000e+00 + 611,-5.000000000000e-02,4.836065573770e-01,1.000000000000e+00 + 612,-5.000000000000e-02,4.836065573770e-01,0.000000000000e+00 + 613,-5.000000000000e-02,4.918032786885e-01,1.000000000000e+00 + 614,-5.000000000000e-02,4.918032786885e-01,0.000000000000e+00 + 615,-5.000000000000e-02,5.000000000000e-01,1.000000000000e+00 + 616,-5.000000000000e-02,5.000000000000e-01,0.000000000000e+00 + 617,-5.000000000000e-02,5.081967213115e-01,1.000000000000e+00 + 618,-5.000000000000e-02,5.081967213115e-01,0.000000000000e+00 + 619,-5.000000000000e-02,5.163934426230e-01,1.000000000000e+00 + 620,-5.000000000000e-02,5.163934426230e-01,0.000000000000e+00 + 621,-5.000000000000e-02,5.245901639344e-01,1.000000000000e+00 + 622,-5.000000000000e-02,5.245901639344e-01,0.000000000000e+00 + 623,-5.000000000000e-02,5.327868852459e-01,1.000000000000e+00 + 624,-5.000000000000e-02,5.327868852459e-01,0.000000000000e+00 + 625,-5.000000000000e-02,5.409836065574e-01,1.000000000000e+00 + 626,-5.000000000000e-02,5.409836065574e-01,0.000000000000e+00 + 627,-5.000000000000e-02,5.491803278689e-01,1.000000000000e+00 + 628,-5.000000000000e-02,5.491803278689e-01,0.000000000000e+00 + 629,-5.000000000000e-02,5.573770491803e-01,1.000000000000e+00 + 630,-5.000000000000e-02,5.573770491803e-01,0.000000000000e+00 + 631,-5.000000000000e-02,5.655737704918e-01,1.000000000000e+00 + 632,-5.000000000000e-02,5.655737704918e-01,0.000000000000e+00 + 633,-5.000000000000e-02,5.737704918033e-01,1.000000000000e+00 + 634,-5.000000000000e-02,5.737704918033e-01,0.000000000000e+00 + 635,-5.000000000000e-02,5.819672131148e-01,1.000000000000e+00 + 636,-5.000000000000e-02,5.819672131148e-01,0.000000000000e+00 + 637,-5.000000000000e-02,5.901639344262e-01,1.000000000000e+00 + 638,-5.000000000000e-02,5.901639344262e-01,0.000000000000e+00 + 639,-5.000000000000e-02,5.983606557377e-01,1.000000000000e+00 + 640,-5.000000000000e-02,5.983606557377e-01,0.000000000000e+00 + 641,-5.000000000000e-02,6.065573770492e-01,1.000000000000e+00 + 642,-5.000000000000e-02,6.065573770492e-01,0.000000000000e+00 + 643,-5.000000000000e-02,6.147540983607e-01,1.000000000000e+00 + 644,-5.000000000000e-02,6.147540983607e-01,0.000000000000e+00 + 645,-5.000000000000e-02,6.229508196721e-01,1.000000000000e+00 + 646,-5.000000000000e-02,6.229508196721e-01,0.000000000000e+00 + 647,-5.000000000000e-02,6.311475409836e-01,1.000000000000e+00 + 648,-5.000000000000e-02,6.311475409836e-01,0.000000000000e+00 + 649,-5.000000000000e-02,6.393442622951e-01,1.000000000000e+00 + 650,-5.000000000000e-02,6.393442622951e-01,0.000000000000e+00 + 651,-5.000000000000e-02,6.475409836066e-01,1.000000000000e+00 + 652,-5.000000000000e-02,6.475409836066e-01,0.000000000000e+00 + 653,-5.000000000000e-02,6.557377049180e-01,1.000000000000e+00 + 654,-5.000000000000e-02,6.557377049180e-01,0.000000000000e+00 + 655,-5.000000000000e-02,6.639344262295e-01,1.000000000000e+00 + 656,-5.000000000000e-02,6.639344262295e-01,0.000000000000e+00 + 657,-5.000000000000e-02,6.721311475410e-01,1.000000000000e+00 + 658,-5.000000000000e-02,6.721311475410e-01,0.000000000000e+00 + 659,-5.000000000000e-02,6.803278688525e-01,1.000000000000e+00 + 660,-5.000000000000e-02,6.803278688525e-01,0.000000000000e+00 + 661,-5.000000000000e-02,6.885245901639e-01,1.000000000000e+00 + 662,-5.000000000000e-02,6.885245901639e-01,0.000000000000e+00 + 663,-5.000000000000e-02,6.967213114754e-01,1.000000000000e+00 + 664,-5.000000000000e-02,6.967213114754e-01,0.000000000000e+00 + 665,-5.000000000000e-02,7.049180327869e-01,1.000000000000e+00 + 666,-5.000000000000e-02,7.049180327869e-01,0.000000000000e+00 + 667,-5.000000000000e-02,7.131147540984e-01,1.000000000000e+00 + 668,-5.000000000000e-02,7.131147540984e-01,0.000000000000e+00 + 669,-5.000000000000e-02,7.213114754098e-01,1.000000000000e+00 + 670,-5.000000000000e-02,7.213114754098e-01,0.000000000000e+00 + 671,-5.000000000000e-02,7.295081967213e-01,1.000000000000e+00 + 672,-5.000000000000e-02,7.295081967213e-01,0.000000000000e+00 + 673,-5.000000000000e-02,7.377049180328e-01,1.000000000000e+00 + 674,-5.000000000000e-02,7.377049180328e-01,0.000000000000e+00 + 675,-5.000000000000e-02,7.459016393443e-01,1.000000000000e+00 + 676,-5.000000000000e-02,7.459016393443e-01,0.000000000000e+00 + 677,-5.000000000000e-02,7.540983606557e-01,1.000000000000e+00 + 678,-5.000000000000e-02,7.540983606557e-01,0.000000000000e+00 + 679,-5.000000000000e-02,7.622950819672e-01,1.000000000000e+00 + 680,-5.000000000000e-02,7.622950819672e-01,0.000000000000e+00 + 681,-5.000000000000e-02,7.704918032787e-01,1.000000000000e+00 + 682,-5.000000000000e-02,7.704918032787e-01,0.000000000000e+00 + 683,-5.000000000000e-02,7.786885245902e-01,1.000000000000e+00 + 684,-5.000000000000e-02,7.786885245902e-01,0.000000000000e+00 + 685,-5.000000000000e-02,7.868852459016e-01,1.000000000000e+00 + 686,-5.000000000000e-02,7.868852459016e-01,0.000000000000e+00 + 687,-5.000000000000e-02,7.950819672131e-01,1.000000000000e+00 + 688,-5.000000000000e-02,7.950819672131e-01,0.000000000000e+00 + 689,-5.000000000000e-02,8.032786885246e-01,1.000000000000e+00 + 690,-5.000000000000e-02,8.032786885246e-01,0.000000000000e+00 + 691,-5.000000000000e-02,8.114754098361e-01,1.000000000000e+00 + 692,-5.000000000000e-02,8.114754098361e-01,0.000000000000e+00 + 693,-5.000000000000e-02,8.196721311475e-01,1.000000000000e+00 + 694,-5.000000000000e-02,8.196721311475e-01,0.000000000000e+00 + 695,-5.000000000000e-02,8.278688524590e-01,1.000000000000e+00 + 696,-5.000000000000e-02,8.278688524590e-01,0.000000000000e+00 + 697,-5.000000000000e-02,8.360655737705e-01,1.000000000000e+00 + 698,-5.000000000000e-02,8.360655737705e-01,0.000000000000e+00 + 699,-5.000000000000e-02,8.442622950820e-01,1.000000000000e+00 + 700,-5.000000000000e-02,8.442622950820e-01,0.000000000000e+00 + 701,-5.000000000000e-02,8.524590163934e-01,1.000000000000e+00 + 702,-5.000000000000e-02,8.524590163934e-01,0.000000000000e+00 + 703,-5.000000000000e-02,8.606557377049e-01,1.000000000000e+00 + 704,-5.000000000000e-02,8.606557377049e-01,0.000000000000e+00 + 705,-5.000000000000e-02,8.688524590164e-01,1.000000000000e+00 + 706,-5.000000000000e-02,8.688524590164e-01,0.000000000000e+00 + 707,-5.000000000000e-02,8.770491803279e-01,1.000000000000e+00 + 708,-5.000000000000e-02,8.770491803279e-01,0.000000000000e+00 + 709,-5.000000000000e-02,8.852459016393e-01,1.000000000000e+00 + 710,-5.000000000000e-02,8.852459016393e-01,0.000000000000e+00 + 711,-5.000000000000e-02,8.934426229508e-01,1.000000000000e+00 + 712,-5.000000000000e-02,8.934426229508e-01,0.000000000000e+00 + 713,-5.000000000000e-02,9.016393442623e-01,1.000000000000e+00 + 714,-5.000000000000e-02,9.016393442623e-01,0.000000000000e+00 + 715,-5.000000000000e-02,9.098360655738e-01,1.000000000000e+00 + 716,-5.000000000000e-02,9.098360655738e-01,0.000000000000e+00 + 717,-5.000000000000e-02,9.180327868852e-01,1.000000000000e+00 + 718,-5.000000000000e-02,9.180327868852e-01,0.000000000000e+00 + 719,-5.000000000000e-02,9.262295081967e-01,1.000000000000e+00 + 720,-5.000000000000e-02,9.262295081967e-01,0.000000000000e+00 + 721,-5.000000000000e-02,9.344262295082e-01,1.000000000000e+00 + 722,-5.000000000000e-02,9.344262295082e-01,0.000000000000e+00 + 723,-5.000000000000e-02,9.426229508197e-01,1.000000000000e+00 + 724,-5.000000000000e-02,9.426229508197e-01,0.000000000000e+00 + 725,-5.000000000000e-02,9.508196721311e-01,1.000000000000e+00 + 726,-5.000000000000e-02,9.508196721311e-01,0.000000000000e+00 + 727,-5.000000000000e-02,9.590163934426e-01,1.000000000000e+00 + 728,-5.000000000000e-02,9.590163934426e-01,0.000000000000e+00 + 729,-5.000000000000e-02,9.672131147541e-01,1.000000000000e+00 + 730,-5.000000000000e-02,9.672131147541e-01,0.000000000000e+00 + 731,-5.000000000000e-02,9.754098360656e-01,1.000000000000e+00 + 732,-5.000000000000e-02,9.754098360656e-01,0.000000000000e+00 + 733,-5.000000000000e-02,9.836065573770e-01,1.000000000000e+00 + 734,-5.000000000000e-02,9.836065573770e-01,0.000000000000e+00 + 735,-5.000000000000e-02,9.918032786885e-01,1.000000000000e+00 + 736,-5.000000000000e-02,9.918032786885e-01,0.000000000000e+00 + 737,-5.000000000000e-02,1.000000000000e+00,1.000000000000e+00 + 738,-5.000000000000e-02,1.000000000000e+00,0.000000000000e+00 +*ELEMENT, TYPE=C3D8I, ELSET=Eall + 1, 1, 2, 3, 4, 5, 6, 7, 8 + 2, 4, 3, 9, 10, 8, 7, 11, 12 + 3, 10, 9, 13, 14, 12, 11, 15, 16 + 4, 14, 13, 17, 18, 16, 15, 19, 20 + 5, 18, 17, 21, 22, 20, 19, 23, 24 + 6, 22, 21, 25, 26, 24, 23, 27, 28 + 7, 26, 25, 29, 30, 28, 27, 31, 32 + 8, 30, 29, 33, 34, 32, 31, 35, 36 + 9, 34, 33, 37, 38, 36, 35, 39, 40 + 10, 38, 37, 41, 42, 40, 39, 43, 44 + 11, 42, 41, 45, 46, 44, 43, 47, 48 + 12, 46, 45, 49, 50, 48, 47, 51, 52 + 13, 50, 49, 53, 54, 52, 51, 55, 56 + 14, 54, 53, 57, 58, 56, 55, 59, 60 + 15, 58, 57, 61, 62, 60, 59, 63, 64 + 16, 62, 61, 65, 66, 64, 63, 67, 68 + 17, 66, 65, 69, 70, 68, 67, 71, 72 + 18, 70, 69, 73, 74, 72, 71, 75, 76 + 19, 74, 73, 77, 78, 76, 75, 79, 80 + 20, 78, 77, 81, 82, 80, 79, 83, 84 + 21, 82, 81, 85, 86, 84, 83, 87, 88 + 22, 86, 85, 89, 90, 88, 87, 91, 92 + 23, 90, 89, 93, 94, 92, 91, 95, 96 + 24, 94, 93, 97, 98, 96, 95, 99, 100 + 25, 98, 97, 101, 102, 100, 99, 103, 104 + 26, 102, 101, 105, 106, 104, 103, 107, 108 + 27, 106, 105, 109, 110, 108, 107, 111, 112 + 28, 110, 109, 113, 114, 112, 111, 115, 116 + 29, 114, 113, 117, 118, 116, 115, 119, 120 + 30, 118, 117, 121, 122, 120, 119, 123, 124 + 31, 122, 121, 125, 126, 124, 123, 127, 128 + 32, 126, 125, 129, 130, 128, 127, 131, 132 + 33, 130, 129, 133, 134, 132, 131, 135, 136 + 34, 134, 133, 137, 138, 136, 135, 139, 140 + 35, 138, 137, 141, 142, 140, 139, 143, 144 + 36, 142, 141, 145, 146, 144, 143, 147, 148 + 37, 146, 145, 149, 150, 148, 147, 151, 152 + 38, 150, 149, 153, 154, 152, 151, 155, 156 + 39, 154, 153, 157, 158, 156, 155, 159, 160 + 40, 158, 157, 161, 162, 160, 159, 163, 164 + 41, 162, 161, 165, 166, 164, 163, 167, 168 + 42, 166, 165, 169, 170, 168, 167, 171, 172 + 43, 170, 169, 173, 174, 172, 171, 175, 176 + 44, 174, 173, 177, 178, 176, 175, 179, 180 + 45, 178, 177, 181, 182, 180, 179, 183, 184 + 46, 182, 181, 185, 186, 184, 183, 187, 188 + 47, 186, 185, 189, 190, 188, 187, 191, 192 + 48, 190, 189, 193, 194, 192, 191, 195, 196 + 49, 194, 193, 197, 198, 196, 195, 199, 200 + 50, 198, 197, 201, 202, 200, 199, 203, 204 + 51, 202, 201, 205, 206, 204, 203, 207, 208 + 52, 206, 205, 209, 210, 208, 207, 211, 212 + 53, 210, 209, 213, 214, 212, 211, 215, 216 + 54, 214, 213, 217, 218, 216, 215, 219, 220 + 55, 218, 217, 221, 222, 220, 219, 223, 224 + 56, 222, 221, 225, 226, 224, 223, 227, 228 + 57, 226, 225, 229, 230, 228, 227, 231, 232 + 58, 230, 229, 233, 234, 232, 231, 235, 236 + 59, 234, 233, 237, 238, 236, 235, 239, 240 + 60, 238, 237, 241, 242, 240, 239, 243, 244 + 61, 242, 241, 245, 246, 244, 243, 247, 248 + 62, 246, 245, 249, 250, 248, 247, 251, 252 + 63, 250, 249, 253, 254, 252, 251, 255, 256 + 64, 254, 253, 257, 258, 256, 255, 259, 260 + 65, 258, 257, 261, 262, 260, 259, 263, 264 + 66, 262, 261, 265, 266, 264, 263, 267, 268 + 67, 266, 265, 269, 270, 268, 267, 271, 272 + 68, 270, 269, 273, 274, 272, 271, 275, 276 + 69, 274, 273, 277, 278, 276, 275, 279, 280 + 70, 278, 277, 281, 282, 280, 279, 283, 284 + 71, 282, 281, 285, 286, 284, 283, 287, 288 + 72, 286, 285, 289, 290, 288, 287, 291, 292 + 73, 290, 289, 293, 294, 292, 291, 295, 296 + 74, 294, 293, 297, 298, 296, 295, 299, 300 + 75, 298, 297, 301, 302, 300, 299, 303, 304 + 76, 302, 301, 305, 306, 304, 303, 307, 308 + 77, 306, 305, 309, 310, 308, 307, 311, 312 + 78, 310, 309, 313, 314, 312, 311, 315, 316 + 79, 314, 313, 317, 318, 316, 315, 319, 320 + 80, 318, 317, 321, 322, 320, 319, 323, 324 + 81, 322, 321, 325, 326, 324, 323, 327, 328 + 82, 326, 325, 329, 330, 328, 327, 331, 332 + 83, 330, 329, 333, 334, 332, 331, 335, 336 + 84, 334, 333, 337, 338, 336, 335, 339, 340 + 85, 338, 337, 341, 342, 340, 339, 343, 344 + 86, 342, 341, 345, 346, 344, 343, 347, 348 + 87, 346, 345, 349, 350, 348, 347, 351, 352 + 88, 350, 349, 353, 354, 352, 351, 355, 356 + 89, 354, 353, 357, 358, 356, 355, 359, 360 + 90, 358, 357, 361, 362, 360, 359, 363, 364 + 91, 362, 361, 365, 366, 364, 363, 367, 368 + 92, 366, 365, 369, 370, 368, 367, 371, 372 + 93, 370, 369, 373, 374, 372, 371, 375, 376 + 94, 374, 373, 377, 378, 376, 375, 379, 380 + 95, 378, 377, 381, 382, 380, 379, 383, 384 + 96, 382, 381, 385, 386, 384, 383, 387, 388 + 97, 386, 385, 389, 390, 388, 387, 391, 392 + 98, 390, 389, 393, 394, 392, 391, 395, 396 + 99, 394, 393, 397, 398, 396, 395, 399, 400 + 100, 398, 397, 401, 402, 400, 399, 403, 404 + 101, 402, 401, 405, 406, 404, 403, 407, 408 + 102, 406, 405, 409, 410, 408, 407, 411, 412 + 103, 410, 409, 413, 414, 412, 411, 415, 416 + 104, 414, 413, 417, 418, 416, 415, 419, 420 + 105, 418, 417, 421, 422, 420, 419, 423, 424 + 106, 422, 421, 425, 426, 424, 423, 427, 428 + 107, 426, 425, 429, 430, 428, 427, 431, 432 + 108, 430, 429, 433, 434, 432, 431, 435, 436 + 109, 434, 433, 437, 438, 436, 435, 439, 440 + 110, 438, 437, 441, 442, 440, 439, 443, 444 + 111, 442, 441, 445, 446, 444, 443, 447, 448 + 112, 446, 445, 449, 450, 448, 447, 451, 452 + 113, 450, 449, 453, 454, 452, 451, 455, 456 + 114, 454, 453, 457, 458, 456, 455, 459, 460 + 115, 458, 457, 461, 462, 460, 459, 463, 464 + 116, 462, 461, 465, 466, 464, 463, 467, 468 + 117, 466, 465, 469, 470, 468, 467, 471, 472 + 118, 470, 469, 473, 474, 472, 471, 475, 476 + 119, 474, 473, 477, 478, 476, 475, 479, 480 + 120, 478, 477, 481, 482, 480, 479, 483, 484 + 121, 482, 481, 485, 486, 484, 483, 487, 488 + 122, 486, 485, 489, 490, 488, 487, 491, 492 + 123, 2, 493, 494, 3, 6, 495, 496, 7 + 124, 3, 494, 497, 9, 7, 496, 498, 11 + 125, 9, 497, 499, 13, 11, 498, 500, 15 + 126, 13, 499, 501, 17, 15, 500, 502, 19 + 127, 17, 501, 503, 21, 19, 502, 504, 23 + 128, 21, 503, 505, 25, 23, 504, 506, 27 + 129, 25, 505, 507, 29, 27, 506, 508, 31 + 130, 29, 507, 509, 33, 31, 508, 510, 35 + 131, 33, 509, 511, 37, 35, 510, 512, 39 + 132, 37, 511, 513, 41, 39, 512, 514, 43 + 133, 41, 513, 515, 45, 43, 514, 516, 47 + 134, 45, 515, 517, 49, 47, 516, 518, 51 + 135, 49, 517, 519, 53, 51, 518, 520, 55 + 136, 53, 519, 521, 57, 55, 520, 522, 59 + 137, 57, 521, 523, 61, 59, 522, 524, 63 + 138, 61, 523, 525, 65, 63, 524, 526, 67 + 139, 65, 525, 527, 69, 67, 526, 528, 71 + 140, 69, 527, 529, 73, 71, 528, 530, 75 + 141, 73, 529, 531, 77, 75, 530, 532, 79 + 142, 77, 531, 533, 81, 79, 532, 534, 83 + 143, 81, 533, 535, 85, 83, 534, 536, 87 + 144, 85, 535, 537, 89, 87, 536, 538, 91 + 145, 89, 537, 539, 93, 91, 538, 540, 95 + 146, 93, 539, 541, 97, 95, 540, 542, 99 + 147, 97, 541, 543, 101, 99, 542, 544, 103 + 148, 101, 543, 545, 105, 103, 544, 546, 107 + 149, 105, 545, 547, 109, 107, 546, 548, 111 + 150, 109, 547, 549, 113, 111, 548, 550, 115 + 151, 113, 549, 551, 117, 115, 550, 552, 119 + 152, 117, 551, 553, 121, 119, 552, 554, 123 + 153, 121, 553, 555, 125, 123, 554, 556, 127 + 154, 125, 555, 557, 129, 127, 556, 558, 131 + 155, 129, 557, 559, 133, 131, 558, 560, 135 + 156, 133, 559, 561, 137, 135, 560, 562, 139 + 157, 137, 561, 563, 141, 139, 562, 564, 143 + 158, 141, 563, 565, 145, 143, 564, 566, 147 + 159, 145, 565, 567, 149, 147, 566, 568, 151 + 160, 149, 567, 569, 153, 151, 568, 570, 155 + 161, 153, 569, 571, 157, 155, 570, 572, 159 + 162, 157, 571, 573, 161, 159, 572, 574, 163 + 163, 161, 573, 575, 165, 163, 574, 576, 167 + 164, 165, 575, 577, 169, 167, 576, 578, 171 + 165, 169, 577, 579, 173, 171, 578, 580, 175 + 166, 173, 579, 581, 177, 175, 580, 582, 179 + 167, 177, 581, 583, 181, 179, 582, 584, 183 + 168, 181, 583, 585, 185, 183, 584, 586, 187 + 169, 185, 585, 587, 189, 187, 586, 588, 191 + 170, 189, 587, 589, 193, 191, 588, 590, 195 + 171, 193, 589, 591, 197, 195, 590, 592, 199 + 172, 197, 591, 593, 201, 199, 592, 594, 203 + 173, 201, 593, 595, 205, 203, 594, 596, 207 + 174, 205, 595, 597, 209, 207, 596, 598, 211 + 175, 209, 597, 599, 213, 211, 598, 600, 215 + 176, 213, 599, 601, 217, 215, 600, 602, 219 + 177, 217, 601, 603, 221, 219, 602, 604, 223 + 178, 221, 603, 605, 225, 223, 604, 606, 227 + 179, 225, 605, 607, 229, 227, 606, 608, 231 + 180, 229, 607, 609, 233, 231, 608, 610, 235 + 181, 233, 609, 611, 237, 235, 610, 612, 239 + 182, 237, 611, 613, 241, 239, 612, 614, 243 + 183, 241, 613, 615, 245, 243, 614, 616, 247 + 184, 245, 615, 617, 249, 247, 616, 618, 251 + 185, 249, 617, 619, 253, 251, 618, 620, 255 + 186, 253, 619, 621, 257, 255, 620, 622, 259 + 187, 257, 621, 623, 261, 259, 622, 624, 263 + 188, 261, 623, 625, 265, 263, 624, 626, 267 + 189, 265, 625, 627, 269, 267, 626, 628, 271 + 190, 269, 627, 629, 273, 271, 628, 630, 275 + 191, 273, 629, 631, 277, 275, 630, 632, 279 + 192, 277, 631, 633, 281, 279, 632, 634, 283 + 193, 281, 633, 635, 285, 283, 634, 636, 287 + 194, 285, 635, 637, 289, 287, 636, 638, 291 + 195, 289, 637, 639, 293, 291, 638, 640, 295 + 196, 293, 639, 641, 297, 295, 640, 642, 299 + 197, 297, 641, 643, 301, 299, 642, 644, 303 + 198, 301, 643, 645, 305, 303, 644, 646, 307 + 199, 305, 645, 647, 309, 307, 646, 648, 311 + 200, 309, 647, 649, 313, 311, 648, 650, 315 + 201, 313, 649, 651, 317, 315, 650, 652, 319 + 202, 317, 651, 653, 321, 319, 652, 654, 323 + 203, 321, 653, 655, 325, 323, 654, 656, 327 + 204, 325, 655, 657, 329, 327, 656, 658, 331 + 205, 329, 657, 659, 333, 331, 658, 660, 335 + 206, 333, 659, 661, 337, 335, 660, 662, 339 + 207, 337, 661, 663, 341, 339, 662, 664, 343 + 208, 341, 663, 665, 345, 343, 664, 666, 347 + 209, 345, 665, 667, 349, 347, 666, 668, 351 + 210, 349, 667, 669, 353, 351, 668, 670, 355 + 211, 353, 669, 671, 357, 355, 670, 672, 359 + 212, 357, 671, 673, 361, 359, 672, 674, 363 + 213, 361, 673, 675, 365, 363, 674, 676, 367 + 214, 365, 675, 677, 369, 367, 676, 678, 371 + 215, 369, 677, 679, 373, 371, 678, 680, 375 + 216, 373, 679, 681, 377, 375, 680, 682, 379 + 217, 377, 681, 683, 381, 379, 682, 684, 383 + 218, 381, 683, 685, 385, 383, 684, 686, 387 + 219, 385, 685, 687, 389, 387, 686, 688, 391 + 220, 389, 687, 689, 393, 391, 688, 690, 395 + 221, 393, 689, 691, 397, 395, 690, 692, 399 + 222, 397, 691, 693, 401, 399, 692, 694, 403 + 223, 401, 693, 695, 405, 403, 694, 696, 407 + 224, 405, 695, 697, 409, 407, 696, 698, 411 + 225, 409, 697, 699, 413, 411, 698, 700, 415 + 226, 413, 699, 701, 417, 415, 700, 702, 419 + 227, 417, 701, 703, 421, 419, 702, 704, 423 + 228, 421, 703, 705, 425, 423, 704, 706, 427 + 229, 425, 705, 707, 429, 427, 706, 708, 431 + 230, 429, 707, 709, 433, 431, 708, 710, 435 + 231, 433, 709, 711, 437, 435, 710, 712, 439 + 232, 437, 711, 713, 441, 439, 712, 714, 443 + 233, 441, 713, 715, 445, 443, 714, 716, 447 + 234, 445, 715, 717, 449, 447, 716, 718, 451 + 235, 449, 717, 719, 453, 451, 718, 720, 455 + 236, 453, 719, 721, 457, 455, 720, 722, 459 + 237, 457, 721, 723, 461, 459, 722, 724, 463 + 238, 461, 723, 725, 465, 463, 724, 726, 467 + 239, 465, 725, 727, 469, 467, 726, 728, 471 + 240, 469, 727, 729, 473, 471, 728, 730, 475 + 241, 473, 729, 731, 477, 475, 730, 732, 479 + 242, 477, 731, 733, 481, 479, 732, 734, 483 + 243, 481, 733, 735, 485, 483, 734, 736, 487 + 244, 485, 735, 737, 489, 487, 736, 738, 491 diff --git a/breaking-dam-2d/solid-calculix/clean.sh b/breaking-dam-2d/solid-calculix/clean.sh new file mode 100755 index 000000000..e93f04f3c --- /dev/null +++ b/breaking-dam-2d/solid-calculix/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_calculix . diff --git a/breaking-dam-2d/solid-calculix/config.yml b/breaking-dam-2d/solid-calculix/config.yml new file mode 100644 index 000000000..fde737c49 --- /dev/null +++ b/breaking-dam-2d/solid-calculix/config.yml @@ -0,0 +1,10 @@ +participants: + + Solid: + interfaces: + - nodes-mesh: Solid-Mesh + patch: surface + read-data: [Force] + write-data: [Displacement] + +precice-config-file: ../precice-config.xml diff --git a/breaking-dam-2d/solid-calculix/fix1_beam.nam b/breaking-dam-2d/solid-calculix/fix1_beam.nam new file mode 100644 index 000000000..a56356e45 --- /dev/null +++ b/breaking-dam-2d/solid-calculix/fix1_beam.nam @@ -0,0 +1,8 @@ +** Names based on fix1 +*NSET,NSET=Nfix1 +1, +2, +5, +6, +493, +495, diff --git a/breaking-dam-2d/solid-calculix/flap.inp b/breaking-dam-2d/solid-calculix/flap.inp new file mode 100644 index 000000000..f91f54cd9 --- /dev/null +++ b/breaking-dam-2d/solid-calculix/flap.inp @@ -0,0 +1,25 @@ +*INCLUDE, INPUT=all.msh +*INCLUDE, INPUT=fix1_beam.nam +*INCLUDE, INPUT=interface_beam.nam +*MATERIAL, Name=EL +*ELASTIC + 40000000, 0.0 +*DENSITY + 3000 +*SOLID SECTION, Elset=Eall, Material=EL +*STEP, NLGEOM, INC=1000000 +*DYNAMIC, ALPHA=0.0, DIRECT +5.E-3, 10.0 +*BOUNDARY +Nfix1, 1, 3 +*BOUNDARY +Nall, 3 +*CLOAD + Nsurface, 1, 0.0 + Nsurface, 2, 0.0 + Nsurface, 3, 0.0 +*NODE FILE + U +*EL FILE + S, E +*END STEP diff --git a/breaking-dam-2d/solid-calculix/interface_beam.nam b/breaking-dam-2d/solid-calculix/interface_beam.nam new file mode 100644 index 000000000..dee1553bb --- /dev/null +++ b/breaking-dam-2d/solid-calculix/interface_beam.nam @@ -0,0 +1,496 @@ +** Names based on surface +*NSET,NSET=Nsurface +1, +4, +5, +8, +10, +12, +14, +16, +18, +20, +22, +24, +26, +28, +30, +32, +34, +36, +38, +40, +42, +44, +46, +48, +50, +52, +54, +56, +58, +60, +62, +64, +66, +68, +70, +72, +74, +76, +78, +80, +82, +84, +86, +88, +90, +92, +94, +96, +98, +100, +102, +104, +106, +108, +110, +112, +114, +116, +118, +120, +122, +124, +126, +128, +130, +132, +134, +136, +138, +140, +142, +144, +146, +148, +150, +152, +154, +156, +158, +160, +162, +164, +166, +168, +170, +172, +174, +176, +178, +180, +182, +184, +186, +188, +190, +192, +194, +196, +198, +200, +202, +204, +206, +208, +210, +212, +214, +216, +218, +220, +222, +224, +226, +228, +230, +232, +234, +236, +238, +240, +242, +244, +246, +248, +250, +252, +254, +256, +258, +260, +262, +264, +266, +268, +270, +272, +274, +276, +278, +280, +282, +284, +286, +288, +290, +292, +294, +296, +298, +300, +302, +304, +306, +308, +310, +312, +314, +316, +318, +320, +322, +324, +326, +328, +330, +332, +334, +336, +338, +340, +342, +344, +346, +348, +350, +352, +354, +356, +358, +360, +362, +364, +366, +368, +370, +372, +374, +376, +378, +380, +382, +384, +386, +388, +390, +392, +394, +396, +398, +400, +402, +404, +406, +408, +410, +412, +414, +416, +418, +420, +422, +424, +426, +428, +430, +432, +434, +436, +438, +440, +442, +444, +446, +448, +450, +452, +454, +456, +458, +460, +462, +464, +466, +468, +470, +472, +474, +476, +478, +480, +482, +484, +486, +488, +489, +490, +491, +492, +493, +494, +495, +496, +497, +498, +499, +500, +501, +502, +503, +504, +505, +506, +507, +508, +509, +510, +511, +512, +513, +514, +515, +516, +517, +518, +519, +520, +521, +522, +523, +524, +525, +526, +527, +528, +529, +530, +531, +532, +533, +534, +535, +536, +537, +538, +539, +540, +541, +542, +543, +544, +545, +546, +547, +548, +549, +550, +551, +552, +553, +554, +555, +556, +557, +558, +559, +560, +561, +562, +563, +564, +565, +566, +567, +568, +569, +570, +571, +572, +573, +574, +575, +576, +577, +578, +579, +580, +581, +582, +583, +584, +585, +586, +587, +588, +589, +590, +591, +592, +593, +594, +595, +596, +597, +598, +599, +600, +601, +602, +603, +604, +605, +606, +607, +608, +609, +610, +611, +612, +613, +614, +615, +616, +617, +618, +619, +620, +621, +622, +623, +624, +625, +626, +627, +628, +629, +630, +631, +632, +633, +634, +635, +636, +637, +638, +639, +640, +641, +642, +643, +644, +645, +646, +647, +648, +649, +650, +651, +652, +653, +654, +655, +656, +657, +658, +659, +660, +661, +662, +663, +664, +665, +666, +667, +668, +669, +670, +671, +672, +673, +674, +675, +676, +677, +678, +679, +680, +681, +682, +683, +684, +685, +686, +687, +688, +689, +690, +691, +692, +693, +694, +695, +696, +697, +698, +699, +700, +701, +702, +703, +704, +705, +706, +707, +708, +709, +710, +711, +712, +713, +714, +715, +716, +717, +718, +719, +720, +721, +722, +723, +724, +725, +726, +727, +728, +729, +730, +731, +732, +733, +734, +735, +736, +737, +738, diff --git a/breaking-dam-2d/solid-calculix/run.sh b/breaking-dam-2d/solid-calculix/run.sh new file mode 100755 index 000000000..3a9f49aae --- /dev/null +++ b/breaking-dam-2d/solid-calculix/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +ccx_preCICE -i flap -precice-participant Solid + +close_log diff --git a/channel-transport-reaction/README.md b/channel-transport-reaction/README.md new file mode 100644 index 000000000..91a46e654 --- /dev/null +++ b/channel-transport-reaction/README.md @@ -0,0 +1,59 @@ +--- +title: Channel transport reaction +permalink: tutorials-channel-transport-reaction.html +keywords: FEniCS, volumetric coupling, reaction, transport +summary: We simulate an advection-diffusion-reaction scenario in a fluid in motion. One solver simulates the fluid flow and another handles the reactions. +--- + +{% note %} +Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/channel-transport-reaction). Read how in the [tutorials introduction](https://www.precice.org/tutorials.html). +{% endnote %} + +## Setup + +We solve a system of advection-diffusion-reaction in a fluid flowing past a cylinder. This case is inspired from a FEniCS tutorial [1]. A fluid flows inside a channel containing a cylinder as an obstacle. Chemical species A, B and C live in the fluid, with sources of A and B at the entry of the channel. Due to diffusion and fluid mixing, A and B react to form a certain amount of C. + +The geometry is shown below: + +![Geometry](images/tutorials-channel-transport-reaction-geometry.png) + +The simulation is split into two participants: a Fluid participant that computes the fluid flow and sends the velocity field to the Chemical participant which computes the reaction, diffusion and advection of all chemical species. The coupling is unidirectional (`serial-explicit` with only one data entity being transferred). + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-channel-transport-reaction-precice-config.png) + +## Available solvers and dependencies + +Both participants run on FEniCS. Install [FEniCS](https://fenicsproject.org/download/) and the [FEniCS-adapter](https://github.com/precice/fenics-adapter) to run this tutorial. + +## Running the simulation + +Each participant has a `run.sh` file in its subfolder. +To start the `Fluid` participant, run: + + ```bash + cd fluid-fenics + ./run.sh + ``` + +To start the `Chemical` participant, run: + + ```bash + cd chemical-fenics + ./run.sh + ``` + +## Postprocessing + +The chemical participant writes `.vtu` and `.pvd` files that can be opened with ParaView. The fluid participant also produces output files representing the velocity field. Since the fluid time step is significantly smaller than the chemical time step, there are more fluid velocity files than chemical concentration files. Keep this in mind when opening both simultaneously. +The figure below shows the state after a duration of 2 units of time. The concentration in A, B and C are plotted. + +![Results](images/tutorials-channel-transport-reaction-state-t40.png) + +## References + + +[1] Hans Petter Langtangen and Anders Logg. Solving PDEs in Python. _Springer_ (2017). https://doi.org/10.1007/978-3-319-52462-7 diff --git a/channel-transport-reaction/chemical-fenics/chemical-reaction-advection-diffusion.json b/channel-transport-reaction/chemical-fenics/chemical-reaction-advection-diffusion.json new file mode 100644 index 000000000..b7f56e8ad --- /dev/null +++ b/channel-transport-reaction/chemical-fenics/chemical-reaction-advection-diffusion.json @@ -0,0 +1,8 @@ +{ + "participant_name": "Chemical", + "config_file_name": "../precice-config.xml", + "interface": { + "coupling_mesh_name": "Chemical-Mesh", + "read_data_name": "Velocity" + } +} diff --git a/channel-transport-reaction/chemical-fenics/chemical-reaction-advection-diffusion.py b/channel-transport-reaction/chemical-fenics/chemical-reaction-advection-diffusion.py new file mode 100644 index 000000000..1fd2e9224 --- /dev/null +++ b/channel-transport-reaction/chemical-fenics/chemical-reaction-advection-diffusion.py @@ -0,0 +1,134 @@ +from fenics import Point, FiniteElement, triangle, FunctionSpace, MixedElement, SubDomain, Function, TestFunction, split, Expression, Constant, assemble, solve, dot, grad, dx, File +from mshr import generate_mesh, Rectangle, Circle +import fenicsprecice +import numpy as np +import csv +from mpi4py import MPI +from pathlib import Path + +outfolder = Path(__file__).parent / 'output' + +default_dt = 1.0 # time step size + +domain = Rectangle(Point(0, 0), Point(2.2, 0.41)) - \ + Circle(Point(0.2, 0.2), 0.05) +mesh = generate_mesh(domain, 64) + +# Three dimensional vector for three species +P = FiniteElement('P', triangle, 1) +V = FunctionSpace(mesh, MixedElement([P, P, P])) +W = FunctionSpace(mesh, MixedElement([P, P])) # Velocity field is 2D + + +class CouplingDomain(SubDomain): + def inside(self, x, on_boundary): + return True + + +# Initialize preCICE +precice = fenicsprecice.Adapter( + adapter_config_filename=Path(__file__).parent / "chemical-reaction-advection-diffusion.json") +precice.initialize(coupling_subdomain=CouplingDomain(), read_function_space=W) +precice_dt = precice.get_max_time_step_size() + +flow_expr = precice.create_coupling_expression() + +dt = np.min([default_dt, precice_dt]) + +# Create used terms (_n suffix means "at previous step") +u_ = Function(V) +u_n = Function(V) +v = TestFunction(V) +u_1, u_2, u_3 = split(u_) +v_1, v_2, v_3 = split(v) +flow = Function(W) +flow_old = Function(W) + +# Formulate the problem + +f = Expression( + ('pow(x[0]-0.1,2)+pow(x[1]-0.1,2)<0.05*0.05 ? 0.1 : 0', + 'pow(x[0]-0.1,2)+pow(x[1]-0.3,2)<0.05*0.05 ? 0.1 : 0'), + degree=1) + +k = Constant(1. / dt) + +r = Constant(10.0) # Reaction speed +diff = Constant(0.01) # Diffusivity + + +average_flow = (flow + flow_old) / 2 + +u_n1, u_n2, u_n3 = split(u_n) + +# Weak form of the PDE. Second order terms (from diffusion) are integrated by parts. +# Integration by parts of laplacian(u) * v * dx yields dot(grad(u), normal) * v * ds - dot(grad(u), grad(v)). +# The surface terms cancels due to the boundary condition dot(grad(u), normal) = 0 (for each u_i). +# Physically speaking, this means that matter doesn't leave the domain +# through diffusion: it only leaves it from the fluid flow. + +F = k * (u_1 - u_n1) * v_1 * dx + 0.5 * dot(average_flow, + grad(u_1 + u_n1)) * v_1 * dx + diff * dot(grad(u_1), + grad(v_1)) * dx - dot(f[0], + v_1) * dx + r * u_1 * u_2 * v_1 * dx + k * (u_2 - u_n2) * v_2 * dx + 0.5 * dot(average_flow, + grad(u_2 + u_n2)) * v_2 * dx + diff * dot(grad(u_2), + grad(v_2)) * dx - dot(f[1], + v_2) * dx + r * u_1 * u_2 * v_2 * dx + k * (u_3 - u_n3) * v_3 * dx + 0.5 * dot(average_flow, + grad(u_3 + u_n3)) * v_3 * dx + diff * dot(grad(u_3), + grad(v_3)) * dx - r * u_1 * u_2 * v_3 * dx + r * u_3 * v_3 * dx + + +t = 0 +vtkfileA = File(str(outfolder / 'chemical_A.pvd')) +vtkfileB = File(str(outfolder / 'chemical_B.pvd')) +vtkfileC = File(str(outfolder / 'chemical_C.pvd')) +vtkfileFlow = File(str(outfolder / 'chemical_fluid_read.pvd')) + +# CSV file to keep track of integrals (i.e. total amount of A, B, C) +# with open(outfolder / 'chemical_out.csv', 'w', newline='') as csvfile: + +if MPI.COMM_WORLD.rank == 0: + csvfile = open(outfolder / 'chemical_out.csv', 'w', newline='') + writer = csv.writer(csvfile, delimiter=' ', quotechar='|', + quoting=csv.QUOTE_MINIMAL) + + # No implicit coupling +while precice.is_coupling_ongoing(): + + precice_dt = precice.get_max_time_step_size() + dt = np.min([default_dt, precice_dt]) + read_data = precice.read_data(dt) + precice.update_coupling_expression(flow_expr, read_data) + flow_old.assign(flow) + flow.interpolate(flow_expr) + # If we add writing, do it here + + k.assign(1. / dt) + + t += dt + print("Time {:.3g}".format(t)) + solve(F == 0, u_) + u_n.assign(u_) + + u_A, u_B, u_C = u_.split() + u_A.rename('data', 'data') + u_B.rename('data', 'data') + u_C.rename('data', 'data') + + # Compute the integrals. (All ranks must do it to synchronize) + total_A = assemble(u_A * dx) + total_B = assemble(u_B * dx) + total_C = assemble(u_C * dx) + # Only the main rank writes to the file. + if MPI.COMM_WORLD.rank == 0: + print(total_A, total_B, total_C) + writer.writerow([t, total_A, total_B, total_C]) + + vtkfileA << u_A, t + vtkfileB << u_B, t + vtkfileC << u_C, t + vtkfileFlow << flow, t + + precice.advance(dt) + +precice.finalize() diff --git a/channel-transport-reaction/chemical-fenics/clean.sh b/channel-transport-reaction/chemical-fenics/clean.sh new file mode 100755 index 000000000..614c6f928 --- /dev/null +++ b/channel-transport-reaction/chemical-fenics/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_fenics . \ No newline at end of file diff --git a/channel-transport-reaction/chemical-fenics/run.sh b/channel-transport-reaction/chemical-fenics/run.sh new file mode 100755 index 000000000..63712e999 --- /dev/null +++ b/channel-transport-reaction/chemical-fenics/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 chemical-reaction-advection-diffusion.py + +close_log diff --git a/channel-transport-reaction/clean-tutorial.sh b/channel-transport-reaction/clean-tutorial.sh new file mode 100755 index 000000000..88f60e8c6 --- /dev/null +++ b/channel-transport-reaction/clean-tutorial.sh @@ -0,0 +1,11 @@ +#!/bin/sh +set -e -u + +# shellcheck disable=SC1091 +. ../tools/cleaning-tools.sh + +clean_tutorial . +clean_precice_logs . +rm -fv ./*.log +rm -fv ./*.vtu + diff --git a/channel-transport-reaction/fluid-fenics/clean.sh b/channel-transport-reaction/fluid-fenics/clean.sh new file mode 100755 index 000000000..614c6f928 --- /dev/null +++ b/channel-transport-reaction/fluid-fenics/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_fenics . \ No newline at end of file diff --git a/channel-transport-reaction/fluid-fenics/fluid-config.json b/channel-transport-reaction/fluid-fenics/fluid-config.json new file mode 100644 index 000000000..f3a828ae3 --- /dev/null +++ b/channel-transport-reaction/fluid-fenics/fluid-config.json @@ -0,0 +1,8 @@ +{ + "participant_name": "Flow", + "config_file_name": "../precice-config.xml", + "interface": { + "coupling_mesh_name": "Flow-Mesh", + "write_data_name": "Velocity" + } +} diff --git a/channel-transport-reaction/fluid-fenics/fluid.py b/channel-transport-reaction/fluid-fenics/fluid.py new file mode 100644 index 000000000..5f2b1b598 --- /dev/null +++ b/channel-transport-reaction/fluid-fenics/fluid.py @@ -0,0 +1,162 @@ +""" +This tutorial is an adaption to preCICE of a case introduced in the FEniCS tutorial book: +"Solving PDEs in Python" by Hans Petter Langtangen and Anders Logg. +See https://fenicsproject.org/tutorial/ + +Instead of loading data to solve chemical reactions, we send the velocity field to preCICE. +""" + + +from fenics import * +from mshr import * +import fenicsprecice +import numpy as np +from pathlib import Path + +outfolder = Path(__file__).parent / 'output' + +# time step size (preCICE handles the main loop; if this is smaller than +# preCICE dt, we subcycle) +default_dt = 0.001 +mu = 0.001 # Dynamic viscosity +rho = 1 # Density + +domain = Rectangle(Point(0, 0), Point(2.2, 0.41)) - \ + Circle(Point(0.2, 0.2), 0.05) +mesh = generate_mesh(domain, 50) +normal = FacetNormal(mesh) + +# Expressions for evaluating BC +inflow = "near(x[0], 0)" +outflow = "near(x[0], 2.2)" +walls = "near(x[1], 0) || near(x[1], 0.41)" +cylinder = "on_boundary && x[0] > 0.1 && x[0] < 0.3 && x[1] > 0.1 && x[1] < 0.3" + +# Second order elements for velocity and first order for pressure +V = VectorFunctionSpace(mesh, 'P', 2) +Q = FunctionSpace(mesh, 'P', 1) + +# Define parabolic inflow profile +inflow_profile = ("4.0*1.5*x[1]*(0.41 - x[1]) / pow(0.41, 2)", "0") + +# Boundary conditions +# Imposed velocity in the outlet and free pressure at the outlet. Walls +# are not slipping +bcu_inflow = DirichletBC(V, Expression(inflow_profile, degree=2), inflow) +bcu_walls = DirichletBC(V, Constant((0, 0)), walls) +bcu_cylinder = DirichletBC(V, Constant((0, 0)), cylinder) +bcp_outflow = DirichletBC(Q, Constant(0), outflow) +bcu = [bcu_inflow, bcu_walls, bcu_cylinder] +bcp = [bcp_outflow] + + +# Define trial and test functions +u = TrialFunction(V) +v = TestFunction(V) +p = TrialFunction(Q) +q = TestFunction(Q) + +# Define functions for solutions at previous and current time steps +u_n = Function(V) +u_ = Function(V) +p_n = Function(Q) +p_ = Function(Q) + +# Define expressions used in variational forms +U = 0.5 * (u_n + u) +n = FacetNormal(mesh) +f = Constant((0, 0)) +k = Constant(default_dt) +mu = Constant(mu) +rho = Constant(rho) + +# Define symmetric gradient + + +def epsilon(u): + return sym(nabla_grad(u)) +# Define stress tensor + + +def sigma(u, p): + return 2 * mu * epsilon(u) - p * Identity(len(u)) + + +# Define variational problem for step 1 +F1 = rho * dot((u - u_n) / k, v) * dx \ + + rho * dot(dot(u_n, nabla_grad(u_n)), v) * dx \ + + inner(sigma(U, p_n), epsilon(v)) * dx \ + + dot(p_n * n, v) * ds - dot(mu * nabla_grad(U) * n, v) * ds \ + - dot(f, v) * dx +a1 = lhs(F1) +L1 = rhs(F1) + +# Define variational problem for step 2 +a2 = dot(nabla_grad(p), nabla_grad(q)) * dx +L2 = dot(nabla_grad(p_n), nabla_grad(q)) * dx - (1 / k) * div(u_) * q * dx + +# Define variational problem for step 3 +a3 = dot(u, v) * dx +L3 = dot(u_, v) * dx - k * dot(nabla_grad(p_ - p_n), v) * dx + +# Assemble matrices +A1 = assemble(a1) +A2 = assemble(a2) +A3 = assemble(a3) + +# Apply boundary conditions to matrices +[bc.apply(A1) for bc in bcu] +[bc.apply(A2) for bc in bcp] + +# Initialize preCICE + +# Coupling subdomain is the entire domain (volumetric coupling) + + +class CouplingDomain(SubDomain): + def inside(self, x, on_boundary): + return True + + +precice = fenicsprecice.Adapter(adapter_config_filename=Path(__file__).parent / "fluid-config.json") +precice.initialize(coupling_subdomain=CouplingDomain(), write_object=u_) +precice_dt = precice.get_max_time_step_size() + +dt = np.min([default_dt, precice_dt]) +k.assign(dt) + +# No implicit coupling supported, as this is uni-directional coupling +# If needed, implement checkpointing +t = 0 +vtkfile = File(str(outfolder / 'chemical_fluid_write.pvd')) + +while precice.is_coupling_ongoing(): + + # Step 1: Tentative velocity step + b1 = assemble(L1) + [bc.apply(b1) for bc in bcu] + solve(A1, u_.vector(), b1, 'bicgstab', 'hypre_amg') + # Step 2: Pressure correction step + b2 = assemble(L2) + [bc.apply(b2) for bc in bcp] + solve(A2, p_.vector(), b2, 'bicgstab', 'hypre_amg') + # Step 3: Velocity correction step + b3 = assemble(L3) + solve(A3, u_.vector(), b3, 'cg', 'sor') + + # Update previous solution + u_n.assign(u_) + p_n.assign(p_) + + precice.write_data(u_) + + t += dt + + vtkfile << u_ + + precice.advance(dt) + precice_dt = precice.get_max_time_step_size() + dt = np.min([default_dt, precice_dt]) + k.assign(dt) + +precice.finalize() diff --git a/channel-transport-reaction/fluid-fenics/run.sh b/channel-transport-reaction/fluid-fenics/run.sh new file mode 100755 index 000000000..e25136551 --- /dev/null +++ b/channel-transport-reaction/fluid-fenics/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 fluid.py + +close_log diff --git a/channel-transport-reaction/images/tutorials-channel-transport-reaction-geometry.png b/channel-transport-reaction/images/tutorials-channel-transport-reaction-geometry.png new file mode 100644 index 000000000..6a1b84739 Binary files /dev/null and b/channel-transport-reaction/images/tutorials-channel-transport-reaction-geometry.png differ 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 new file mode 100644 index 000000000..e401822ac Binary files /dev/null and b/channel-transport-reaction/images/tutorials-channel-transport-reaction-precice-config.png differ diff --git a/channel-transport-reaction/images/tutorials-channel-transport-reaction-state-t40.png b/channel-transport-reaction/images/tutorials-channel-transport-reaction-state-t40.png new file mode 100644 index 000000000..658af05a6 Binary files /dev/null and b/channel-transport-reaction/images/tutorials-channel-transport-reaction-state-t40.png differ diff --git a/channel-transport-reaction/plot.py b/channel-transport-reaction/plot.py new file mode 100644 index 000000000..fef7fdd7e --- /dev/null +++ b/channel-transport-reaction/plot.py @@ -0,0 +1,38 @@ +import pandas as pd +import matplotlib.pyplot as plt +import numpy as np + +plt.rcParams["figure.figsize"] = [7.50, 3.50] +plt.rcParams["figure.autolayout"] = True + +files = {"default": "chemistry-fenics/output/chemical_out.csv"} +datasets = {} + +headers = ['Time', 'A', 'B', 'C'] + +for key, path in files.items(): + datasets[key] = pd.read_csv(files[key], names=headers, delimiter=' ') + plt.plot(datasets[key]['Time'], datasets[key]['A'], label=key) + plt.title("Total amount of A") + plt.xlabel("Time") + plt.ylabel("Total amount") + plt.legend() + plt.show() + +for key, path in files.items(): + datasets[key] = pd.read_csv(files[key], names=headers, delimiter=' ') + plt.plot(datasets[key]['Time'], datasets[key]['B'], label=key) + plt.title("Total amount of B") + plt.xlabel("Time") + plt.ylabel("Total amount") + plt.legend() + plt.show() + +for key, path in files.items(): + datasets[key] = pd.read_csv(files[key], names=headers, delimiter=' ') + plt.plot(datasets[key]['Time'], datasets[key]['C'], label=key) + plt.title("Total amount of C") + plt.xlabel("Time") + plt.ylabel("Total amount") + plt.legend() + plt.show() diff --git a/channel-transport-reaction/precice-config.xml b/channel-transport-reaction/precice-config.xml new file mode 100644 index 000000000..8656c5006 --- /dev/null +++ b/channel-transport-reaction/precice-config.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/channel-transport/README.md b/channel-transport/README.md index 7a7d8e5ff..494f11229 100644 --- a/channel-transport/README.md +++ b/channel-transport/README.md @@ -21,13 +21,22 @@ The behavior of the blob over the full 200 timesteps looks as follows: Animation of blob over 200 timesteps. - + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-channel-transport-precice-config.png +) + ## Available solvers Fluid participant: * Nutils. For more information, have a look at the [Nutils adapter documentation](https://www.precice.org/adapter-nutils.html). This Nutils solver requires at least Nutils v7.0. +* OpenFOAM (pimpleFoam). For more information, have a look at the [OpenFOAM adapter documentation](https://precice.org/adapter-openfoam-overview.html). + Transport participant: * Nutils. For more information, have a look at the [Nutils adapter documentation](https://www.precice.org/adapter-nutils.html). This Nutils solver requires at least Nutils v7.0. diff --git a/channel-transport/fluid-nutils/fluid.py b/channel-transport/fluid-nutils/fluid.py index b6635864a..aa91605df 100644 --- a/channel-transport/fluid-nutils/fluid.py +++ b/channel-transport/fluid-nutils/fluid.py @@ -13,7 +13,7 @@ def main(): - print("Running utils") + print("Running Nutils") # define the Nutils mesh nx = 48 @@ -55,28 +55,29 @@ def main(): cons = solver.optimize(["u"], sqr, droptol=1e-15) # preCICE setup - interface = precice.Interface("Fluid", "../precice-config.xml", 0, 1) + participant = precice.Participant("Fluid", "../precice-config.xml", 0, 1) # define coupling mesh mesh_name = "Fluid-Mesh" - mesh_id = interface.get_mesh_id(mesh_name) vertices = gauss.eval(ns.x) - vertex_ids = interface.set_mesh_vertices(mesh_id, vertices) + vertex_ids = participant.set_mesh_vertices(mesh_name, vertices) # coupling data - velocity_id = interface.get_data_id("Velocity", mesh_id) + data_name = "Velocity" - precice_dt = interface.initialize() + participant.initialize() timestep = 0 - dt = 0.005 + solver_dt = 0.005 + precice_dt = participant.get_max_time_step_size() + dt = min(precice_dt, solver_dt) state = solver.solve_linear(("u", "p"), (ures, pres), constrain=cons) # initial condition # add convective term and time derivative for Navier-Stokes ures += gauss.integral("ubasis_ni (dudt_i + μ (u_i u_j)_,j) d:x" @ ns) - while interface.is_coupling_ongoing(): + while participant.is_coupling_ongoing(): if timestep % 1 == 0: # visualize bezier = domain.sample("bezier", 2) @@ -84,25 +85,26 @@ def main(): with log.add(log.DataLog()): export.vtk("Fluid_" + str(timestep), bezier.tri, x, u=u, p=p) + precice_dt = participant.get_max_time_step_size() + # potentially adjust non-matching timestep sizes - dt = min(dt, precice_dt) + dt = min(solver_dt, precice_dt) # solve Nutils timestep state["u0"] = state["u"] state["dt"] = dt state = solver.newton(("u", "p"), (ures, pres), constrain=cons, arguments=state).solve(1e-10) - if interface.is_write_data_required(dt): - velocity_values = gauss.eval(ns.u, **state) - interface.write_block_vector_data(velocity_id, vertex_ids, velocity_values) + velocity_values = gauss.eval(ns.u, **state) + participant.write_data(mesh_name, data_name, vertex_ids, velocity_values) # do the coupling - precice_dt = interface.advance(dt) + participant.advance(dt) # advance variables timestep += 1 - interface.finalize() + participant.finalize() if __name__ == "__main__": diff --git a/channel-transport/fluid-nutils/requirements.txt b/channel-transport/fluid-nutils/requirements.txt new file mode 100644 index 000000000..cfd521c81 --- /dev/null +++ b/channel-transport/fluid-nutils/requirements.txt @@ -0,0 +1,2 @@ +nutils==7 +pyprecice==3 diff --git a/channel-transport/fluid-nutils/run.sh b/channel-transport/fluid-nutils/run.sh index 788f40d13..7094b61c8 100755 --- a/channel-transport/fluid-nutils/run.sh +++ b/channel-transport/fluid-nutils/run.sh @@ -1,4 +1,12 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 -m venv .venv +. .venv/bin/activate +pip install -r requirements.txt python3 fluid.py + +close_log diff --git a/channel-transport/fluid-openfoam/0/U b/channel-transport/fluid-openfoam/0/U new file mode 100644 index 000000000..2cf022003 --- /dev/null +++ b/channel-transport/fluid-openfoam/0/U @@ -0,0 +1,39 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} + +dimensions [0 1 -1 0 0 0 0]; +internalField uniform (10 0 0); + +boundaryField +{ + inlet + { + type fixedValue; + value $internalField; + } + outlet + { + type zeroGradient; + } + obstacle + { + type noSlip; + } + upperWall + { + type noSlip; + } + lowerWall + { + type noSlip; + } + frontAndBack + { + type empty; + } +} diff --git a/channel-transport/fluid-openfoam/0/p b/channel-transport/fluid-openfoam/0/p new file mode 100644 index 000000000..5252ec67a --- /dev/null +++ b/channel-transport/fluid-openfoam/0/p @@ -0,0 +1,45 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p; +} + +dimensions [0 2 -2 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + inlet + { + type zeroGradient; + } + + outlet + { + type fixedValue; + value uniform 0; + } + + obstacle + { + type zeroGradient; + } + + upperWall + { + type zeroGradient; + } + + lowerWall + { + type zeroGradient; + } + + frontAndBack + { + type empty; + } +} \ No newline at end of file diff --git a/partitioned-heat-conduction/openfoam-dirichlet/clean.sh b/channel-transport/fluid-openfoam/clean.sh similarity index 87% rename from partitioned-heat-conduction/openfoam-dirichlet/clean.sh rename to channel-transport/fluid-openfoam/clean.sh index 1d4095dbf..c31d9fc76 100755 --- a/partitioned-heat-conduction/openfoam-dirichlet/clean.sh +++ b/channel-transport/fluid-openfoam/clean.sh @@ -4,4 +4,3 @@ set -e -u . ../../tools/cleaning-tools.sh clean_openfoam . -rm -rfv 0 diff --git a/channel-transport/fluid-openfoam/constant/transportProperties b/channel-transport/fluid-openfoam/constant/transportProperties new file mode 100644 index 000000000..5383adaad --- /dev/null +++ b/channel-transport/fluid-openfoam/constant/transportProperties @@ -0,0 +1,11 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object transportProperties; +} + +transportModel Newtonian; + +nu nu [ 0 2 -1 0 0 0 0 ] 1; diff --git a/channel-transport/fluid-openfoam/constant/turbulenceProperties b/channel-transport/fluid-openfoam/constant/turbulenceProperties new file mode 100644 index 000000000..592f6d52d --- /dev/null +++ b/channel-transport/fluid-openfoam/constant/turbulenceProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object turbulenceProperties; +} + +simulationType laminar; diff --git a/partitioned-heat-conduction/openfoam-dirichlet/run.sh b/channel-transport/fluid-openfoam/run.sh similarity index 60% rename from partitioned-heat-conduction/openfoam-dirichlet/run.sh rename to channel-transport/fluid-openfoam/run.sh index d9334f454..da82a9ba2 100755 --- a/partitioned-heat-conduction/openfoam-dirichlet/run.sh +++ b/channel-transport/fluid-openfoam/run.sh @@ -1,9 +1,12 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + blockMesh -touch openfoam-dirichlet.foam -./setInitialField.sh ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/channel-transport/fluid-openfoam/system/blockMeshDict b/channel-transport/fluid-openfoam/system/blockMeshDict new file mode 100644 index 000000000..bdb4fe67b --- /dev/null +++ b/channel-transport/fluid-openfoam/system/blockMeshDict @@ -0,0 +1,146 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +x0 0.; +x1 2.; +x2 3.; +x3 6.; + +y0 0.; +y1 1.; +y2 2.; + +z0 0; +z1 1; + +vertices +( + ($x0 $y0 $z0 ) // 0 + ($x1 $y0 $z0 ) // 1 + ($x2 $y0 $z0 ) // 2 + ($x3 $y0 $z0 ) // 3 + ($x0 $y1 $z0 ) // 4 + ($x1 $y1 $z0 ) // 5 + ($x2 $y1 $z0 ) // 6 + ($x3 $y1 $z0 ) // 7 + ($x0 $y2 $z0 ) // 8 + ($x1 $y2 $z0 ) // 9 + ($x2 $y2 $z0 ) // 10 + ($x3 $y2 $z0 ) // 11 + + ($x0 $y0 $z1 ) // 12 + ($x1 $y0 $z1 ) // 13 + ($x2 $y0 $z1 ) // 14 + ($x3 $y0 $z1 ) // 15 + ($x0 $y1 $z1 ) // 16 + ($x1 $y1 $z1 ) // 17 + ($x2 $y1 $z1 ) // 18 + ($x3 $y1 $z1 ) // 19 + ($x0 $y2 $z1 ) // 20 + ($x1 $y2 $z1 ) // 21 + ($x2 $y2 $z1 ) // 22 + ($x3 $y2 $z1 ) // 23 +); + + +// Grading +h1 16; +h2 8; +h3 24; +v1 8; + +blocks +( + hex ( 0 1 5 4 12 13 17 16 ) + ($h1 $v1 1 ) + simpleGrading (1 1 1) + + hex ( 2 3 7 6 14 15 19 18 ) + ($h3 $v1 1) + simpleGrading (1 1 1) + + hex ( 4 5 9 8 16 17 21 20 ) + ($h1 $v1 1) + simpleGrading (1 1 1) + + hex ( 5 6 10 9 17 18 22 21 ) + ($h2 $v1 1) + simpleGrading (1 1 1) + + hex ( 6 7 11 10 18 19 23 22 ) + ($h3 $v1 1 ) + simpleGrading (1 1 1) +); + +boundary +( + inlet + { + type patch; + faces + ( + ( 0 4 16 12 ) + ( 4 8 20 16 ) + ); + } + outlet + { + type patch; + faces + ( + ( 3 7 19 15 ) + ( 7 11 23 19 ) + ); + } + obstacle + { + type wall; + faces + ( + ( 1 5 17 13 ) + ( 5 6 18 17 ) + ( 6 2 14 18 ) + ); + } + upperWall + { + type wall; + faces + ( + ( 8 9 21 20 ) + ( 9 10 22 21 ) + ( 10 11 23 22 ) + ); + } + lowerWall + { + type wall; + faces + ( + ( 0 1 13 12 ) + ( 2 3 15 14 ) + ); + } + frontAndBack + { + type empty; + faces + ( + ( 0 1 5 4 ) + ( 2 3 7 6 ) + ( 4 5 9 8 ) + ( 5 6 10 9 ) + ( 6 7 11 10 ) + ( 12 13 17 16 ) + ( 14 15 19 18 ) + ( 16 17 21 20 ) + ( 17 18 22 21 ) + ( 18 19 23 22 ) + ); + } +); \ No newline at end of file diff --git a/channel-transport/fluid-openfoam/system/controlDict b/channel-transport/fluid-openfoam/system/controlDict new file mode 100644 index 000000000..2880058b4 --- /dev/null +++ b/channel-transport/fluid-openfoam/system/controlDict @@ -0,0 +1,44 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} + +application pimpleFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 1.0; + +deltaT 0.005; + +writeControl adjustableRunTime; + +writeInterval 0.005; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + libs ("libpreciceAdapterFunctionObject.so"); + } +} diff --git a/channel-transport/fluid-openfoam/system/decomposeParDict b/channel-transport/fluid-openfoam/system/decomposeParDict new file mode 100644 index 000000000..f9eae003a --- /dev/null +++ b/channel-transport/fluid-openfoam/system/decomposeParDict @@ -0,0 +1,16 @@ +FoamFile { + version 2.0; + class dictionary; + object decomposeParDict; + format ascii; +} + +numberOfSubdomains 4; + +method simple; + +simpleCoeffs +{ + n (2 2 1); + delta 0.001; +} \ No newline at end of file diff --git a/channel-transport/fluid-openfoam/system/fvSchemes b/channel-transport/fluid-openfoam/system/fvSchemes new file mode 100644 index 000000000..80c096192 --- /dev/null +++ b/channel-transport/fluid-openfoam/system/fvSchemes @@ -0,0 +1,39 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ + default none; + div(phi,U) bounded Gauss upwind; + div((nuEff*dev2(T(grad(U))))) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/channel-transport/fluid-openfoam/system/fvSolution b/channel-transport/fluid-openfoam/system/fvSolution new file mode 100644 index 000000000..d8045408b --- /dev/null +++ b/channel-transport/fluid-openfoam/system/fvSolution @@ -0,0 +1,74 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} + +solvers +{ + + p + { + + solver PCG; + preconditioner DIC; + tolerance 1e-8; + relTol 1e-3; + } + + pFinal + { + $p; + relTol 0; + } + + pcorr + { + $p; + } + + pcorrFinal + { + $pcorr; + relTol 0; + } + + Phi + { + $p; + } + + "(U|cellDisplacement)" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-6; + relTol 1e-4; + minIter 2; + } + + "(U|cellDisplacement)Final" + { + $U; + relTol 0; + } +} + +PIMPLE +{ + nCorrectors 4; + nNonOrthogonalCorrectors 1; + consistent true; + correctPhi true; + momentumPredictor true; + nOuterCorrectors 1; +} + + +potentialFlow +{ + nNonOrthogonalCorrectors 10; +} diff --git a/channel-transport/fluid-openfoam/system/preciceDict b/channel-transport/fluid-openfoam/system/preciceDict new file mode 100644 index 000000000..7368a7a56 --- /dev/null +++ b/channel-transport/fluid-openfoam/system/preciceDict @@ -0,0 +1,32 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Fluid; + +modules (FF); + +interfaces +{ + Interface1 + { + mesh Fluid-Mesh; + patches (); + locations volumeCenters; + + readData + ( + ); + + writeData + ( + Velocity + ); + }; +}; \ No newline at end of file diff --git a/channel-transport/images/tutorials-channel-transport-precice-config.png b/channel-transport/images/tutorials-channel-transport-precice-config.png new file mode 100644 index 000000000..3fd022358 Binary files /dev/null and b/channel-transport/images/tutorials-channel-transport-precice-config.png differ diff --git a/channel-transport/precice-config.xml b/channel-transport/precice-config.xml index 97b9736f5..9abf595ca 100644 --- a/channel-transport/precice-config.xml +++ b/channel-transport/precice-config.xml @@ -7,41 +7,36 @@ enabled="true" /> - - + - - - + + + - - - + + + - - - - - - + + + + + + + + - - - - + + + + - + - - - - - - - + + + + + + diff --git a/channel-transport/transport-nutils/requirements.txt b/channel-transport/transport-nutils/requirements.txt new file mode 100644 index 000000000..cfd521c81 --- /dev/null +++ b/channel-transport/transport-nutils/requirements.txt @@ -0,0 +1,2 @@ +nutils==7 +pyprecice==3 diff --git a/channel-transport/transport-nutils/run.sh b/channel-transport/transport-nutils/run.sh index ac3581bb5..4430e392c 100755 --- a/channel-transport/transport-nutils/run.sh +++ b/channel-transport/transport-nutils/run.sh @@ -1,4 +1,12 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 -m venv .venv +. .venv/bin/activate +pip install -r requirements.txt python3 transport.py + +close_log diff --git a/channel-transport/transport-nutils/transport.py b/channel-transport/transport-nutils/transport.py index 0ffdcbcfb..83aaebd82 100644 --- a/channel-transport/transport-nutils/transport.py +++ b/channel-transport/transport-nutils/transport.py @@ -13,7 +13,7 @@ def main(): - print("Running utils") + print("Running Nutils") # define the Nutils mesh nx = 120 @@ -51,21 +51,22 @@ def main(): cons = solver.optimize("lhs", sqr, droptol=1e-15) # preCICE setup - interface = precice.Interface("Transport", "../precice-config.xml", 0, 1) + participant = precice.Participant("Transport", "../precice-config.xml", 0, 1) # define coupling mesh mesh_name = "Transport-Mesh" - mesh_id = interface.get_mesh_id(mesh_name) vertices = gauss.eval(ns.x) - vertex_ids = interface.set_mesh_vertices(mesh_id, vertices) + vertex_ids = participant.set_mesh_vertices(mesh_name, vertices) # coupling data - velocity_id = interface.get_data_id("Velocity", mesh_id) + data_name = "Velocity" - precice_dt = interface.initialize() + participant.initialize() timestep = 0 - dt = 0.005 + solver_dt = 0.005 + precice_dt = participant.get_max_time_step_size() + dt = min(precice_dt, solver_dt) # set blob as initial condition sqr = domain.integral("(u - uinit)^2" @ ns, degree=2) @@ -74,7 +75,7 @@ def main(): # initialize the velocity values velocity_values = np.zeros_like(vertices) - while interface.is_coupling_ongoing(): + while participant.is_coupling_ongoing(): if timestep % 1 == 0: # visualize bezier = domain.sample("bezier", 2) @@ -82,12 +83,13 @@ def main(): with log.add(log.DataLog()): export.vtk("Transport_" + str(timestep), bezier.tri, x, T=u) - # read velocity values from interface - if interface.is_read_data_available(): - velocity_values = interface.read_block_vector_data(velocity_id, vertex_ids) + precice_dt = participant.get_max_time_step_size() # potentially adjust non-matching timestep sizes - dt = min(dt, precice_dt) + dt = min(solver_dt, precice_dt) + + # read velocity values from participant + velocity_values = participant.read_data(mesh_name, data_name, vertex_ids, dt) # solve nutils timestep lhs = solver.solve_linear( @@ -95,13 +97,13 @@ def main(): ) # do the coupling - precice_dt = interface.advance(dt) + participant.advance(dt) # advance variables timestep += 1 lhs0 = lhs - interface.finalize() + participant.finalize() if __name__ == "__main__": diff --git a/clean-all.sh b/clean-all.sh index 0e5bc2e5c..dc4de8d8a 100755 --- a/clean-all.sh +++ b/clean-all.sh @@ -1,6 +1,6 @@ #!/bin/sh set -e -u -echo "- Cleaning up all tutorials..." +echo "Cleaning up all tutorials..." -find . -maxdepth 2 -mindepth 2 -name clean-tutorial.sh -execdir sh -c './clean-tutorial.sh' \; \ No newline at end of file +find . -maxdepth 2 -mindepth 2 -name clean-tutorial.sh -execdir sh -c './clean-tutorial.sh' \; diff --git a/elastic-tube-1d/README.md b/elastic-tube-1d/README.md index dc4b35665..54b2e8e98 100644 --- a/elastic-tube-1d/README.md +++ b/elastic-tube-1d/README.md @@ -29,6 +29,12 @@ The following parameters have been chosen: Additionally the solvers use the parameters `N = 100` (number of cells), `tau = 0.01` (dimensionless timestep size), `kappa = 100` (dimensionless structural stiffness) by default. These values can be modified directly in each solver. +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-elastic-tube-1d-precice-config.png) + ## Available solvers Both fluid and solid participant are supported in: @@ -122,6 +128,14 @@ python3 plot-vtk.py diameter fluid-python/output/out_fluid_ ![FSI3 setup](images/tutorials-elastic-tube-1d-diameter.png) +## Comparing different Fluid results + +The Fluid participant defines a watchpoint at `x=5`, which records `pressure` and `diameter` for every timestep. +To compare the results of the various Fluid participants, you can run them all and plot the watchpoints using `plot-all.sh`. +The following is an example of running all Fluid solvers against the `solid-cpp` solver: + +![Plot comparing pressure and diameter of all Fluid participants](images/tutorials-elastic-tube-1d-all.png) + ## References [1] B. Gatzhammer. Efficient and Flexible Partitioned Simulation of Fluid-Structure Interactions. Technische Universitaet Muenchen, Fakultaet fuer Informatik, 2014. diff --git a/elastic-tube-1d/fluid-cpp/CMakeLists.txt b/elastic-tube-1d/fluid-cpp/CMakeLists.txt index ca587d693..460944517 100644 --- a/elastic-tube-1d/fluid-cpp/CMakeLists.txt +++ b/elastic-tube-1d/fluid-cpp/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required (VERSION 3.10) project(ElasticTube LANGUAGES CXX) -set (CMAKE_CXX_STANDARD 11) +set (CMAKE_CXX_STANDARD 17) if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build." FORCE) @@ -15,7 +15,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter") endif() -find_package(precice REQUIRED CONFIG) +find_package(precice 3 REQUIRED CONFIG) find_package(LAPACK REQUIRED) add_executable(FluidSolver diff --git a/elastic-tube-1d/fluid-cpp/clean.sh b/elastic-tube-1d/fluid-cpp/clean.sh index ff2895ffa..f84ab182f 100755 --- a/elastic-tube-1d/fluid-cpp/clean.sh +++ b/elastic-tube-1d/fluid-cpp/clean.sh @@ -5,3 +5,4 @@ set -e -u rm -rvf ./output/*.vtk clean_precice_logs . +clean_case_logs . diff --git a/elastic-tube-1d/fluid-cpp/run.sh b/elastic-tube-1d/fluid-cpp/run.sh index e8c898b8e..0e005451e 100755 --- a/elastic-tube-1d/fluid-cpp/run.sh +++ b/elastic-tube-1d/fluid-cpp/run.sh @@ -1,4 +1,15 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +if [ ! -d build ]; then + mkdir build + cmake -S . -B build + cmake --build build +fi + ./build/FluidSolver ../precice-config.xml + +close_log diff --git a/elastic-tube-1d/fluid-cpp/src/FluidComputeSolution.cpp b/elastic-tube-1d/fluid-cpp/src/FluidComputeSolution.cpp index 050868e65..39348a124 100644 --- a/elastic-tube-1d/fluid-cpp/src/FluidComputeSolution.cpp +++ b/elastic-tube-1d/fluid-cpp/src/FluidComputeSolution.cpp @@ -3,48 +3,53 @@ #include #include #include -#include #include +#include using std::sin; using std::sqrt; // Simplifies strided access on a 1d buffer -template +template class StridedAccess { - public: - StridedAccess(T*first, int stride) : first(first), stride(stride) {}; - // This accessor allows for row-major access - T& operator()(int i, int j) { return first[j*stride+i]; } - private: - T*first; - int stride; +public: + StridedAccess(T *first, int stride) + : first(first), stride(stride){}; + // This accessor allows for row-major access + T &operator()(int i, int j) + { + return first[j * stride + i]; + } + +private: + T *first; + int stride; }; extern "C" { void dgesv_( - int * n, - int * nrhs, + int *n, + int *nrhs, double *A, - int * lda, - int * ipiv, + int *lda, + int *ipiv, double *b, - int * ldb, - int * info); + int *ldb, + int *info); } /* Function for fluid_nl i.e. non-linear */ int fluidComputeSolutionSerial( - double const * const velocity_old, - double const * const pressure_old, - double const * const crossSectionLength_old, - double const * const crossSectionLength, - double t, - int N, - double kappa, - double tau, - double * velocity, - double * pressure) + double const *const velocity_old, + double const *const pressure_old, + double const *const crossSectionLength_old, + double const *const crossSectionLength, + double t, + int N, + double kappa, + double tau, + double *velocity, + double *pressure) { const double PI = 3.141592653589793; @@ -59,54 +64,39 @@ int fluidComputeSolutionSerial( // Used as Ax = b // i.e. LHS*x = Res - std::vector Res(2 * N + 2); - std::vector LHS_buffer(std::pow(2*N + 2, 2)); - StridedAccess LHS(LHS_buffer.data(), 2* N + 2); + std::vector Res(2 * N + 2); + std::vector LHS_buffer(std::pow(2 * N + 2, 2)); + StridedAccess LHS(LHS_buffer.data(), 2 * N + 2); /* LAPACK Variables */ - int nlhs = (2 * N + 2); - int nrhs = 1; + int nlhs = (2 * N + 2); + int nrhs = 1; std::vector ipiv(nlhs); /* Stabilization Intensity */ const double alpha = 0.0; //(N * kappa * tau) / (N * tau + 1); - const double L = 10.0; - const double dx = L / kappa; // 1.0 / (N * kappa); + const double L = 10.0; + const double dx = L / kappa; // 1.0 / (N * kappa); // k is the iteration counter - for(int k = 1; ; ++k) { + for (int k = 1;; ++k) { std::fill(Res.begin(), Res.end(), 0.0); for (int i = 1; i < N; i++) { - /* Momentum */ + /* Momentum */ Res[i] = (velocity_old[i] * crossSectionLength_old[i] - velocity[i] * crossSectionLength[i]) * dx / tau; - Res[i] += 0.25 * (- crossSectionLength[i + 1] * velocity[i] * velocity[i + 1] - - crossSectionLength[i] * velocity[i] * velocity[i + 1]); + Res[i] += 0.25 * (-crossSectionLength[i + 1] * velocity[i] * velocity[i + 1] - crossSectionLength[i] * velocity[i] * velocity[i + 1]); - Res[i] += 0.25 * (- crossSectionLength[i + 1] * velocity[i] * velocity[i] - - crossSectionLength[i] * velocity[i] * velocity[i] - + crossSectionLength[i] * velocity[i - 1] * velocity[i] - + crossSectionLength[i - 1] * velocity[i - 1] * velocity[i]); + Res[i] += 0.25 * (-crossSectionLength[i + 1] * velocity[i] * velocity[i] - crossSectionLength[i] * velocity[i] * velocity[i] + crossSectionLength[i] * velocity[i - 1] * velocity[i] + crossSectionLength[i - 1] * velocity[i - 1] * velocity[i]); - Res[i] += 0.25 * (+ crossSectionLength[i - 1] * velocity[i - 1] * velocity[i - 1] - + crossSectionLength[i] * velocity[i - 1] * velocity[i - 1]); + Res[i] += 0.25 * (+crossSectionLength[i - 1] * velocity[i - 1] * velocity[i - 1] + crossSectionLength[i] * velocity[i - 1] * velocity[i - 1]); - Res[i] += 0.25*(+ crossSectionLength[i - 1] * pressure[i - 1] - + crossSectionLength[i] * pressure[i - 1] - - crossSectionLength[i - 1] * pressure[i] - + crossSectionLength[i + 1] * pressure[i] - - crossSectionLength[i] * pressure[i + 1] - - crossSectionLength[i + 1] * pressure[i + 1]); + Res[i] += 0.25 * (+crossSectionLength[i - 1] * pressure[i - 1] + crossSectionLength[i] * pressure[i - 1] - crossSectionLength[i - 1] * pressure[i] + crossSectionLength[i + 1] * pressure[i] - crossSectionLength[i] * pressure[i + 1] - crossSectionLength[i + 1] * pressure[i + 1]); /* Continuity */ Res[i + N + 1] = (crossSectionLength_old[i] - crossSectionLength[i]) * dx / tau; - Res[i + N + 1] += 0.25*(+ crossSectionLength[i - 1] * velocity[i - 1] - + crossSectionLength[i] * velocity[i - 1] - + crossSectionLength[i - 1] * velocity[i] - - crossSectionLength[i + 1] * velocity[i] - - crossSectionLength[i] * velocity[i + 1] - - crossSectionLength[i + 1] * velocity[i + 1]); + Res[i + N + 1] += 0.25 * (+crossSectionLength[i - 1] * velocity[i - 1] + crossSectionLength[i] * velocity[i - 1] + crossSectionLength[i - 1] * velocity[i] - crossSectionLength[i + 1] * velocity[i] - crossSectionLength[i] * velocity[i + 1] - crossSectionLength[i + 1] * velocity[i + 1]); Res[i + N + 1] += alpha * (pressure[i - 1] - 2 * pressure[i] + pressure[i + 1]); } @@ -114,12 +104,12 @@ int fluidComputeSolutionSerial( /* Boundary */ /* Velocity Inlet is prescribed */ - const double u0 = 10.0; - const double ampl = 3.0; - const double frequency = 10.0; - const double t_shift = 0.0; + const double u0 = 10.0; + const double ampl = 3.0; + const double frequency = 10.0; + const double t_shift = 0.0; const double velocity_in = u0 + ampl * sin(frequency * (t + t_shift) * PI); - Res[0] = velocity_in - velocity[0]; + Res[0] = velocity_in - velocity[0]; /* Pressure Inlet is linearly interpolated */ Res[N + 1] = -pressure[0] + 2 * pressure[1] - pressure[2]; @@ -129,17 +119,15 @@ int fluidComputeSolutionSerial( /* Pressure Outlet is "non-reflecting" */ const double tmp2 = sqrt(c_mk2 - pressure_old[N] / 2) - (velocity[N] - velocity_old[N]) / 4; - Res[2 * N + 1] = -pressure[N] + 2 * (c_mk2 - std::pow(tmp2, 2)); + Res[2 * N + 1] = -pressure[N] + 2 * (c_mk2 - std::pow(tmp2, 2)); // compute norm of residual const double norm_1 = std::sqrt( - std::inner_product(Res.begin(), Res.end(), Res.begin(), 0.0) - ); + std::inner_product(Res.begin(), Res.end(), Res.begin(), 0.0)); const double norm_2 = std::sqrt( std::inner_product(pressure, pressure + chunkLength, pressure, 0.0) + - std::inner_product(velocity, velocity + chunkLength, velocity, 0.0) - ); + std::inner_product(velocity, velocity + chunkLength, velocity, 0.0)); const double norm = norm_1 / norm_2; // NOTE tolerance is 1e-10 and max iterations is 1000 in python @@ -153,34 +141,25 @@ int fluidComputeSolutionSerial( for (int i = 1; i < N; i++) { // Momentum, Velocity - LHS(i, i - 1) +=0.25*(-2 * crossSectionLength[i - 1] * velocity[i - 1] - -2 * crossSectionLength[i] * velocity[i - 1] - - crossSectionLength[i] * velocity[i] - - crossSectionLength[i - 1] * velocity[i]); - - LHS(i, i) += crossSectionLength[i] * dx / tau; - LHS(i, i) += 0.25 * (+ crossSectionLength[i + 1] * velocity[i + 1] - + crossSectionLength[i] * velocity[i + 1] - +2 * crossSectionLength[i + 1] * velocity[i] - +2 * crossSectionLength[i] * velocity[i] - - crossSectionLength[i] * velocity[i - 1] - - crossSectionLength[i - 1] * velocity[i - 1]); - LHS(i, i + 1) += 0.25 * (+ crossSectionLength[i + 1] * velocity[i] - + crossSectionLength[i] * velocity[i]); + LHS(i, i - 1) += 0.25 * (-2 * crossSectionLength[i - 1] * velocity[i - 1] - 2 * crossSectionLength[i] * velocity[i - 1] - crossSectionLength[i] * velocity[i] - crossSectionLength[i - 1] * velocity[i]); + + LHS(i, i) += crossSectionLength[i] * dx / tau; + LHS(i, i) += 0.25 * (+crossSectionLength[i + 1] * velocity[i + 1] + crossSectionLength[i] * velocity[i + 1] + 2 * crossSectionLength[i + 1] * velocity[i] + 2 * crossSectionLength[i] * velocity[i] - crossSectionLength[i] * velocity[i - 1] - crossSectionLength[i - 1] * velocity[i - 1]); + LHS(i, i + 1) += 0.25 * (+crossSectionLength[i + 1] * velocity[i] + crossSectionLength[i] * velocity[i]); // Momentum, Pressure LHS(i, N + 1 + i - 1) += -0.25 * crossSectionLength[i - 1] - 0.25 * crossSectionLength[i]; - LHS(i, N + 1 + i) += 0.25 * crossSectionLength[i - 1] - 0.25 * crossSectionLength[i + 1]; - LHS(i, N + 1 + i + 1) += 0.25 * crossSectionLength[i] + 0.25 * crossSectionLength[i + 1]; + LHS(i, N + 1 + i) += 0.25 * crossSectionLength[i - 1] - 0.25 * crossSectionLength[i + 1]; + LHS(i, N + 1 + i + 1) += 0.25 * crossSectionLength[i] + 0.25 * crossSectionLength[i + 1]; // Continuity, Velocity LHS(i + N + 1, i - 1) += -0.25 * crossSectionLength[i - 1] - 0.25 * crossSectionLength[i]; - LHS(i + N + 1, i) += -0.25 * crossSectionLength[i - 1] + 0.25 * crossSectionLength[i + 1]; - LHS(i + N + 1, i + 1) += 0.25 * crossSectionLength[i] + 0.25 * crossSectionLength[i + 1]; + LHS(i + N + 1, i) += -0.25 * crossSectionLength[i - 1] + 0.25 * crossSectionLength[i + 1]; + LHS(i + N + 1, i + 1) += 0.25 * crossSectionLength[i] + 0.25 * crossSectionLength[i + 1]; // Continuity, Pressure LHS(i + N + 1, N + 1 + i - 1) -= alpha; - LHS(i + N + 1, N + 1 + i) += 2 * alpha; + LHS(i + N + 1, N + 1 + i) += 2 * alpha; LHS(i + N + 1, N + 1 + i + 1) -= alpha; } diff --git a/elastic-tube-1d/fluid-cpp/src/FluidComputeSolution.h b/elastic-tube-1d/fluid-cpp/src/FluidComputeSolution.h index 20c52c543..e2207a6c4 100644 --- a/elastic-tube-1d/fluid-cpp/src/FluidComputeSolution.h +++ b/elastic-tube-1d/fluid-cpp/src/FluidComputeSolution.h @@ -3,13 +3,13 @@ const double PI = 3.14159265359; int fluidComputeSolutionSerial( - double const * const velocity_old, - double const * const pressure_old, - double const * const crossSectionLength_old, - double const * const crossSectionLength, - double t, - int N, - double kappa, - double tau, - double * velocity, - double * pressure); + double const *const velocity_old, + double const *const pressure_old, + double const *const crossSectionLength_old, + double const *const crossSectionLength, + double t, + int N, + double kappa, + double tau, + double *velocity, + double *pressure); diff --git a/elastic-tube-1d/fluid-cpp/src/FluidSolver.cpp b/elastic-tube-1d/fluid-cpp/src/FluidSolver.cpp index 88c99d551..d2e1d9a4a 100644 --- a/elastic-tube-1d/fluid-cpp/src/FluidSolver.cpp +++ b/elastic-tube-1d/fluid-cpp/src/FluidSolver.cpp @@ -1,13 +1,12 @@ #include "FluidComputeSolution.h" #include "utilities.h" +#include #include #include -#include -#include "precice/SolverInterface.hpp" +#include "precice/precice.hpp" using namespace precice; -using namespace precice::constants; int main(int argc, char **argv) { @@ -20,36 +19,36 @@ int main(int argc, char **argv) return -1; } - std::string configFileName(argv[1]); - int domainSize = 100; //N - int chunkLength = domainSize + 1; - const double kappa = 100; - const double L = 10.0; // tube length + std::string configFileName(argv[1]); + int domainSize = 100; // N + int chunkLength = domainSize + 1; + const double kappa = 100; + const double L = 10.0; // tube length const std::string solverName = "Fluid"; - std::string outputFilePrefix = "./output/out_fluid"; //extra + std::string outputFilePrefix = "./output/out_fluid"; // extra - SolverInterface interface(solverName, configFileName, 0, 1); + precice::Participant interface(solverName, configFileName, 0, 1); std::cout << "preCICE configured..." << std::endl; - const int dimensions = interface.getDimensions(); - const int meshID = interface.getMeshID("Fluid-Nodes-Mesh"); - const int pressureID = interface.getDataID("Pressure", meshID); - const int crossSectionLengthID = interface.getDataID("CrossSectionLength", meshID); + auto meshName = "Fluid-Nodes-Mesh"; + auto pressureName = "Pressure"; + auto crossSectionLengthName = "CrossSectionLength"; + const int dimensions = interface.getMeshDimensions(meshName); - std::vector vertexIDs(chunkLength); + std::vector vertexIDs(chunkLength); const double PI = 3.141592653589793; - const double r0 = 1 / sqrt(PI); // radius of the tube - const double a0 = std::pow(r0, 2) * PI; // cross sectional area - const double u0 = 10; // mean velocity - const double ampl = 3; // amplitude of varying velocity - const double frequency = 10; // frequency of variation - const double t_shift = 0; // temporal shift of variation - const double p0 = 0; // pressure at outlet - const double vel_in_0 = u0 + ampl * sin(frequency * (t_shift) * PI); + const double r0 = 1 / sqrt(PI); // radius of the tube + const double a0 = std::pow(r0, 2) * PI; // cross sectional area + const double u0 = 10; // mean velocity + const double ampl = 3; // amplitude of varying velocity + const double frequency = 10; // frequency of variation + const double t_shift = 0; // temporal shift of variation + const double p0 = 0; // pressure at outlet + const double vel_in_0 = u0 + ampl * sin(frequency * (t_shift) *PI); std::vector pressure(chunkLength, p0); std::vector pressure_old(pressure); @@ -59,7 +58,7 @@ int main(int argc, char **argv) std::vector velocity_old(velocity); std::vector grid(dimensions * chunkLength); - const double cellwidth =(L / domainSize) ; + const double cellwidth = (L / domainSize); for (int i = 0; i < chunkLength; i++) { for (int d = 0; d < dimensions; d++) { if (d == 0) { @@ -70,76 +69,65 @@ int main(int argc, char **argv) } } - interface.setMeshVertices(meshID, chunkLength, grid.data(), vertexIDs.data()); - - double t = 0.0; - std::cout << "Initialize preCICE..." << std::endl; - double dt = interface.initialize(); + interface.setMeshVertices(meshName, grid, vertexIDs); - if (interface.isActionRequired(actionWriteInitialData())) { - interface.writeBlockScalarData(pressureID, chunkLength, vertexIDs.data(), pressure.data()); - interface.markActionFulfilled(actionWriteInitialData()); + if (interface.requiresInitialData()) { + interface.writeData(meshName, pressureName, vertexIDs, pressure); } - interface.initializeData(); + double t = 0.0; + std::cout << "Initialize preCICE..." << std::endl; + interface.initialize(); - if (interface.isReadDataAvailable()) { - interface.readBlockScalarData(crossSectionLengthID, chunkLength, vertexIDs.data(), crossSectionLength.data()); - } + interface.readData(meshName, crossSectionLengthName, vertexIDs, 0, crossSectionLength); std::copy(crossSectionLength.begin(), crossSectionLength.end(), crossSectionLength_old.begin()); // initialize such that mass conservation is fulfilled - for(int i = 0; i < chunkLength; ++i) { + for (int i = 0; i < chunkLength; ++i) { velocity_old[i] = vel_in_0 * crossSectionLength_old[0] / crossSectionLength_old[i]; } int out_counter = 0; while (interface.isCouplingOngoing()) { - if (interface.isActionRequired(actionWriteIterationCheckpoint())) { - interface.markActionFulfilled(actionWriteIterationCheckpoint()); + if (interface.requiresWritingCheckpoint()) { } - + + auto dt = interface.getMaxTimeStepSize(); + fluidComputeSolutionSerial( // values from last time window velocity_old.data(), pressure_old.data(), crossSectionLength_old.data(), // last received crossSectionLength crossSectionLength.data(), - t+dt, // used for inlet velocity - domainSize, - kappa, + t + dt, // used for inlet velocity + domainSize, + kappa, dt, // tau // resulting velocity pressure velocity.data(), pressure.data()); - - if (interface.isWriteDataRequired(dt)) { - interface.writeBlockScalarData(pressureID, chunkLength, vertexIDs.data(), pressure.data()); - } - + + interface.writeData(meshName, pressureName, vertexIDs, pressure); + interface.advance(dt); - //interface.readBlockScalarData(crossSectionLengthID, chunkLength, vertexIDs.data(), crossSectionLength.data()); - if (interface.isReadDataAvailable()) { - interface.readBlockScalarData(crossSectionLengthID, chunkLength, vertexIDs.data(), crossSectionLength.data()); - } + interface.readData(meshName, crossSectionLengthName, vertexIDs, interface.getMaxTimeStepSize(), crossSectionLength); - if (interface.isActionRequired(actionReadIterationCheckpoint())) { // i.e. not yet converged - interface.markActionFulfilled(actionReadIterationCheckpoint()); + if (interface.requiresReadingCheckpoint()) { } else { t += dt; write_vtk(t, out_counter, outputFilePrefix.c_str(), chunkLength, grid.data(), velocity.data(), pressure.data(), crossSectionLength.data()); for (int i = 0; i < chunkLength; i++) { crossSectionLength_old[i] = crossSectionLength[i]; - pressure_old[i] = pressure[i]; - velocity_old[i] = velocity[i]; + pressure_old[i] = pressure[i]; + velocity_old[i] = velocity[i]; } out_counter++; } } std::cout << "Exiting FluidSolver" << std::endl; - interface.finalize(); return 0; } diff --git a/elastic-tube-1d/fluid-cpp/src/utilities.cpp b/elastic-tube-1d/fluid-cpp/src/utilities.cpp index a96e3cb9e..1ed3166f1 100644 --- a/elastic-tube-1d/fluid-cpp/src/utilities.cpp +++ b/elastic-tube-1d/fluid-cpp/src/utilities.cpp @@ -8,22 +8,22 @@ #include #include -/* - Function for solving the linear system +/* + Function for solving the linear system LAPACK is used DGESV computes the solution to a real system of linear equations A * x = b, where A is an N-by-N matrix and x and b are N-by-NRHS matrices. */ extern "C" { void dgesv_( - int * n, - int * nrhs, + int *n, + int *nrhs, double *A, - int * lda, - int * ipiv, + int *lda, + int *ipiv, double *b, - int * ldb, - int * info); + int *ldb, + int *info); } void initializeWriting(std::ofstream &filestream) @@ -35,19 +35,19 @@ void initializeWriting(std::ofstream &filestream) void writeHeader(std::ostream &outFile) { - outFile << "# vtk DataFile Version 2.0" << std::endl - << std::endl - << "ASCII" << std::endl - << std::endl - << "DATASET UNSTRUCTURED_GRID" << std::endl - << std::endl; + outFile << "# vtk DataFile Version 2.0\n" + << '\n' + << "ASCII\n" + << '\n' + << "DATASET UNSTRUCTURED_GRID\n" + << '\n'; } void exportMesh(std::ofstream &outFile, int N_slices, double *grid) { // Plot vertices - outFile << "POINTS " << N_slices << " float " << std::endl - << std::endl; + outFile << "POINTS " << N_slices << " float\n" + << '\n'; for (int i = 0; i < N_slices; i++) { // read x,y from grid. Set z = 0 @@ -55,14 +55,14 @@ void exportMesh(std::ofstream &outFile, int N_slices, double *grid) double x = grid[2 * i + 0]; double y = grid[2 * i + 1]; double z = 0.0; - outFile << x << " " << y << " " << z << std::endl; + outFile << x << " " << y << " " << z << '\n'; } - outFile << std::endl; + outFile << '\n'; } void exportVectorData(std::ofstream &outFile, int N_slices, double *data, const char *dataname) { - outFile << "VECTORS " << dataname << " float" << std::endl; + outFile << "VECTORS " << dataname << " float\n"; for (int i = 0; i < N_slices; i++) { // Plot vertex data @@ -71,23 +71,23 @@ void exportVectorData(std::ofstream &outFile, int N_slices, double *data, const double vx = data[i]; double vy = 0.0; double vz = 0.0; - outFile << vx << " " << vy << " " << vz << std::endl; + outFile << vx << " " << vy << " " << vz << '\n'; } - outFile << std::endl; + outFile << '\n'; } void exportScalarData(std::ofstream &outFile, int N_slices, double *data, std::string dataname) { - outFile << "SCALARS " << dataname << " float" << std::endl; - outFile << "LOOKUP_TABLE default" << std::endl; + outFile << "SCALARS " << dataname << " float\n"; + outFile << "LOOKUP_TABLE default\n"; for (int i = 0; i < N_slices; i++) { // Plot vertex data - outFile << data[i] << std::endl; + outFile << data[i] << '\n'; } - outFile << std::endl; + outFile << '\n'; } void write_vtk(double t, int iteration, const char *filename_prefix, int N_slices, double *grid, double *velocity, double *pressure, double *diameter) @@ -103,8 +103,8 @@ void write_vtk(double t, int iteration, const char *filename_prefix, int N_slice writeHeader(outstream); exportMesh(outstream, N_slices, grid); - outstream << "POINT_DATA " << N_slices << std::endl; - outstream << std::endl; + outstream << "POINT_DATA " << N_slices << '\n'; + outstream << '\n'; exportVectorData(outstream, N_slices, velocity, "velocity"); exportScalarData(outstream, N_slices, pressure, "pressure"); diff --git a/elastic-tube-1d/fluid-cpp/src/utilities.h b/elastic-tube-1d/fluid-cpp/src/utilities.h index 416ba690d..17c1cedfe 100644 --- a/elastic-tube-1d/fluid-cpp/src/utilities.h +++ b/elastic-tube-1d/fluid-cpp/src/utilities.h @@ -1,14 +1,13 @@ #ifndef FLUID_NL_H_ #define FLUID_NL_H_ -#include void write_vtk(double t, int iteration, const char *filename_prefix, int N_slices, - double * grid, - double * velocity, - double * pressure, - double * diameter); + double *grid, + double *velocity, + double *pressure, + double *diameter); #endif diff --git a/elastic-tube-1d/fluid-python/FluidSolver.py b/elastic-tube-1d/fluid-python/FluidSolver.py index 354366672..e9ae8c496 100644 --- a/elastic-tube-1d/fluid-python/FluidSolver.py +++ b/elastic-tube-1d/fluid-python/FluidSolver.py @@ -10,8 +10,6 @@ import matplotlib.animation as manimation from output import writeOutputToVTK import precice -from precice import action_write_initial_data, action_write_iteration_checkpoint, \ - action_read_iteration_checkpoint # physical properties of the tube r0 = 1 / np.sqrt(np.pi) # radius of the tube @@ -68,10 +66,14 @@ def crossSection0(N): print("N: " + str(N)) print("Configure preCICE...") -interface = precice.Interface("Fluid", args.configurationFileName, 0, 1) +interface = precice.Participant("Fluid", args.configurationFileName, 0, 1) print("preCICE configured...") -dimensions = interface.get_dimensions() +meshName = "Fluid-Nodes-Mesh" +crossSectionLengthName = "CrossSectionLength" +pressureName = "Pressure" + +dimensions = interface.get_mesh_dimensions(meshName) velocity = velocity_in(0) * np.ones(N + 1) velocity_old = velocity_in(0) * np.ones(N + 1) @@ -88,33 +90,24 @@ def crossSection0(N): writer = FFMpegWriter(fps=15, metadata=metadata) writer.setup(fig, "writer_test.mp4", 100) -meshID = interface.get_mesh_id("Fluid-Nodes-Mesh") -crossSectionLengthID = interface.get_data_id("CrossSectionLength", meshID) -pressureID = interface.get_data_id("Pressure", meshID) - -vertexIDs = np.zeros(N + 1) grid = np.zeros([N + 1, dimensions]) - grid[:, 0] = np.linspace(0, L, N + 1) # x component grid[:, 1] = 0 # y component, leave blank -vertexIDs = interface.set_mesh_vertices(meshID, grid) +vertexIDs = interface.set_mesh_vertices(meshName, grid) + +if interface.requires_initial_data(): + interface.write_data(meshName, pressureName, vertexIDs, pressure) t = 0 + print("Fluid: init precice...") # preCICE defines timestep size of solver via precice-config.xml -precice_dt = interface.initialize() +interface.initialize() -if interface.is_action_required(action_write_initial_data()): - interface.write_block_scalar_data(pressureID, vertexIDs, pressure) - interface.mark_action_fulfilled(action_write_initial_data()) - -interface.initialize_data() - -if interface.is_read_data_available(): - crossSectionLength = interface.read_block_scalar_data( - crossSectionLengthID, vertexIDs) +crossSectionLength = interface.read_data( + meshName, crossSectionLengthName, vertexIDs, 0) crossSectionLength_old = np.copy(crossSectionLength) # initialize such that mass conservation is fulfilled @@ -126,20 +119,22 @@ def crossSection0(N): time_it = 0 while interface.is_coupling_ongoing(): # When an implicit coupling scheme is used, checkpointing is required - if interface.is_action_required(action_write_iteration_checkpoint()): - interface.mark_action_fulfilled(action_write_iteration_checkpoint()) + if interface.requires_writing_checkpoint(): + pass + precice_dt = interface.get_max_time_step_size() + + crossSectionLength = interface.read_data( + meshName, crossSectionLengthName, vertexIDs, precice_dt) velocity, pressure, success = perform_partitioned_implicit_euler_step( velocity_old, pressure_old, crossSectionLength_old, crossSectionLength, dx, precice_dt, velocity_in( t + precice_dt), custom_coupling=True) - interface.write_block_scalar_data(pressureID, vertexIDs, pressure) + interface.write_data(meshName, pressureName, vertexIDs, pressure) interface.advance(precice_dt) - crossSectionLength = interface.read_block_scalar_data( - crossSectionLengthID, vertexIDs) # i.e. not yet converged - if interface.is_action_required(action_read_iteration_checkpoint()): - interface.mark_action_fulfilled(action_read_iteration_checkpoint()) + if interface.requires_reading_checkpoint(): + pass else: # converged, timestep complete t += precice_dt if plotting_mode is config.PlottingModes.VIDEO: @@ -159,5 +154,3 @@ def crossSection0(N): if plotting_mode is config.PlottingModes.VIDEO and writeVideoToFile: writer.finish() - -interface.finalize() diff --git a/elastic-tube-1d/fluid-python/clean.sh b/elastic-tube-1d/fluid-python/clean.sh index ff2895ffa..f84ab182f 100755 --- a/elastic-tube-1d/fluid-python/clean.sh +++ b/elastic-tube-1d/fluid-python/clean.sh @@ -5,3 +5,4 @@ set -e -u rm -rvf ./output/*.vtk clean_precice_logs . +clean_case_logs . diff --git a/elastic-tube-1d/fluid-python/run.sh b/elastic-tube-1d/fluid-python/run.sh index 4272d9b77..dcf4c901d 100755 --- a/elastic-tube-1d/fluid-python/run.sh +++ b/elastic-tube-1d/fluid-python/run.sh @@ -1,4 +1,9 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + python3 ./FluidSolver.py ../precice-config.xml + +close_log diff --git a/elastic-tube-1d/fluid-python/tubePlotting.py b/elastic-tube-1d/fluid-python/tubePlotting.py index 6a82ffa6d..24bc8afae 100644 --- a/elastic-tube-1d/fluid-python/tubePlotting.py +++ b/elastic-tube-1d/fluid-python/tubePlotting.py @@ -44,7 +44,7 @@ def plotVar(ax, crossSection, dx, t): def doPlotting(ax, crossSection0, velocity0, pressure0, dx, t): plotTube(ax, crossSection0, velocity0, pressure0, dx, t) - #plotVar(ax[1], crossSection0, dx, t) + # plotVar(ax[1], crossSection0, dx, t) plt.title(t) plt.pause(0.1) # ax[1].cla() diff --git a/elastic-tube-1d/fluid-rust/Cargo.toml b/elastic-tube-1d/fluid-rust/Cargo.toml new file mode 100644 index 000000000..b7e82a6e5 --- /dev/null +++ b/elastic-tube-1d/fluid-rust/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "fluid-rust" +version = "0.1.0" +edition = "2021" +publish = false +repository = "https://github.com/precice/tutorials" +description = "The fluid participant of the elastic-tube 1D tutorial" +license = "LGPL-3.0-or-later" + +[dependencies] +"precice" = "3" +"nalgebra" = "0.31" diff --git a/elastic-tube-1d/fluid-rust/clean.sh b/elastic-tube-1d/fluid-rust/clean.sh new file mode 100755 index 000000000..f84ab182f --- /dev/null +++ b/elastic-tube-1d/fluid-rust/clean.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +rm -rvf ./output/*.vtk +clean_precice_logs . +clean_case_logs . diff --git a/elastic-tube-1d/fluid-rust/run.sh b/elastic-tube-1d/fluid-rust/run.sh new file mode 100755 index 000000000..9985f982b --- /dev/null +++ b/elastic-tube-1d/fluid-rust/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +cargo run --release ../precice-config.xml + +close_log diff --git a/elastic-tube-1d/fluid-rust/src/main.rs b/elastic-tube-1d/fluid-rust/src/main.rs new file mode 100644 index 000000000..f9d472f4a --- /dev/null +++ b/elastic-tube-1d/fluid-rust/src/main.rs @@ -0,0 +1,159 @@ +use std::env; +use std::process::ExitCode; + +mod solver; +mod utils; + +fn main() -> ExitCode { + println!("Starting Fluid Solver..."); + + let args: Vec<_> = env::args().collect(); + + if args.len() != 2 { + println!("Fluid: Usage: {} ", args[0]); + return ExitCode::from(1); + } + + let config = &args[1]; + + const DOMAIN_SIZE: usize = 100; + const CHUNK_SIZE: usize = DOMAIN_SIZE + 1; + + let mut participant = precice::Participant::new("Fluid", config, 0, 1); + + println!("preCICE configured..."); + + let mesh_name = "Fluid-Nodes-Mesh"; + let dimensions = participant.get_mesh_dimensions(mesh_name); + assert!(participant.get_data_dimensions(mesh_name, "CrossSectionLength") == 1); + assert!(participant.get_data_dimensions(mesh_name, "Pressure") == 1); + + const KAPPA: f64 = 100_f64; + const L: f64 = 10_f64; + const DX: f64 = L / KAPPA; + + const R0: f64 = 2.0 * std::f64::consts::FRAC_2_SQRT_PI; + const A0: f64 = R0 * R0 * std::f64::consts::PI; + const U0: f64 = 10.0; + const AMPL: f64 = 3.0; + const FREQUENCY: f64 = 10.0; + const T_SHIFT: f64 = 0.0; + const P0: f64 = 0.0; + let vel_in0: f64 = U0 + AMPL * (FREQUENCY * T_SHIFT * std::f64::consts::PI).sin(); + + let mut pressure: Vec = vec![P0; CHUNK_SIZE]; + let mut cross_section_length: Vec = vec![A0; CHUNK_SIZE]; + let mut velocity: Vec = vec![vel_in0; CHUNK_SIZE]; + + let mut pressure_old = pressure.clone(); + + const CELLWIDTH: f64 = L / DOMAIN_SIZE as f64; + let grid_size = CHUNK_SIZE * dimensions as usize; + let grid: Vec = { + let mut v: Vec = vec![0_f64; grid_size]; + for i in 0..CHUNK_SIZE { + let idx = i * dimensions as usize; + v[idx] = i as f64 * CELLWIDTH; + } + v + }; + + let vertex_ids = { + let mut ids = vec![-1; CHUNK_SIZE]; + participant.set_mesh_vertices(mesh_name, &grid[..], &mut ids[..]); + ids + }; + + println!("Initializing preCICE..."); + + if participant.requires_initial_data() { + participant.write_data(mesh_name, "Pressure", &vertex_ids[..], &pressure[..]); + } + + participant.initialize(); + + participant.read_data( + mesh_name, + "CrossSectionLength", + &vertex_ids[..], + 0.0, + &mut cross_section_length[..], + ); + + let mut cross_section_length_old = cross_section_length.clone(); + + // initialize such that mass conservation is fulfilled + let mut velocity_old = { + let csl0 = cross_section_length[0]; + cross_section_length + .iter() + .map(|csl| vel_in0 * csl0 / csl) + .collect::>() + }; + + let mut out_counter = 0; + + let mut t = 0.0; + + while participant.is_coupling_ongoing() { + if participant.requires_writing_checkpoint() { + // do nothing + } + + let dt = participant.get_max_time_step_size(); + + solver::fluid_compute_solution( + &velocity_old[..], + &pressure_old[..], + &cross_section_length_old[..], + &cross_section_length[..], + t, + DOMAIN_SIZE, + KAPPA, + dt, + &mut velocity[..], + &mut pressure[..], + ); + + participant.write_data(mesh_name, "Pressure", &vertex_ids[..], &pressure[..]); + + participant.advance(dt); + + participant.read_data( + mesh_name, + "CrossSectionLength", + &vertex_ids[..], + participant.get_max_time_step_size(), + &mut cross_section_length[..], + ); + + if participant.requires_reading_checkpoint() { + // i.e. fluid not yet converged + + //pressure.copy_from_slice(&pressure_old[..]); + //velocity.copy_from_slice(&velocity_old[..]); + } else { + t += dt; + pressure_old.copy_from_slice(&pressure[..]); + velocity_old.copy_from_slice(&velocity[..]); + cross_section_length_old.copy_from_slice(&cross_section_length[..]); + + let filename = format!("./output/out_fluid_{out_counter}.vtk"); + println!("writing timestep at t={} to {}", t, filename); + utils::write_vtk( + &filename, + DX, + &velocity_old[..], + &pressure_old[..], + &cross_section_length_old[..], + ) + .expect("Unable to write the vtk file"); + out_counter += 1; + } + } + + println!("Exiting FluidSolver at t={}", t); + participant.finalize(); + + ExitCode::SUCCESS +} diff --git a/elastic-tube-1d/fluid-rust/src/solver.rs b/elastic-tube-1d/fluid-rust/src/solver.rs new file mode 100644 index 000000000..ed5f4534b --- /dev/null +++ b/elastic-tube-1d/fluid-rust/src/solver.rs @@ -0,0 +1,172 @@ +use nalgebra::{DMatrix, DVector}; + +pub fn fluid_compute_solution( + velocity_old: &[f64], + pressure_old: &[f64], + cross_section_length_old: &[f64], + cross_section_length: &[f64], + t: f64, + n: usize, + kappa: f64, + tau: f64, + velocity: &mut [f64], + pressure: &mut [f64], +) { + // Initial guess + pressure.copy_from_slice(pressure_old); + + const E: f64 = 10000_f64; + //const C_MK2 : f64 = E / std::f64::consts::FRAC_2_SQRT_PI; + let c_mk2: f64 = E / 2.0 * std::f64::consts::PI.sqrt(); + + // lhs = 2*N+2 + + const ALPHA: f64 = 0.0; + const L: f64 = 10.0; + let dx = L / kappa; + + let equations = 2 * n + 2; + + let mut k = 0; + loop { + k += 1; + + let res = { + let mut res = DVector::from_element(equations, 0.0); + for i in 1..n { + let [p_l, p_c, p_r]: [f64; 3] = pressure[i - 1..i + 2].try_into().unwrap(); + let [v_l, v_c, v_r]: [f64; 3] = velocity[i - 1..i + 2].try_into().unwrap(); + let [c_l, c_c, c_r]: [f64; 3] = + cross_section_length[i - 1..i + 2].try_into().unwrap(); + + /* Momentum */ + res[i] = (velocity_old[i] * cross_section_length_old[i] - v_c * c_c) * dx / tau + + 0.25 * (-c_r * v_c * v_r - c_c * v_c * v_r) + + 0.25 + * (-c_r * v_c * v_c - c_c * v_c * v_c + c_c * v_l * v_c + c_l * v_l * v_c) + + 0.25 * (c_l * v_l * v_l + c_c * v_l * v_l) + + 0.25 + * (c_l * p_l + c_c * p_l - c_l * p_c + c_r * p_c - c_c * p_r - c_r * p_r); + + /* Continuity */ + res[i + n + 1] = (cross_section_length_old[i] - c_c) * dx / tau + + 0.25 + * (c_l * v_l + c_c * v_l + c_l * v_c - c_r * v_c - c_c * v_r - c_r * v_r) + + ALPHA * (p_l - 2.0 * p_c + p_r); + } + /* Boundary */ + + /* Velocity Inlet is prescribed */ + let u0 = 10.0; + let ampl = 3.0; + let frequency = 10.0; + let t_shift = 0.0; + let velocity_in = + u0 + ampl * (frequency * (t + tau + t_shift) * std::f64::consts::PI).sin(); + res[0] = velocity_in - velocity[0]; + + /* Pressure Inlet is linearly interpolated */ + res[n + 1] = -pressure[0] + 2.0 * pressure[1] - pressure[2]; + + /* Velocity Outlet is linearly interpolated */ + res[n] = -velocity[n] + 2.0 * velocity[n - 1] - velocity[n - 2]; + + /* Pressure Outlet is "non-reflecting" */ + let tmp2 = + (c_mk2 - pressure_old[n] / 2.0).sqrt() - (velocity[n] - velocity_old[n]) / 4.0; + res[2 * n + 1] = -pressure[n] + 2.0 * (c_mk2 - tmp2.powi(2)); + res + }; + + // compute norm of residual + let norm: f64 = { + let norm1 = res.map(|x: f64| x * x).sum().sqrt(); + let norm2 = pressure + .iter() + .chain(velocity.iter()) + .map(|x| x * x) + .sum::() + .sqrt(); + norm1 / norm2 + }; + + const TOL: f64 = 1e-10; + const MAX_ITER: usize = 1000; + if norm < TOL && k > 1 { + //println!("Success at k={} res={} tol={}", k, norm, TOL); + break; + } else if k > MAX_ITER { + panic!("Nonlinear Solver break, iterations: {k}, residual norm: {norm}"); + } else { + //println!("Continuing k={} res={:.10} tol={:.10}", k, norm, TOL); + } + + /* Initializing the the LHS i.e. Left Hand Side */ + let lhs = { + let mut lhs = DMatrix::from_element(equations, equations, 0.0); + for i in 1..n { + let [v_l, v_c, v_r]: [f64; 3] = velocity[i - 1..i + 2].try_into().unwrap(); + let [c_l, c_c, c_r]: [f64; 3] = + cross_section_length[i - 1..i + 2].try_into().unwrap(); + + // Momentum, Velocity + lhs[(i, i - 1)] = + 0.25 * (-2.0 * c_l * v_l - 2.0 * c_c * v_l - c_c * v_c - c_l * v_c); + + lhs[(i, i)] = c_c * dx / tau + + 0.25 + * (c_r * v_r + c_c * v_r + 2.0 * c_r * v_c + 2.0 * c_c * v_c + - c_c * v_l + - c_l * v_l); + lhs[(i, i + 1)] = 0.25 * (c_r * v_c + c_c * v_c); + + // Momentum, Pressure + lhs[(i, n + 1 + i - 1)] = -0.25 * (c_l + c_c); + lhs[(i, n + 1 + i)] = 0.25 * (c_l - c_r); + lhs[(i, n + 1 + i + 1)] = 0.25 * (c_c + c_r); + + // Continuity, Velocity + lhs[(i + n + 1, i - 1)] = -0.25 * (c_l + c_c); + lhs[(i + n + 1, i)] = -0.25 * (c_l - c_r); + lhs[(i + n + 1, i + 1)] = 0.25 * (c_c + c_r); + + // Continuity, Pressure + lhs[(i + n + 1, n + 1 + i - 1)] = -ALPHA; + lhs[(i + n + 1, n + 1 + i)] = 2.0 * ALPHA; + lhs[(i + n + 1, n + 1 + i + 1)] = -ALPHA; + } + + /* Boundary */ + + // Velocity Inlet is prescribed + lhs[(0, 0)] = 1.0; + // Pressure Inlet is linearly interpolated + lhs[(n + 1, n + 1)] = 1.0; + lhs[(n + 1, n + 2)] = -2.0; + lhs[(n + 1, n + 3)] = 1.0; + // Velocity Outlet is linearly interpolated + lhs[(n, n)] = 1.0; + lhs[(n, n - 1)] = -2.0; + lhs[(n, n - 2)] = 1.0; + // Pressure Outlet is non-Reflecting + lhs[(2 * n + 1, 2 * n + 1)] = 1.0; + lhs[(2 * n + 1, n)] = + -((c_mk2 - pressure_old[n] / 2.0).sqrt() - (velocity[n] - velocity_old[n]) / 4.0); + lhs + }; + + let sol = lhs + .lu() + .solve(&res) + .expect("Linear Solver did not converge!"); + + velocity + .iter_mut() + .zip(sol.as_slice()[..n + 1].iter()) + .for_each(|p| *p.0 += p.1); + pressure + .iter_mut() + .zip(sol.as_slice()[n + 1..].iter()) + .for_each(|p| *p.0 += p.1); + } +} diff --git a/elastic-tube-1d/fluid-rust/src/utils.rs b/elastic-tube-1d/fluid-rust/src/utils.rs new file mode 100644 index 000000000..3ad0c8070 --- /dev/null +++ b/elastic-tube-1d/fluid-rust/src/utils.rs @@ -0,0 +1,62 @@ +use std::fs::{create_dir, File}; +use std::io::{BufWriter, Write}; +use std::path; + +pub fn write_vtk( + file: &str, + dx: f64, + velocity: &[f64], + pressure: &[f64], + cross_section_length: &[f64], +) -> std::io::Result<()> { + let filepath = path::Path::new(file); + if !filepath.parent().unwrap().exists() { + create_dir(filepath.parent().unwrap())?; + } + + // let mut f = File::create(file).expect("Unable to open vtk file"); + let file = File::create(file).expect("Unable to open vtk file"); + let mut f = BufWriter::new(file); + + let n_points = velocity.len(); + + write!(f, "# vtk DataFile Version 2.0\n\n")?; + write!(f, "ASCII\n\n")?; + write!(f, "DATASET UNSTRUCTURED_GRID\n\n")?; + write!(f, "POINTS {n_points} float\n\n")?; + for i in 0..n_points { + writeln!( + f, + "{:.16e} 0.0000000000000000e+00 0.0000000000000000e+00", + i as f64 * dx + )?; + } + writeln!(f)?; + + write!(f, "POINT_DATA {n_points}\n\n")?; + + writeln!(f, "VECTORS velocity float")?; + for v in velocity { + writeln!( + f, + "{:.16e} 0.0000000000000000e+00 0.0000000000000000e+00", + v + )?; + } + writeln!(f)?; + + writeln!(f, "SCALARS pressure float")?; + writeln!(f, "LOOKUP_TABLE default")?; + for v in pressure { + writeln!(f, "{:.16e}", v)?; + } + writeln!(f)?; + + writeln!(f, "SCALARS diameter float")?; + writeln!(f, "LOOKUP_TABLE default")?; + for v in cross_section_length { + writeln!(f, "{:.16e}", v)?; + } + writeln!(f)?; + Ok(()) +} diff --git a/elastic-tube-1d/images/tutorials-elastic-tube-1d-all.png b/elastic-tube-1d/images/tutorials-elastic-tube-1d-all.png new file mode 100644 index 000000000..166b27d4e Binary files /dev/null and b/elastic-tube-1d/images/tutorials-elastic-tube-1d-all.png differ diff --git a/elastic-tube-1d/images/tutorials-elastic-tube-1d-precice-config.png b/elastic-tube-1d/images/tutorials-elastic-tube-1d-precice-config.png new file mode 100644 index 000000000..9e0994de7 Binary files /dev/null and b/elastic-tube-1d/images/tutorials-elastic-tube-1d-precice-config.png differ diff --git a/elastic-tube-1d/metadata.yaml b/elastic-tube-1d/metadata.yaml new file mode 100644 index 000000000..79e66ab61 --- /dev/null +++ b/elastic-tube-1d/metadata.yaml @@ -0,0 +1,44 @@ +name: Elastic tube 1D +path: elastic-tube-1d +url: https://precice.org/tutorials-elastic-tube-1d.html + +participants: + - Fluid + - Solid + +cases: + fluid-cpp: + participant: Fluid + directory: ./fluid-cpp + run: mkdir build && cmake -S . -B build && cmake --build build && ./run.sh + component: bare + + solid-cpp: + participant: Solid + directory: ./solid-cpp + run: mkdir build && cmake -S . -B build && cmake --build build && ./run.sh + 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-rust: + participant: Solid + directory: ./solid-rust + run: ./run.sh + component: bare diff --git a/elastic-tube-1d/plot-all.sh b/elastic-tube-1d/plot-all.sh new file mode 100755 index 000000000..966610234 --- /dev/null +++ b/elastic-tube-1d/plot-all.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +gnuplot -p << EOF + set grid + set term pngcairo enhanced size 900,654 + set output "images/tutorials-elastic-tube-1d-all.png" + + set multiplot layout 2, 1 + set title 'Diameter of elastic-tube at x=5' + + set ylabel 'diameter[m]' + plot \ + "fluid-cpp/precice-Fluid-watchpoint-Middle.log" using 1:4 with linespoints title "cpp", \ + "fluid-python/precice-Fluid-watchpoint-Middle.log" using 1:4 with linespoints lw 2 title "python", \ + "fluid-rust/precice-Fluid-watchpoint-Middle.log" using 1:4 with linespoints title "rust" + + set title 'Pressure of elastic-tube at x=5' + set ylabel 'pressure' + plot \ + "fluid-cpp/precice-Fluid-watchpoint-Middle.log" using 1:5 with linespoints title "cpp", \ + "fluid-python/precice-Fluid-watchpoint-Middle.log" using 1:5 with linespoints title "python", \ + "fluid-rust/precice-Fluid-watchpoint-Middle.log" using 1:5 with linespoints title "rust" + + set xlabel 'time [s]' + +EOF diff --git a/elastic-tube-1d/plot-diameter.sh b/elastic-tube-1d/plot-diameter.sh index f4d31bb82..8d1b17c4e 100755 --- a/elastic-tube-1d/plot-diameter.sh +++ b/elastic-tube-1d/plot-diameter.sh @@ -16,3 +16,10 @@ if [ -n "$(ls -A ./fluid-python/output/*.vtk 2>/dev/null)" ]; then else echo "No results to plot from fluid-python." fi + +# Plot diameter from fluid-rust +if [ -n "$(ls -A ./fluid-rust/output/*.vtk 2>/dev/null)" ]; then + python3 plot-vtk.py diameter fluid-rust/output/out_fluid_ & +else + echo "No results to plot from fluid-python." +fi diff --git a/elastic-tube-1d/precice-config.xml b/elastic-tube-1d/precice-config.xml index 581327626..1bd347d0c 100644 --- a/elastic-tube-1d/precice-config.xml +++ b/elastic-tube-1d/precice-config.xml @@ -4,70 +4,66 @@ - - - + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + + - - - - - - - + + + + + + + - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + 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 new file mode 100644 index 000000000..d74a1ded9 --- /dev/null +++ b/elastic-tube-1d/reference-results/fluid-cpp_solid-cpp.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:501038f52ba09cea3e7d430f26ff8ca88b301e0aa38862ce894cabaf47237490 +size 702367 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 new file mode 100644 index 000000000..075150403 --- /dev/null +++ b/elastic-tube-1d/reference-results/fluid-cpp_solid-python.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0d2520075e8ecdcee88288cf91f8da7af2b805771241200168455ed117b13a6a +size 702553 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 new file mode 100644 index 000000000..882c15b7a --- /dev/null +++ b/elastic-tube-1d/reference-results/fluid-python_solid-python.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:553e17167087ce036096c5319d41e322f28e9fbd9da32a63b28002e26ea023df +size 702971 diff --git a/elastic-tube-1d/reference_results.metadata b/elastic-tube-1d/reference_results.metadata new file mode 100644 index 000000000..242a5ac91 --- /dev/null +++ b/elastic-tube-1d/reference_results.metadata @@ -0,0 +1,65 @@ + + +# 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-cpp_solid-cpp.tar.gz | 2024-04-13 12:00:34 | 501038f52ba09cea3e7d430f26ff8ca88b301e0aa38862ce894cabaf47237490 | +| fluid-python_solid-python.tar.gz | 2024-04-13 12:00:34 | 553e17167087ce036096c5319d41e322f28e9fbd9da32a63b28002e26ea023df | +| fluid-cpp_solid-python.tar.gz | 2024-04-13 12:00:34 | 0d2520075e8ecdcee88288cf91f8da7af2b805771241200168455ed117b13a6a | + +## List of arguments used to generate the files + +| name | value | +|------|------| +| PRECICE_REF | v3.1.1 | +| OPENFOAM_EXECUTABLE | openfoam2312 | +| OPENFOAM_ADAPTER_REF | v1.3.0 | +| PYTHON_BINDINGS_REF | v3.1.0 | +| FENICS_ADAPTER_REF | v2.1.0 | +| TUTORIALS_REF | 340b447 | +| PLATFORM | ubuntu_2204 | +| CALULIX_VERSION | 2.20 | +| CALULIX_ADAPTER_REF | v2.20.1 | +| SU2_VERSION | 7.5.1 | +| SU2_ADAPTER_REF | 64d4aff | +## Information about the machine + +### uname -a + +Linux precice-tests 5.15.0-101-generic #111-Ubuntu SMP Tue Mar 5 20:16:58 UTC 2024 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-1d/solid-cpp/CMakeLists.txt b/elastic-tube-1d/solid-cpp/CMakeLists.txt index e5a8ee5d1..96e5ca92f 100644 --- a/elastic-tube-1d/solid-cpp/CMakeLists.txt +++ b/elastic-tube-1d/solid-cpp/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required (VERSION 3.10) project(ElasticTube LANGUAGES CXX) -set (CMAKE_CXX_STANDARD 11) +set (CMAKE_CXX_STANDARD 17) if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build." FORCE) @@ -15,7 +15,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter") endif() -find_package(precice REQUIRED CONFIG) +find_package(precice 3 REQUIRED CONFIG) add_executable(SolidSolver src/SolidComputeSolution.cpp diff --git a/elastic-tube-1d/solid-cpp/clean.sh b/elastic-tube-1d/solid-cpp/clean.sh index 7330c8aaa..4c864fb36 100755 --- a/elastic-tube-1d/solid-cpp/clean.sh +++ b/elastic-tube-1d/solid-cpp/clean.sh @@ -4,3 +4,4 @@ set -e -u . ../../tools/cleaning-tools.sh clean_precice_logs . +clean_case_logs . diff --git a/elastic-tube-1d/solid-cpp/run.sh b/elastic-tube-1d/solid-cpp/run.sh index 0c72002ce..fe674287d 100755 --- a/elastic-tube-1d/solid-cpp/run.sh +++ b/elastic-tube-1d/solid-cpp/run.sh @@ -1,4 +1,15 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +if [ ! -d build ]; then + mkdir build + cmake -S . -B build + cmake --build build +fi + ./build/SolidSolver ../precice-config.xml + +close_log diff --git a/elastic-tube-1d/solid-cpp/src/SolidComputeSolution.cpp b/elastic-tube-1d/solid-cpp/src/SolidComputeSolution.cpp index 45e3fdcb2..1ac9be73d 100644 --- a/elastic-tube-1d/solid-cpp/src/SolidComputeSolution.cpp +++ b/elastic-tube-1d/solid-cpp/src/SolidComputeSolution.cpp @@ -1,17 +1,19 @@ #include #include "SolidSolver.h" -void SolidComputeSolution(int chunkLength, double const * const pressure, double *crossSectionLength) +void SolidComputeSolution(int chunkLength, double const *const pressure, double *crossSectionLength) { /* * Update displacement of membrane based on pressure data from the fluid solver */ - const double PI = 3.14159265359; - const double E = 10000; - const double c_mk2 = E / 2 * std::sqrt(PI); + const double PI = 3.14159265359; + const double E = 10000; + const double r0 = 1.0 / std::sqrt(PI); + const double c_mk = std::sqrt(E / 2 / r0); + const double c_mk2 = c_mk * c_mk; const double pressure0 = 0.0; + for (int i = 0; i < chunkLength; i++) { - //crossSectionLength[i] = 4.0 / ((2.0 - pressure[i]) * (2.0 - pressure[i])); - crossSectionLength[i] = std::pow((pressure0 - 2.0 * c_mk2) / (pressure[i] - 2.0 * c_mk2), 2); + crossSectionLength[i] = std::pow((pressure0 - 2.0 * c_mk2), 2.0) / std::pow((pressure[i] - 2.0 * c_mk2), 2.0); } } diff --git a/elastic-tube-1d/solid-cpp/src/SolidSolver.cpp b/elastic-tube-1d/solid-cpp/src/SolidSolver.cpp index fad15fa09..c865921ee 100644 --- a/elastic-tube-1d/solid-cpp/src/SolidSolver.cpp +++ b/elastic-tube-1d/solid-cpp/src/SolidSolver.cpp @@ -1,13 +1,12 @@ #include "SolidSolver.h" #include #include -#include "precice/SolverInterface.hpp" +#include "precice/precice.hpp" int main(int argc, char **argv) { std::cout << "Starting Solid Solver..." << std::endl; using namespace precice; - using namespace precice::constants; if (argc != 2) { std::cout << "Fluid: Usage: " << argv[0] << " configurationFileName>" << std::endl; @@ -16,72 +15,60 @@ int main(int argc, char **argv) return -1; } - std::string configFileName(argv[1]); - int domainSize = 100; // N - int chunkLength = domainSize + 1; + std::string configFileName(argv[1]); + const int domainSize = 100; // N + const int chunkLength = domainSize + 1; + const double tubeLength = 10; std::cout << "N: " << domainSize << std::endl; std::cout << "inputs: " << argc << std::endl; const std::string solverName = "Solid"; - SolverInterface interface(solverName, configFileName, 0, 1); + precice::Participant interface(solverName, configFileName, 0, 1); std::cout << "preCICE configured..." << std::endl; - int dimensions = interface.getDimensions(); - int meshID = interface.getMeshID("Solid-Nodes-Mesh"); - int crossSectionLengthID = interface.getDataID("CrossSectionLength", meshID); - int pressureID = interface.getDataID("Pressure", meshID); + auto meshName = "Solid-Nodes-Mesh"; + auto crossSectionLengthName = "CrossSectionLength"; + auto pressureName = "Pressure"; + const int dimensions = interface.getMeshDimensions(meshName); std::vector pressure(chunkLength, 0.0); std::vector crossSectionLength(chunkLength, 1.0); - std::vector grid(dimensions * chunkLength); - for (int i = 0; i < chunkLength; i++) { - for (int j = 0; j < dimensions; j++) { - grid[i * dimensions + j] = i * (1 - j); - } + std::vector grid(dimensions * chunkLength, 0.0); + const double dx = tubeLength / domainSize; + for (int i = 0; i < chunkLength; ++i) { + grid[i * dimensions] = dx * i; } std::vector vertexIDs(chunkLength); - interface.setMeshVertices(meshID, chunkLength, grid.data(), vertexIDs.data()); - - double t = 0; - std::cout << "Initialize preCICE..." << std::endl; - double dt = interface.initialize(); + interface.setMeshVertices(meshName, grid, vertexIDs); - if (interface.isActionRequired(actionWriteInitialData())) { - interface.writeBlockScalarData(crossSectionLengthID, chunkLength, vertexIDs.data(), crossSectionLength.data()); - interface.markActionFulfilled(actionWriteInitialData()); + if (interface.requiresInitialData()) { + interface.writeData(meshName, crossSectionLengthName, vertexIDs, crossSectionLength); } - interface.initializeData(); + std::cout << "Initialize preCICE..." << std::endl; + interface.initialize(); while (interface.isCouplingOngoing()) { - if (interface.isActionRequired(actionWriteIterationCheckpoint())) { - interface.markActionFulfilled(actionWriteIterationCheckpoint()); + if (interface.requiresWritingCheckpoint()) { } + double dt = interface.getMaxTimeStepSize(); - if (interface.isReadDataAvailable()) { - interface.readBlockScalarData(pressureID, chunkLength, vertexIDs.data(), pressure.data()); - } + interface.readData(meshName, pressureName, vertexIDs, dt, pressure); SolidComputeSolution(chunkLength, pressure.data(), crossSectionLength.data()); // Call Solver - if (interface.isWriteDataRequired(dt)) { - interface.writeBlockScalarData(crossSectionLengthID, chunkLength, vertexIDs.data(), crossSectionLength.data()); - } + interface.writeData(meshName, crossSectionLengthName, vertexIDs, crossSectionLength); interface.advance(dt); - if (interface.isActionRequired(actionReadIterationCheckpoint())) { // i.e. fluid not yet converged - interface.markActionFulfilled(actionReadIterationCheckpoint()); - } else { - t += dt; + if (interface.requiresReadingCheckpoint()) { // i.e. fluid not yet converged } } std::cout << "Exiting SolidSolver" << std::endl; - interface.finalize(); return 0; } diff --git a/elastic-tube-1d/solid-cpp/src/SolidSolver.h b/elastic-tube-1d/solid-cpp/src/SolidSolver.h index be7e3934a..1f4332670 100644 --- a/elastic-tube-1d/solid-cpp/src/SolidSolver.h +++ b/elastic-tube-1d/solid-cpp/src/SolidSolver.h @@ -2,4 +2,4 @@ #include -void SolidComputeSolution(int chunkLength, double const * const pressure, double *crossSectionLength); +void SolidComputeSolution(int chunkLength, double const *const pressure, double *crossSectionLength); diff --git a/elastic-tube-1d/solid-python/SolidSolver.py b/elastic-tube-1d/solid-python/SolidSolver.py index 4f600d375..49cf36b83 100644 --- a/elastic-tube-1d/solid-python/SolidSolver.py +++ b/elastic-tube-1d/solid-python/SolidSolver.py @@ -5,9 +5,6 @@ import argparse import numpy as np import precice -from precice import action_write_initial_data, action_read_iteration_checkpoint, \ - action_write_iteration_checkpoint - r0 = 1 / np.sqrt(np.pi) # radius of the tube a0 = r0**2 * np.pi # cross sectional area @@ -40,62 +37,62 @@ def crossSection0(N): print("N: " + str(N)) print("Configure preCICE...") -interface = precice.Interface("Solid", args.configurationFileName, 0, 1) +interface = precice.Participant("Solid", args.configurationFileName, 0, 1) print("preCICE configured...") -dimensions = interface.get_dimensions() +meshName = "Solid-Nodes-Mesh" +crossSectionLengthName = "CrossSectionLength" +pressureName = "Pressure" + +dimensions = interface.get_mesh_dimensions(meshName) pressure = p0 * np.ones(N + 1) crossSectionLength = a0 * np.ones(N + 1) -meshID = interface.get_mesh_id("Solid-Nodes-Mesh") -crossSectionLengthID = interface.get_data_id("CrossSectionLength", meshID) -pressureID = interface.get_data_id("Pressure", meshID) - -vertexIDs = np.zeros(N + 1) +# Define mesh coordinates and register coordinates grid = np.zeros([N + 1, dimensions]) - grid[:, 0] = np.linspace(0, L, N + 1) # x component grid[:, 1] = 0 # np.linspace(0, config.L, N+1) # y component, leave blank -vertexIDs = interface.set_mesh_vertices(meshID, grid) +vertexIDs = interface.set_mesh_vertices(meshName, grid) -t = 0 +if interface.requires_initial_data(): + interface.write_data(meshName, crossSectionLengthName, + vertexIDs, crossSectionLength) print("Solid: init precice...") -# preCICE defines timestep size of solver via precice-config.xml -precice_dt = interface.initialize() - -if interface.is_action_required(action_write_initial_data()): - interface.write_block_scalar_data(crossSectionLengthID, vertexIDs, crossSectionLength) - interface.mark_action_fulfilled(action_write_initial_data()) - -interface.initialize_data() +interface.initialize() -if interface.is_read_data_available(): - pressure = interface.read_block_scalar_data(pressureID, vertexIDs) +# Calculate initial crossSection and local pressure from initial received pressure +pressure = interface.read_data(meshName, pressureName, vertexIDs, 0) crossSection0 = crossSection0(pressure.shape[0] - 1) pressure0 = p0 * np.ones_like(pressure) + +def solve(pressure): + return crossSection0 * ((pressure0 - 2.0 * c_mk ** 2) ** 2 / (pressure - 2.0 * c_mk ** 2) ** 2) + + while interface.is_coupling_ongoing(): # When an implicit coupling scheme is used, checkpointing is required - if interface.is_action_required(action_write_iteration_checkpoint()): - interface.mark_action_fulfilled(action_write_iteration_checkpoint()) + if interface.requires_writing_checkpoint(): + pass - crossSectionLength = crossSection0 * ( - (pressure0 - 2.0 * c_mk ** 2) ** 2 / (pressure - 2.0 * c_mk ** 2) ** 2) + precice_dt = interface.get_max_time_step_size() - interface.write_block_scalar_data(crossSectionLengthID, vertexIDs, crossSectionLength) - precice_dt = interface.advance(precice_dt) - pressure = interface.read_block_scalar_data(pressureID, vertexIDs) + # Read data, solve timestep, and write data + pressure = interface.read_data( + meshName, pressureName, vertexIDs, precice_dt) + crossSectionLength = solve(pressure) + interface.write_data(meshName, crossSectionLengthName, + vertexIDs, crossSectionLength) - if interface.is_action_required(action_read_iteration_checkpoint()): # i.e. not yet converged - interface.mark_action_fulfilled(action_read_iteration_checkpoint()) - else: - t += precice_dt + # Advance the coupling + interface.advance(precice_dt) -print("Exiting SolidSolver") + if interface.requires_reading_checkpoint(): + pass -interface.finalize() +print("Exiting SolidSolver") diff --git a/elastic-tube-1d/solid-python/clean.sh b/elastic-tube-1d/solid-python/clean.sh index 7330c8aaa..4c864fb36 100755 --- a/elastic-tube-1d/solid-python/clean.sh +++ b/elastic-tube-1d/solid-python/clean.sh @@ -4,3 +4,4 @@ set -e -u . ../../tools/cleaning-tools.sh clean_precice_logs . +clean_case_logs . diff --git a/elastic-tube-1d/solid-python/run.sh b/elastic-tube-1d/solid-python/run.sh index ad00c6c38..6e772ed24 100755 --- a/elastic-tube-1d/solid-python/run.sh +++ b/elastic-tube-1d/solid-python/run.sh @@ -1,4 +1,9 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + python3 ./SolidSolver.py ../precice-config.xml + +close_log diff --git a/elastic-tube-1d/solid-rust/Cargo.toml b/elastic-tube-1d/solid-rust/Cargo.toml new file mode 100644 index 000000000..c9de9e33d --- /dev/null +++ b/elastic-tube-1d/solid-rust/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "solid-rust" +version = "0.1.0" +edition = "2021" +publish = false +repository = "https://github.com/precice/tutorials" +description = "The solid participant of the elastic-tube 1D tutorial" +license = "LGPL-3.0-or-later" + +[dependencies] +"precice" = "3" diff --git a/elastic-tube-1d/solid-rust/clean.sh b/elastic-tube-1d/solid-rust/clean.sh new file mode 100755 index 000000000..4c864fb36 --- /dev/null +++ b/elastic-tube-1d/solid-rust/clean.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_precice_logs . +clean_case_logs . diff --git a/elastic-tube-1d/solid-rust/run.sh b/elastic-tube-1d/solid-rust/run.sh new file mode 100755 index 000000000..85bee03f5 --- /dev/null +++ b/elastic-tube-1d/solid-rust/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +cargo run --release ../precice-config.xml + +close_log diff --git a/elastic-tube-1d/solid-rust/src/main.rs b/elastic-tube-1d/solid-rust/src/main.rs new file mode 100644 index 000000000..cf091a832 --- /dev/null +++ b/elastic-tube-1d/solid-rust/src/main.rs @@ -0,0 +1,102 @@ +use std::env; +use std::process::ExitCode; + +mod solver; + +fn main() -> ExitCode { + println!("Starting Solid Solver..."); + + let args: Vec<_> = env::args().collect(); + + if args.len() != 2 { + println!("Fluid: Usage: {} ", args[0]); + return ExitCode::from(1); + } + + let config = &args[1]; + + const DOMAIN_SIZE: usize = 100; + const CHUNK_SIZE: usize = DOMAIN_SIZE + 1; + const TUBE_LENGTH: f64 = 10.0; + + let mut participant = precice::Participant::new("Solid", config, 0, 1); + + println!("preCICE configured..."); + + let mesh_name = "Solid-Nodes-Mesh"; + let dimensions = participant.get_mesh_dimensions(mesh_name); + assert!(participant.get_data_dimensions(mesh_name, "CrossSectionLength") == 1); + assert!(participant.get_data_dimensions(mesh_name, "Pressure") == 1); + + let mut pressure: Vec = vec![0.0; CHUNK_SIZE]; + let mut cross_section_length: Vec = vec![1.0; CHUNK_SIZE]; + + let grid_size = CHUNK_SIZE * dimensions as usize; + let grid: Vec = { + let mut v: Vec = vec![0_f64; grid_size]; + const DX: f64 = TUBE_LENGTH / DOMAIN_SIZE as f64; + for i in 0..CHUNK_SIZE - 1 { + v[i * dimensions as usize] = DX * i as f64; + } + v + }; + + let vertex_ids = { + let mut ids = vec![-1; CHUNK_SIZE]; + participant.set_mesh_vertices(mesh_name, &grid[..], &mut ids[..]); + ids + }; + + if participant.requires_initial_data() { + participant.write_data( + mesh_name, + "CrossSectionLength", + &vertex_ids[..], + &cross_section_length[..], + ); + } + + println!("Initializing preCICE..."); + + participant.initialize(); + + let mut t = 0.0; + while participant.is_coupling_ongoing() { + if participant.requires_writing_checkpoint() { + // no nothing + } + + let dt = participant.get_max_time_step_size(); + + participant.read_data( + mesh_name, + "Pressure", + &vertex_ids[..], + dt, + &mut pressure[..], + ); + + solver::solid_compute_solution(&pressure, &mut cross_section_length); + + participant.write_data( + mesh_name, + "CrossSectionLength", + &vertex_ids[..], + &cross_section_length[..], + ); + + participant.advance(dt); + + if participant.requires_reading_checkpoint() { + // i.e. fluid not yet converged + // do nothing + } else { + t += dt; + } + } + + println!("Exiting SolidSolver at t={}", t); + participant.finalize(); + + ExitCode::SUCCESS +} diff --git a/elastic-tube-1d/solid-rust/src/solver.rs b/elastic-tube-1d/solid-rust/src/solver.rs new file mode 100644 index 000000000..2a37a227c --- /dev/null +++ b/elastic-tube-1d/solid-rust/src/solver.rs @@ -0,0 +1,11 @@ +pub fn solid_compute_solution(pressure: &[f64], cross_section_length: &mut [f64]) { + assert!(pressure.len() == cross_section_length.len()); + const E: f64 = 10000.0; + const C_MK2: f64 = E / std::f64::consts::FRAC_2_SQRT_PI; + const PRESSURE0: f64 = 0.0; + let new: Vec<_> = pressure + .iter() + .map(|p| ((PRESSURE0 - 2.0 * C_MK2) / (p - 2.0 * C_MK2)).powi(2)) + .collect(); + cross_section_length.copy_from_slice(&new[..]); +} diff --git a/elastic-tube-3d/README.md b/elastic-tube-3d/README.md index 30bf09493..34377b7ab 100644 --- a/elastic-tube-3d/README.md +++ b/elastic-tube-3d/README.md @@ -15,6 +15,12 @@ The expanding tube test case involves a cylindrical fluid domain surrounded by a The expanding tube test case comes with the interface surface mesh connectivity of the solid domain. This allows the use of nearest-projection mapping of the displacements of the solid domain. In order to run the example with nearest projection mapping, the "node-mesh-with-connectivity" has been specified in the `solid-calculix/config.yml` file. More details can be found in the [CalculiX configuration description](https://www.precice.org/adapter-calculix-config.html#nearest-projection-mapping). +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-elastic-tube-3d-precice-config.png) + ## Available solvers Fluid participant: @@ -37,7 +43,7 @@ You can visualize the results using paraView or `cgx`(for native CalculiX result ![result tube](images/tutorials-elastic-tube-3d-tube-result.png) -You can also plot the displacement of the midpoint of the tube by running `sh plot-displacement.sh `. The displacement plot for each solver combination looks like: +You can also plot the displacement of the midpoint of the tube for each participant individually by running `sh plot-displacements.sh `. If you have run all the solver combinations and want to compare the plots, you can run `sh plot-all-displacements.sh` which looks like: ![plot tube](images/tutorials-elastic-tube-3d-plot.png) diff --git a/elastic-tube-3d/fluid-openfoam/run.sh b/elastic-tube-3d/fluid-openfoam/run.sh index c305d6d9b..9d072bcda 100755 --- a/elastic-tube-3d/fluid-openfoam/run.sh +++ b/elastic-tube-3d/fluid-openfoam/run.sh @@ -1,8 +1,12 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + cp -r constant/polyMesh.orig constant/polyMesh -touch fluid-openfoam.foam ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/elastic-tube-3d/fluid-openfoam/system/fvSolution b/elastic-tube-3d/fluid-openfoam/system/fvSolution index 40c25c2b6..2a5f351e6 100755 --- a/elastic-tube-3d/fluid-openfoam/system/fvSolution +++ b/elastic-tube-3d/fluid-openfoam/system/fvSolution @@ -209,6 +209,25 @@ outerResidualControl } */ +// OpenFOAM 9 (.org) or newer +// see also https://github.com/OpenFOAM/OpenFOAM-dev/commit/4c8122783aedaa7dadf0486163a98350e625db32 +/* +outerCorrectorResidualControl +{ +U +{ + tolerance 1e-5; + relTol 0; +} + +p +{ + tolerance 1e-5; + relTol 0; +} +} +*/ + relaxationFactors { U 0.5; diff --git a/elastic-tube-3d/images/tutorials-elastic-tube-3d-plot.png b/elastic-tube-3d/images/tutorials-elastic-tube-3d-plot.png index 3eae44a0f..37a79255e 100644 Binary files a/elastic-tube-3d/images/tutorials-elastic-tube-3d-plot.png and b/elastic-tube-3d/images/tutorials-elastic-tube-3d-plot.png differ diff --git a/elastic-tube-3d/images/tutorials-elastic-tube-3d-precice-config.png b/elastic-tube-3d/images/tutorials-elastic-tube-3d-precice-config.png new file mode 100644 index 000000000..eca931670 Binary files /dev/null and b/elastic-tube-3d/images/tutorials-elastic-tube-3d-precice-config.png differ diff --git a/elastic-tube-3d/images/tutorials-elastic-tube-3d-tube-result.png b/elastic-tube-3d/images/tutorials-elastic-tube-3d-tube-result.png index ff8fb2c5e..80764d5a4 100644 Binary files a/elastic-tube-3d/images/tutorials-elastic-tube-3d-tube-result.png and b/elastic-tube-3d/images/tutorials-elastic-tube-3d-tube-result.png differ diff --git a/elastic-tube-3d/metadata.yaml b/elastic-tube-3d/metadata.yaml new file mode 100644 index 000000000..04b45db3c --- /dev/null +++ b/elastic-tube-3d/metadata.yaml @@ -0,0 +1,28 @@ +name: Elastic tube 3D +path: elastic-tube-3d # relative to git repo +url: https://precice.org/tutorials-elastic-tube-3d.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 + + solid-fenics: + participant: Solid + directory: ./solid-fenics + run: ./run.sh + component: fenics-adapter + + diff --git a/elastic-tube-3d/plot-all-displacements.sh b/elastic-tube-3d/plot-all-displacements.sh index 128f7ca03..b293f9b03 100755 --- a/elastic-tube-3d/plot-all-displacements.sh +++ b/elastic-tube-3d/plot-all-displacements.sh @@ -2,7 +2,7 @@ gnuplot -p << EOF set grid - set title 'displacement at the middle of the tube + set title 'displacement at the middle of the tube' set xlabel 'time [s]' set ylabel 'displacement [m]' set term pngcairo enhanced size 900,654 diff --git a/elastic-tube-3d/plot-displacements.sh b/elastic-tube-3d/plot-displacements.sh new file mode 100755 index 000000000..757aa5b20 --- /dev/null +++ b/elastic-tube-3d/plot-displacements.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +if [ "${1:-}" = "" ]; then + echo "No target directory specified. Please specify the directory of the solid participant containing the watchpoint, e.g. ./plot-displacements.sh solid-calculix." + exit 1 +fi + +FILE="$1/precice-Solid-watchpoint-Tube-Midpoint.log" + +if [ ! -f "$FILE" ]; then + echo "Unable to locate the watchpoint file (precice-Solid-watchpoint-Tube-Midpoint.log) in the specified solid directory '${1}'. Make sure the specified directory matches the solid participant you used for the calculations." + exit 1 +fi + +gnuplot -p << EOF + set grid + set title 'displacement of the tube midpoint' + set xlabel 'time [s]' + set ylabel 'displacement of the tube midpoint [m]' + set term pngcairo enhanced size 900,654 + set output "images/tutorials-elastic-tube-3d-displacement-watchpoints.png" + plot "$1/precice-Solid-watchpoint-Tube-Midpoint.log" using 1:5 with lines title "$1 tube midpoint circumferential", \ + "$1/precice-Solid-watchpoint-Tube-Midpoint.log" using 1:6 with lines title "$1 tube midpoint radial", \ + "$1/precice-Solid-watchpoint-Tube-Midpoint.log" using 1:7 with lines title "$1 tube midpoint axial" +EOF + +echo "Plot saved in images/tutorials-elastic-tube-3d-displacement-watchpoints.png" diff --git a/elastic-tube-3d/precice-config.xml b/elastic-tube-3d/precice-config.xml index ff3ee9296..05e5ed421 100644 --- a/elastic-tube-3d/precice-config.xml +++ b/elastic-tube-3d/precice-config.xml @@ -7,69 +7,64 @@ enabled="true" /> - - - + + - - - + + + - - - + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - - - - - - + + + + + + - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/elastic-tube-3d/solid-calculix/run.sh b/elastic-tube-3d/solid-calculix/run.sh index 5ebdaf5b2..6e8b5a83f 100755 --- a/elastic-tube-3d/solid-calculix/run.sh +++ b/elastic-tube-3d/solid-calculix/run.sh @@ -1,6 +1,11 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + export OMP_NUM_THREADS=1 export CCX_NPROC_EQUATION_SOLVER=1 ccx_preCICE -i tube -precice-participant Solid + +close_log diff --git a/elastic-tube-3d/solid-fenics/run.sh b/elastic-tube-3d/solid-fenics/run.sh index 15315c67d..2c9d2da09 100755 --- a/elastic-tube-3d/solid-fenics/run.sh +++ b/elastic-tube-3d/solid-fenics/run.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash set -e -u python3 solid.py diff --git a/elastic-tube-3d/solid-fenics/solid.py b/elastic-tube-3d/solid-fenics/solid.py index bef8cfd4f..54f18fd21 100644 --- a/elastic-tube-3d/solid-fenics/solid.py +++ b/elastic-tube-3d/solid-fenics/solid.py @@ -1,9 +1,8 @@ # Import required libs from fenics import Constant, Function, AutoSubDomain, VectorFunctionSpace, interpolate, \ - TrialFunction, TestFunction, Point, Expression, DirichletBC, nabla_grad, \ - Identity, inner, dx, ds, sym, grad, lhs, rhs, dot, File, solve, assemble_system + TrialFunction, TestFunction, Point, Expression, DirichletBC, \ + Identity, inner, dx, ds, sym, grad, div, lhs, rhs, dot, File, solve, assemble_system from mshr import Cylinder, generate_mesh -from ufl import nabla_div import numpy as np from fenicsprecice import Adapter import math @@ -65,7 +64,8 @@ def neumann_boundary(x, on_boundary): precice = Adapter(adapter_config_filename="precice-adapter-config-fsi-s.json") # Initialize the coupling interface -precice_dt = precice.initialize(coupling_boundary, read_function_space=V, write_object=V, fixed_boundary=fixed_boundary) +precice.initialize(coupling_boundary, read_function_space=V, write_object=V, fixed_boundary=fixed_boundary) +precice_dt = precice.get_max_time_step_size() fenics_dt = precice_dt # if fenics_dt == precice_dt, no subcycling is applied dt = Constant(np.min([precice_dt, fenics_dt])) @@ -82,12 +82,12 @@ def neumann_boundary(x, on_boundary): # Define strain def epsilon(u): - return 0.5 * (nabla_grad(u) + nabla_grad(u).T) + return 0.5 * (grad(u) + grad(u).T) # Define Stress tensor def sigma(u): - return lambda_ * nabla_div(u) * Identity(dim) + 2 * mu * epsilon(u) + return lambda_ * div(u) * Identity(dim) + 2 * mu * epsilon(u) # Define Mass form @@ -168,15 +168,18 @@ def avg(x_old, x_new, alpha): u_n.rename("Displacement", "") u_np1.rename("Displacement", "") -displacement_out << u_n +displacement_out << (u_n, t) while precice.is_coupling_ongoing(): - if precice.is_action_required(precice.action_write_iteration_checkpoint()): # write checkpoint + if precice.requires_writing_checkpoint(): # write checkpoint precice.store_checkpoint(u_n, t, n) + precice_dt = precice.get_max_time_step_size() + dt = Constant(np.min([precice_dt, fenics_dt])) + # read data from preCICE and get a new coupling expression - read_data = precice.read_data() + read_data = precice.read_data(dt) # Update the point sources on the coupling boundary with the new read data forces_x, forces_y, forces_z = precice.get_point_sources(read_data) @@ -195,17 +198,15 @@ def avg(x_old, x_new, alpha): assert (b is not b_forces) solve(A, u_np1.vector(), b_forces) - dt = Constant(np.min([precice_dt, fenics_dt])) - # Write relative displacements to preCICE u_delta.vector()[:] = u_np1.vector()[:] - u_n.vector()[:] precice.write_data(u_delta) # Call to advance coupling, also returns the optimum time step value - precice_dt = precice.advance(dt(0)) + precice.advance(dt(0)) # Either revert to old step if timestep has not converged or move to next timestep - if precice.is_action_required(precice.action_read_iteration_checkpoint()): # roll back to checkpoint + if precice.requires_reading_checkpoint(): # roll back to checkpoint u_cp, t_cp, n_cp = precice.retrieve_checkpoint() u_n.assign(u_cp) t = t_cp @@ -221,6 +222,6 @@ def avg(x_old, x_new, alpha): displacement_out << (u_n, t) # Plot tip displacement evolution -displacement_out << u_n +displacement_out << (u_n, t) precice.finalize() diff --git a/flow-around-controlled-moving-cylinder/.gitignore b/flow-around-controlled-moving-cylinder/.gitignore new file mode 100644 index 000000000..043bb5f18 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/.gitignore @@ -0,0 +1,3 @@ +controller-fmi/PIDcontroller.fmu +controller-fmi/output/ +fluid-openfoam/0/ # Since we start from 0.orig diff --git a/flow-around-controlled-moving-cylinder/README.md b/flow-around-controlled-moving-cylinder/README.md new file mode 100644 index 000000000..7b3ed5968 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/README.md @@ -0,0 +1,120 @@ +--- +title: Flow around controlled moving cylinder +permalink: tutorials-flow-around-controlled-moving-cylinder.html +keywords: FMI, FSI, OpenFOAM, controller, multi coupling, PID +summary: Flow around a rigid moving cylinder. A FMI-based controller is used to dampen out the oscillation. +--- + +{% note %} +Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/flow-around-controlled-moving-cylinder). Read how in the [tutorials introduction](https://www.precice.org/tutorials.html). +{% endnote %} + +## Setup + +We simulate a 2D flow around a cylinder. The cylinder is not fixed, but mounted on a spring-damper system which allows it to move in the y-direction. The vortex shedding of the flow brings the cylinder to oscillate up and down. This setup has received attention as a test case for numerical simulations [2] in the past and is backed up with experimental data [3]. The oscillation can be counteracted by moving the root point of the spring [4]. To adjust the root point accordingly, a PID controller is implemented. The full setup is shown below: + +![Setup of flow around controlled moving cylinder](images/tutorials-flow-around-controlled-moving-cylinder-setup.png) + +This case was contributed by Leonard Willeke et al. [1]. To reduce the overall runtime compared to the original contribution, this case uses a larger time step size 2.5e-3 (instead of 1e-3) and the controller switches on at t=2 (instead of t=40). Still, the scenario requires around an hour to complete. + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-flow-around-controlled-moving-cylinder-precice-config.png) + +## Available solvers + +OpenFOAM is used for the `Fluid` participant. The spring-damper system is solved in a separate Python `Solid` participant. Finally, the PID algorithm is calculated in an FMU as participant `Controller`. + +- *OpenFOAM*: To run this case, you need the preCICE [OpenFOAM Adapter](https://precice.org/adapter-openfoam-get.html). OpenFOAM is used to simulate the laminar flow around the cylinder with the solver `pimpleFoam`. +- *FMI*: A solver using the [preCICE-FMI Runner](https://github.com/precice/fmi-runner) (requires at least v0.2). The Runner executes the FMU model `PIDcontroller.fmu` for computation. The provided run script (see below) builds this model if not already there. If you want to change the model parameters or simulation setup, have a look inside `fmi-settings.json` and `precice-settings.json` (see folder `controller-fmi`). +- *Python*: A python script solving the spring damper system. It uses the preCICE [Python bindings](https://www.precice.org/installation-bindings-python.html) and depends on the Python library `numpy`. You can install `numpy` from your system package manager or with `pip3 install --user `. + +## Running the simulation + +Open three separate terminals. The commands for the `Solid` and the `Controller` are: + +```bash +cd solid-python +./run.sh +``` + +and + +```bash +cd controller-fmi +./run.sh +``` + +For the `Fluid` participant, you can run OpenFOAM either in serial or in parallel. To run the case in serial, you can use the same command as before + +```bash +cd fluid-openfoam +./run.sh +``` + +while for the parallel computation, you need to set an additional flag + +```bash +cd fluid-openfoam +./run.sh -parallel +``` + +## Post-processing + +There are multiple options for post-processing, depending on what you want to visualize. + +### Plot displacement and forces + +The `Solid` participant writes a `watchpoint` during the simulation. To plot this data in four individual windows, run the command + +```bash +./plot-watchpoint.sh solid-python +``` + +The displacement of the cylinder clearly shows the onset of the controller after t=2: + +![Displacement of controlled moving cylinder](images/tutorials-flow-around-controlled-moving-cylinder-watchpoint.png) + +### Plot controller variables + +Upon completion of the scenario, the preCICE-FMI Runner stores some of the internal controller variables such as output values and the terms of the different gains. To plot for example the error between measured and wanted state, run the command + +```bash +python3 plot-timeseries.py ./controller-fmi/output/controller-output.csv E_OVER_T +``` + +To get a full list of the plot options, run `python3 plot-timeseries.py -h`. Please note: This script requires a few standard python libraries (pandas, matplotlib, argparse, enum). + +### View the simulation results in ParaView + +OpenFOAM creates `.vtk` files during the simulation which you can visualize and animate in [ParaView](https://www.paraview.org/download/). To do so, run + +```bash +cd fluid-openfoam +paraFoam +``` + +The displacements of the cylinder are very small, however, and, thus, not directly visible. With a `WarpByVector` filter based on the `cellDisplacement` data, try scaling them up by a factor of 100. + +## Acknowledgements + +Many thanks to [Mosayeb Shams](https://github.com/mosayebshams) from Herriot Watt University, UK, who helped to set up this simulation case. + +## Sources + +- The general idea was taken from [4]. +- The OpenFOAM case files make use of the following work: + - An [OpenFOAM tutorial](https://gitlab.com/mAlletto/openfoamtutorials/-/tree/master/transverseRe100m*10) to study vortex induced vibrations on a 2D cylinder + - An [online article](https://curiosityfluids.com/2016/07/19/oscillating-cylinder-in-crossflow-pimpledymfoam/) discussing the setup of a similar OpenFOAM case + +## References + +[1] L. Willeke, D. Schneider, B. Uekermann, [A preCICE-FMI Runner to Couple FMUs to PDE-Based Simulations](https://doi.org/10.3384/ecp204479), Proceedings 15th Intern. Modelica Conference, 2023 + +[2] Placzek, A. and Sigrist, J.F. and Hamdouni, A. [Numerical Simulation of an oscillating cylinder in a cross-flow at low Reynolds number: Forced and free oscillations](https://dx.doi.org/10.1016/j.compfluid.2008.01.007), Computers and Fluids, 2009, 38 (1), pp.80-100 + +[3] Anagnostopoulus, P. and Bearman, P.W. Response Characteristics of a vortex-excited cylinder at low Reynolds numbers, Journal of Fluids and Structures, January 1992, DOI: 10.1016/0889-9746(92)90054-7 + +[4] Sicklinger, S. [Stabilized Co-Simulation of Coupled Problems including Fields and Signals](https://www.researchgate.net/publication/269705153_Stabilized_Co-Simulation_of_Coupled_Problems_Including_Fields_and_Signals), Technical University of Munich, Dissertation diff --git a/flow-around-controlled-moving-cylinder/clean-tutorial.sh b/flow-around-controlled-moving-cylinder/clean-tutorial.sh new file mode 100755 index 000000000..7cc460c25 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/clean-tutorial.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -e -u + +# shellcheck disable=SC1091 +. ../tools/cleaning-tools.sh + +clean_tutorial . +clean_precice_logs . diff --git a/partitioned-heat-conduction/nutils/clean.sh b/flow-around-controlled-moving-cylinder/controller-fmi/clean.sh similarity index 80% rename from partitioned-heat-conduction/nutils/clean.sh rename to flow-around-controlled-moving-cylinder/controller-fmi/clean.sh index 6684cc729..d4e26a453 100755 --- a/partitioned-heat-conduction/nutils/clean.sh +++ b/flow-around-controlled-moving-cylinder/controller-fmi/clean.sh @@ -3,4 +3,4 @@ set -e -u . ../../tools/cleaning-tools.sh -clean_nutils +clean_fmi . diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmi-settings.json b/flow-around-controlled-moving-cylinder/controller-fmi/fmi-settings.json new file mode 100644 index 000000000..85569c5b7 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmi-settings.json @@ -0,0 +1,28 @@ +{ + "simulation_params": { + "fmu_file_name": "./PIDcontroller.fmu", + "output_file_name": "./output/controller-output.csv", + "output": ["e", "P", "I", "D", "u_1", "u_2", "y_1", "y_2"], + "fmu_read_data_names": ["y_1", "y_2"], + "fmu_write_data_names":["u_1", "u_2"], + "fmu_instance_name": "pid_controller" + }, + "model_params": { + "r": 0.0, + "use_implicit_method": true, + "compute_u_1": false + }, + "initial_conditions": { + "kp": 0, + "ki": 0, + "kd": 0 + + }, + "input_signals": { + "names": ["time", "kp", "ki", "kd"], + "data": [ + [0.0, 0.0, 0.0, 0.0], + [2.0, 0.02, 0.02, 0.01] + ] + } +} diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/CMakeLists.txt b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/CMakeLists.txt new file mode 100644 index 000000000..4205e0681 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/CMakeLists.txt @@ -0,0 +1,273 @@ +cmake_minimum_required (VERSION 3.16) + +set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + +FUNCTION(cat IN_FILE OUT_FILE) + file(READ ${IN_FILE} CONTENTS) + file(APPEND ${OUT_FILE} "${CONTENTS}") +ENDFUNCTION() + +project (Reference-FMUs) + +find_package (Python3) +find_package (Git) + +set(FMI_VERSION 2 CACHE STRING "FMI Version") +set_property(CACHE FMI_VERSION PROPERTY STRINGS 1 2 3) + +set(FMI_TYPE ME CACHE STRING "FMI Type (FMI 1.0 only)") +set_property(CACHE FMI_TYPE PROPERTY STRINGS ME CS) + +if (${FMI_VERSION} GREATER 1) + set(FMI_TYPE "") +endif () + +set(WITH_FMUSIM OFF CACHE BOOL "Add fmusim project") + +if (MSVC) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) + + # Minimum supported MSVC version is 1800 = Visual Studio 12.0/2013 + # See also https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html + if (MSVC_VERSION VERSION_LESS 1800) + message (SEND_ERROR "MSVC_VERSION ${MSVC_VERSION} is not a supported Visual Studio compiler version. Please use Visual Studio 2013 or any later version.") + endif () +endif () + +add_compile_definitions(FMI_VERSION=${FMI_VERSION}) + +if (${FMI_VERSION} GREATER 2) + + if (WIN32) + set(FMI_PLATFORM windows) + elseif (APPLE) + set(FMI_PLATFORM darwin) + else () + set(FMI_PLATFORM linux) + endif () + + if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8") + set (FMI_PLATFORM x86_64-${FMI_PLATFORM}) + else () + set (FMI_PLATFORM x86-${FMI_PLATFORM}) + endif () + +else () + + if (WIN32) + set(FMI_PLATFORM win) + elseif (APPLE) + set(FMI_PLATFORM darwin) + else () + set(FMI_PLATFORM linux) + endif () + + if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8") + set (FMI_PLATFORM ${FMI_PLATFORM}64) + else () + set (FMI_PLATFORM ${FMI_PLATFORM}32) + endif () + +endif () + +MESSAGE("FMI_PLATFORM: " ${FMI_PLATFORM}) + +if (${FMI_VERSION} LESS 3) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/all.c" "#define FMI_VERSION ${FMI_VERSION} + +#include \"fmi${FMI_VERSION}Functions.c\" +#include \"model.c\" +#include \"cosimulation.c\" +") +endif () + +set (MODEL_NAMES PIDcontroller) + +foreach (MODEL_NAME ${MODEL_NAMES}) + +set(TARGET_NAME ${MODEL_NAME}) + +SET(HEADERS + ${MODEL_NAME}/config.h + include/cosimulation.h + include/model.h +) + +if (${FMI_VERSION} EQUAL 2) + SET(HEADERS + ${HEADERS} + include/fmi2Functions.h + include/fmi2FunctionTypes.h + include/fmi2TypesPlatform.h + ) +elseif (${FMI_VERSION} EQUAL 3) + SET(HEADERS + ${HEADERS} + include/fmi3Functions.h + include/fmi3FunctionTypes.h + include/fmi3PlatformTypes.h + ) +endif() + +SET(SOURCES + ${MODEL_NAME}/model.c + src/fmi${FMI_VERSION}Functions.c + src/cosimulation.c +) + +add_library(${TARGET_NAME} SHARED + ${HEADERS} + ${SOURCES} + ${MODEL_NAME}/FMI${FMI_VERSION}${FMI_TYPE}.xml +) + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../..) + +target_compile_definitions(${TARGET_NAME} PRIVATE + DISABLE_PREFIX +) + +if (MSVC) + target_compile_options(${TARGET_NAME} PRIVATE /W4 /WX) +else() + target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra -Wpedantic -Werror) +endif() + +if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET_NAME} PRIVATE "-static-libgcc") +endif() + +if (CMAKE_C_COMPILER_ID STREQUAL "Intel") + target_link_options(${TARGET_NAME} PRIVATE "-static-intel" "-static-libgcc") +endif() + +if (${FMI_VERSION} EQUAL 1 AND "${FMI_TYPE}" STREQUAL CS) + target_compile_definitions(${TARGET_NAME} PRIVATE FMI_COSIMULATION) +endif() + +target_include_directories(${TARGET_NAME} PRIVATE + include + ${MODEL_NAME} +) + +set(FMU_BUILD_DIR temp/${MODEL_NAME}) + +set_target_properties(${TARGET_NAME} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + RUNTIME_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + RUNTIME_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + LIBRARY_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + LIBRARY_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + LIBRARY_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + ARCHIVE_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" +) + +set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "") +set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${MODEL_NAME}) + +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib) + +# modelDescription.xml +add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/FMI${FMI_VERSION}${FMI_TYPE}.xml + "${FMU_BUILD_DIR}/modelDescription.xml" +) + +if (${Python3_Interpreter_FOUND} AND ${Git_FOUND}) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/set_tool_version.py" + "${FMU_BUILD_DIR}/modelDescription.xml" "${GIT_EXECUTABLE}" + ) +endif() + +# model specific header and source +foreach (SOURCE_FILE config.h model.c) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/${SOURCE_FILE}" + "${FMU_BUILD_DIR}/sources/${SOURCE_FILE}" + ) +endforeach(SOURCE_FILE) + +# documentation +if (${FMI_VERSION} EQUAL 1) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/readme.html" + "${FMU_BUILD_DIR}/documentation/_main.html" + ) +else() + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/readme.html" + "${FMU_BUILD_DIR}/documentation/index.html" + ) +endif() + +# license +add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/LICENSE.txt" + "${FMU_BUILD_DIR}/documentation/LICENSE.txt" +) + +# common headers +foreach (SOURCE_FILE model.h cosimulation.h) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/include/${SOURCE_FILE}" + "${FMU_BUILD_DIR}/sources/${SOURCE_FILE}" + ) +endforeach(SOURCE_FILE) + +# common sources +foreach (SOURCE_FILE fmi${FMI_VERSION}Functions.c cosimulation.c) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/src/${SOURCE_FILE}" + "${FMU_BUILD_DIR}/sources/${SOURCE_FILE}" + ) +endforeach(SOURCE_FILE) + +# all.c / buildDescription.xml +if (${FMI_VERSION} LESS 3) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_BINARY_DIR}/all.c" + "${FMU_BUILD_DIR}/sources/all.c" + ) +else() + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/buildDescription.xml" + "${FMU_BUILD_DIR}/sources/buildDescription.xml" + ) +endif() + +set(ARCHIVE_FILES "modelDescription.xml" "binaries" "documentation" "sources") + +if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/resources") + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/resources" + "${FMU_BUILD_DIR}/resources/" + ) + set(ARCHIVE_FILES ${ARCHIVE_FILES} "resources") +endif() + +# delete unintended files from binaries (Release configuration only) +if (MSVC) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND if $ neq 0 ( + ${CMAKE_COMMAND} -E rm -f + "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}/${MODEL_NAME}.exp" + "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}/${MODEL_NAME}.lib" + ) + ) +endif() + +# create ZIP archive +add_custom_command(TARGET ${TARGET_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E tar "cfv" ${CMAKE_CURRENT_BINARY_DIR}/${MODEL_NAME}.fmu --format=zip + ${ARCHIVE_FILES} + WORKING_DIRECTORY ${FMU_BUILD_DIR} COMMENT "Creating ZIP archive" +) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${MODEL_NAME}.fmu DESTINATION ${CMAKE_INSTALL_PREFIX}) + +endforeach(MODEL_NAME) + +if (WITH_FMUSIM) + add_subdirectory(fmusim) +endif () diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/FMI1CS.xml b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/FMI1CS.xml new file mode 100644 index 000000000..1cec06a90 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/FMI1CS.xml @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/FMI1ME.xml b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/FMI1ME.xml new file mode 100644 index 000000000..3408f64d6 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/FMI1ME.xml @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/FMI2.xml b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/FMI2.xml new file mode 100644 index 000000000..8bcc5c706 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/FMI2.xml @@ -0,0 +1,214 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/FMI3.xml b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/FMI3.xml new file mode 100644 index 000000000..92e8aeb7a --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/FMI3.xml @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/buildDescription.xml b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/buildDescription.xml new file mode 100644 index 000000000..12ec75970 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/buildDescription.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/config.h b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/config.h new file mode 100644 index 000000000..e5d2dfe0b --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/config.h @@ -0,0 +1,69 @@ +#ifndef config_h +#define config_h + +#include // for bool + +// define class name and unique id +#define MODEL_IDENTIFIER PIDcontroller +#define INSTANTIATION_TOKEN "{1AE5E10D-9521-4DE3-80B9-D0EAAA7D5AF1}" + +#define CO_SIMULATION +#define MODEL_EXCHANGE + +// define model size +#define NX 2 +#define NZ 1 + +#define SET_FLOAT64 +#define SET_BOOLEAN +#define GET_OUTPUT_DERIVATIVE +#define GET_BOOLEAN +#define EVENT_UPDATE + +#define FIXED_SOLVER_STEP 1e-3 +#define DEFAULT_STOP_TIME 3 + +typedef enum { + + vr_time, + vr_r, + vr_e, + vr_e_ls, + vr_kp, + vr_ki, + vr_kd, + vr_P, + vr_I, + vr_D, + vr_y_1, + vr_y_2, + vr_u_1, + vr_u_2, + vr_I_max, + vr_use_implicit_method, + vr_compute_u_1 + +} ValueReference; + +typedef struct { + + double r; + double e; + double e_ls; + double kp; + double ki; + double kd; + double P; + double I; + double D; + double y_1; + double y_2; + double u_1; + double u_2; + double I_max; + bool use_implicit_method; + bool compute_u_1; + +} ModelData; + +#endif /* config_h */ diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/model.c b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/model.c new file mode 100644 index 000000000..bd21edd82 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/model.c @@ -0,0 +1,219 @@ +#include "model.h" +#include // for DBL_MIN +#include // for fabs() +#include "config.h" + +#define V_MIN (0.1) +#define EVENT_EPSILON (1e-10) + +void setStartValues(ModelInstance *comp) +{ + + M(r) = 0; + M(e_ls) = 0; + M(kp) = 0; + M(ki) = 0; + M(kd) = 0; + M(P) = 0; + M(I) = 0; + M(D) = 0; + M(y_1) = 0; + M(y_2) = 0; + M(u_1) = 0; + M(u_2) = 0; + M(I_max) = 100; + + M(use_implicit_method) = false; + M(compute_u_1) = true; +} + +Status calculateValues(ModelInstance *comp) +{ + + UNUSED(comp); + return OK; +} + +Status getFloat64(ModelInstance *comp, ValueReference vr, double *value, size_t *index) +{ + switch (vr) { + case vr_time: + value[(*index)++] = comp->time; + return OK; + case vr_r: + value[(*index)++] = M(r); + return OK; + case vr_e: + value[(*index)++] = M(e); + return OK; + case vr_e_ls: + value[(*index)++] = M(e_ls); + return OK; + case vr_kp: + value[(*index)++] = M(kp); + return OK; + case vr_ki: + value[(*index)++] = M(ki); + return OK; + case vr_kd: + value[(*index)++] = M(kd); + return OK; + case vr_P: + value[(*index)++] = M(P); + return OK; + case vr_I: + value[(*index)++] = M(I); + return OK; + case vr_D: + value[(*index)++] = M(D); + return OK; + case vr_y_1: + value[(*index)++] = M(y_1); + return OK; + case vr_y_2: + value[(*index)++] = M(y_2); + return OK; + case vr_u_1: + value[(*index)++] = M(u_1); + return OK; + case vr_u_2: + value[(*index)++] = M(u_2); + return OK; + case vr_I_max: + value[(*index)++] = M(I_max); + return OK; + default: + logError(comp, "Get Float64 is not allowed for value reference %u.", vr); + return Error; + } +} + +Status getBoolean(ModelInstance *comp, ValueReference vr, bool *value, size_t *index) +{ + + switch (vr) { + case vr_use_implicit_method: + value[(*index)++] = M(use_implicit_method); + break; + case vr_compute_u_1: + value[(*index)++] = M(compute_u_1); + break; + default: + logError(comp, "Get Boolean is not allowed for value reference %u.", vr); + return Error; + } + + return OK; +} + +Status setFloat64(ModelInstance *comp, ValueReference vr, const double *value, size_t *index) +{ + switch (vr) { + + case vr_r: + M(r) = value[(*index)++]; + return OK; + case vr_kp: + M(kp) = value[(*index)++]; + return OK; + case vr_ki: + M(ki) = value[(*index)++]; + return OK; + case vr_kd: + M(kd) = value[(*index)++]; + return OK; + case vr_y_1: + M(y_1) = value[(*index)++]; + return OK; + case vr_y_2: + M(y_2) = value[(*index)++]; + return OK; + case vr_I_max: + M(I_max) = value[(*index)++]; + return OK; + default: + logError(comp, "Unexpected value reference: %u.", vr); + return Error; + } +} + +Status setBoolean(ModelInstance *comp, ValueReference vr, const bool *value, size_t *index) +{ + + switch (vr) { + case vr_use_implicit_method: + M(use_implicit_method) = value[(*index)++]; + break; + case vr_compute_u_1: + M(compute_u_1) = value[(*index)++]; + break; + default: + logError(comp, "Set Boolean is not allowed for value reference %u.", vr); + return Error; + } + + comp->isDirtyValues = true; + + return OK; +} + +Status getOutputDerivative(ModelInstance *comp, ValueReference valueReference, int order, double *value) +{ + + if (order != 1) { + logError(comp, "The output derivative order %d for value reference %u is not available.", order, valueReference); + return Error; + } + + switch (valueReference) { + + default: + logError(comp, "The output derivative for value reference %u is not available.", valueReference); + return Error; + } + + UNUSED(value); +} + +void eventUpdate(ModelInstance *comp) +{ + + if (false) { + + } else { + comp->valuesOfContinuousStatesChanged = false; + } + + comp->nominalsOfContinuousStatesChanged = false; + comp->terminateSimulation = false; + comp->nextEventTimeDefined = false; +} + +void getContinuousStates(ModelInstance *comp, double x[], size_t nx) +{ + UNUSED(comp); + UNUSED(nx); + UNUSED(x); +} + +void setContinuousStates(ModelInstance *comp, const double x[], size_t nx) +{ + UNUSED(comp); + UNUSED(nx); + UNUSED(x); +} + +void getDerivatives(ModelInstance *comp, double dx[], size_t nx) +{ + UNUSED(comp); + UNUSED(nx); + UNUSED(dx); +} + +void getEventIndicators(ModelInstance *comp, double z[], size_t nz) +{ + + UNUSED(nz); + UNUSED(comp); + UNUSED(z); +} diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/readme.html b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/readme.html new file mode 100644 index 000000000..c63699b4b --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/PIDcontroller/readme.html @@ -0,0 +1,135 @@ + + + +PIDcontroller + + + +
+

PIDcontroller

+ +

The PID Controller implements the following equation:

+ +
e = r - y
+u = kp*e + ki*e*dt + kd*(e-e_ls)*(1/dt)
+
+ +

with the variables

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VariableStartCausalityVariabilityDescription
u0outputcontinuousControl output
y0parametertunableControl input
r0parametertunableReference value
elocalcontinuousError between reference and input
e_lslocalcontinuousError between reference and input from last time step
kp0parametertunableProportional gain
ki0parametertunableIntegral gain
kd0parametertunableDerivative gain
dt0.01parametertunableSolver step size
+ + +
+ + diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/README.md b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/README.md new file mode 100644 index 000000000..5b0344a1a --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/README.md @@ -0,0 +1,19 @@ +# Build instruction + +To build the Oscillator FMU you need [CMake](https://cmake.org/) ≥ 3.16 and a supported [build tool](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html) e.g. Visual Studio ≥ 2013 , Xcode or make. + +Compile the model with the following commands: + +```bash +mkdir build +cd build +cmake -DFMI_TYPE=CS -DFMI_VERSION=3 .. +make +cp ./PIDcontroller.fmu ../.. +``` + +Instead of `make`, you can also use your preferred build tool to create the FMU. + +## License + +The FMU model `PIDcontroller.fmu` used for this tutorial is based on the [Reference-FMUs](https://github.com/modelica/Reference-FMUs) from the Modelica Association Project "FMI", which are released under the 2-Clause BSD License (see folder "thirdparty"). diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/FMI.h b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/FMI.h new file mode 100644 index 000000000..07111130f --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/FMI.h @@ -0,0 +1,160 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#endif + +#include +#include + +#ifndef FMI_MAX_MESSAGE_LENGTH +#define FMI_MAX_MESSAGE_LENGTH 4096 +#endif + +#ifndef FMI_STATIC +#define FMI_STATIC +#endif + +typedef enum { + FMIOK, + FMIWarning, + FMIDiscard, + FMIError, + FMIFatal, + FMIPending +} FMIStatus; + +typedef enum { + + // FMI 3.0 variable types + FMIFloat32Type, + FMIDiscreteFloat32Type, + FMIFloat64Type, + FMIDiscreteFloat64Type, + FMIInt8Type, + FMIUInt8Type, + FMIInt16Type, + FMIUInt16Type, + FMIInt32Type, + FMIUInt32Type, + FMIInt64Type, + FMIUInt64Type, + FMIBooleanType, + FMIStringType, + FMIBinaryType, + FMIClockType, + + // Aliases for FMI 1.0 and 2.0 + FMIRealType = FMIFloat64Type, + FMIDiscreteRealType = FMIDiscreteFloat64Type, + FMIIntegerType = FMIInt32Type, + +} FMIVariableType; + +typedef enum { + FMIVersion1 = 1, + FMIVersion2 = 2, + FMIVersion3 = 3 +} FMIVersion; + +typedef enum { + FMIModelExchange, + FMICoSimulation, + FMIScheduledExecution +} FMIInterfaceType; + +typedef enum { + FMI2StartAndEndState = 1 << 0, + FMI2InstantiatedState = 1 << 1, + FMI2InitializationModeState = 1 << 2, + + // model exchange states + FMI2EventModeState = 1 << 3, + FMI2ContinuousTimeModeState = 1 << 4, + + // co-simulation states + FMI2StepCompleteState = 1 << 5, + FMI2StepInProgressState = 1 << 6, + FMI2StepFailedState = 1 << 7, + FMI2StepCanceledState = 1 << 8, + + FMI2TerminatedState = 1 << 9, + FMI2ErrorState = 1 << 10, + FMI2FatalState = 1 << 11, +} FMI2State; + +typedef unsigned int FMIValueReference; + +typedef struct FMIInstance_ FMIInstance; + +typedef struct FMI2Functions_ FMI2Functions; + +typedef struct FMI3Functions_ FMI3Functions; + +typedef void FMILogFunctionCall(FMIInstance *instance, FMIStatus status, const char *message, ...); + +typedef void FMILogMessage(FMIInstance *instance, FMIStatus status, const char *category, const char *message); + +struct FMIInstance_ { + + FMI2Functions *fmi2Functions; + FMI3Functions *fmi3Functions; + +#ifdef _WIN32 + HMODULE libraryHandle; +#else + void *libraryHandle; +#endif + + void *userData; + + FMILogMessage *logMessage; + FMILogFunctionCall *logFunctionCall; + + double time; + + char *buf1; + char *buf2; + + size_t bufsize1; + size_t bufsize2; + + void *component; + + const char *name; + + bool logFMICalls; + + FMI2State state; + + FMIStatus status; + + FMIVersion fmiVersion; + + FMIInterfaceType interfaceType; +}; + +FMI_STATIC FMIInstance *FMICreateInstance(const char *instanceName, const char *libraryPath, FMILogMessage *logMessage, FMILogFunctionCall *logFunctionCall); + +FMI_STATIC void FMIFreeInstance(FMIInstance *instance); + +FMI_STATIC const char *FMIValueReferencesToString(FMIInstance *instance, const FMIValueReference vr[], size_t nvr); + +FMI_STATIC const char *FMIValuesToString(FMIInstance *instance, size_t vValues, const size_t sizes[], const void *values, FMIVariableType variableType); + +FMI_STATIC FMIStatus FMIURIToPath(const char *uri, char *path, const size_t pathLength); + +FMI_STATIC FMIStatus FMIPathToURI(const char *path, char *uri, const size_t uriLength); + +FMI_STATIC FMIStatus FMIPlatformBinaryPath(const char *unzipdir, const char *modelIdentifier, FMIVersion fmiVersion, char *platformBinaryPath, size_t size); + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/FMI2.h b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/FMI2.h new file mode 100644 index 000000000..7836d4471 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/FMI2.h @@ -0,0 +1,219 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "FMI.h" +#include "fmi2Functions.h" + +struct FMI2Functions_ { + + fmi2CallbackFunctions callbacks; + fmi2EventInfo eventInfo; + + /*************************************************** + Common Functions for FMI 2.0 + ****************************************************/ + + /* required functions */ + fmi2GetTypesPlatformTYPE *fmi2GetTypesPlatform; + fmi2GetVersionTYPE *fmi2GetVersion; + fmi2SetDebugLoggingTYPE *fmi2SetDebugLogging; + fmi2InstantiateTYPE *fmi2Instantiate; + fmi2FreeInstanceTYPE *fmi2FreeInstance; + fmi2SetupExperimentTYPE *fmi2SetupExperiment; + fmi2EnterInitializationModeTYPE *fmi2EnterInitializationMode; + fmi2ExitInitializationModeTYPE *fmi2ExitInitializationMode; + fmi2TerminateTYPE *fmi2Terminate; + fmi2ResetTYPE *fmi2Reset; + fmi2GetRealTYPE *fmi2GetReal; + fmi2GetIntegerTYPE *fmi2GetInteger; + fmi2GetBooleanTYPE *fmi2GetBoolean; + fmi2GetStringTYPE *fmi2GetString; + fmi2SetRealTYPE *fmi2SetReal; + fmi2SetIntegerTYPE *fmi2SetInteger; + fmi2SetBooleanTYPE *fmi2SetBoolean; + fmi2SetStringTYPE *fmi2SetString; + + /* optional functions */ + fmi2GetFMUstateTYPE *fmi2GetFMUstate; + fmi2SetFMUstateTYPE *fmi2SetFMUstate; + fmi2FreeFMUstateTYPE *fmi2FreeFMUstate; + fmi2SerializedFMUstateSizeTYPE *fmi2SerializedFMUstateSize; + fmi2SerializeFMUstateTYPE *fmi2SerializeFMUstate; + fmi2DeSerializeFMUstateTYPE *fmi2DeSerializeFMUstate; + fmi2GetDirectionalDerivativeTYPE *fmi2GetDirectionalDerivative; + + /*************************************************** + Functions for FMI 2.0 for Model Exchange + ****************************************************/ + + fmi2EnterEventModeTYPE *fmi2EnterEventMode; + fmi2NewDiscreteStatesTYPE *fmi2NewDiscreteStates; + fmi2EnterContinuousTimeModeTYPE *fmi2EnterContinuousTimeMode; + fmi2CompletedIntegratorStepTYPE *fmi2CompletedIntegratorStep; + fmi2SetTimeTYPE *fmi2SetTime; + fmi2SetContinuousStatesTYPE *fmi2SetContinuousStates; + fmi2GetDerivativesTYPE *fmi2GetDerivatives; + fmi2GetEventIndicatorsTYPE *fmi2GetEventIndicators; + fmi2GetContinuousStatesTYPE *fmi2GetContinuousStates; + fmi2GetNominalsOfContinuousStatesTYPE *fmi2GetNominalsOfContinuousStates; + + /*************************************************** + Functions for FMI 2.0 for Co-Simulation + ****************************************************/ + + fmi2SetRealInputDerivativesTYPE *fmi2SetRealInputDerivatives; + fmi2GetRealOutputDerivativesTYPE *fmi2GetRealOutputDerivatives; + fmi2DoStepTYPE *fmi2DoStep; + fmi2CancelStepTYPE *fmi2CancelStep; + fmi2GetStatusTYPE *fmi2GetStatus; + fmi2GetRealStatusTYPE *fmi2GetRealStatus; + fmi2GetIntegerStatusTYPE *fmi2GetIntegerStatus; + fmi2GetBooleanStatusTYPE *fmi2GetBooleanStatus; + fmi2GetStringStatusTYPE *fmi2GetStringStatus; +}; + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers of header files and setting logging status */ +FMI_STATIC const char *FMI2GetTypesPlatform(FMIInstance *instance); + +FMI_STATIC const char *FMI2GetVersion(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2SetDebugLogging(FMIInstance *instance, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]); + +FMI_STATIC FMIStatus FMI2Instantiate(FMIInstance *instance, const char *fmuResourceLocation, fmi2Type fmuType, fmi2String fmuGUID, + fmi2Boolean visible, fmi2Boolean loggingOn); + +FMI_STATIC void FMI2FreeInstance(FMIInstance *instance); + +/* Enter and exit initialization mode, terminate and reset */ +FMI_STATIC FMIStatus FMI2SetupExperiment(FMIInstance *instance, + fmi2Boolean toleranceDefined, + fmi2Real tolerance, + fmi2Real startTime, + fmi2Boolean stopTimeDefined, + fmi2Real stopTime); + +FMI_STATIC FMIStatus FMI2EnterInitializationMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2ExitInitializationMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2Terminate(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2Reset(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2SetupExperiment(FMIInstance *instance, + fmi2Boolean toleranceDefined, + fmi2Real tolerance, + fmi2Real startTime, + fmi2Boolean stopTimeDefined, + fmi2Real stopTime); + +/* Getting and setting variable values */ +FMI_STATIC FMIStatus FMI2GetReal(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]); + +FMI_STATIC FMIStatus FMI2GetInteger(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]); + +FMI_STATIC FMIStatus FMI2GetBoolean(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]); + +FMI_STATIC FMIStatus FMI2GetString(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]); + +FMI_STATIC FMIStatus FMI2SetReal(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]); + +FMI_STATIC FMIStatus FMI2SetInteger(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]); + +FMI_STATIC FMIStatus FMI2SetBoolean(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]); + +FMI_STATIC FMIStatus FMI2SetString(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]); + +/* Getting and setting the internal FMU state */ +FMI_STATIC FMIStatus FMI2GetFMUstate(FMIInstance *instance, fmi2FMUstate *FMUstate); + +FMI_STATIC FMIStatus FMI2SetFMUstate(FMIInstance *instance, fmi2FMUstate FMUstate); + +FMI_STATIC FMIStatus FMI2FreeFMUstate(FMIInstance *instance, fmi2FMUstate *FMUstate); + +FMI_STATIC FMIStatus FMI2SerializedFMUstateSize(FMIInstance *instance, fmi2FMUstate FMUstate, size_t *size); + +FMI_STATIC FMIStatus FMI2SerializeFMUstate(FMIInstance *instance, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size); + +FMI_STATIC FMIStatus FMI2DeSerializeFMUstate(FMIInstance *instance, const fmi2Byte serializedState[], size_t size, fmi2FMUstate *FMUstate); + +/* Getting partial derivatives */ +FMI_STATIC FMIStatus FMI2GetDirectionalDerivative(FMIInstance *instance, + const fmi2ValueReference vUnknown_ref[], size_t nUnknown, + const fmi2ValueReference vKnown_ref[], size_t nKnown, + const fmi2Real dvKnown[], + fmi2Real dvUnknown[]); + +/*************************************************** +Types for Functions for FMI2 for Model Exchange +****************************************************/ + +/* Enter and exit the different modes */ +FMI_STATIC FMIStatus FMI2EnterEventMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2NewDiscreteStates(FMIInstance *instance, fmi2EventInfo *eventInfo); + +FMI_STATIC FMIStatus FMI2EnterContinuousTimeMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2CompletedIntegratorStep(FMIInstance *instance, + fmi2Boolean noSetFMUStatePriorToCurrentPoint, + fmi2Boolean *enterEventMode, + fmi2Boolean *terminateSimulation); + +/* Providing independent variables and re-initialization of caching */ +FMI_STATIC FMIStatus FMI2SetTime(FMIInstance *instance, fmi2Real time); + +FMI_STATIC FMIStatus FMI2SetContinuousStates(FMIInstance *instance, const fmi2Real x[], size_t nx); + +/* Evaluation of the model equations */ +FMI_STATIC FMIStatus FMI2GetDerivatives(FMIInstance *instance, fmi2Real derivatives[], size_t nx); + +FMI_STATIC FMIStatus FMI2GetEventIndicators(FMIInstance *instance, fmi2Real eventIndicators[], size_t ni); + +FMI_STATIC FMIStatus FMI2GetContinuousStates(FMIInstance *instance, fmi2Real x[], size_t nx); + +FMI_STATIC FMIStatus FMI2GetNominalsOfContinuousStates(FMIInstance *instance, fmi2Real x_nominal[], size_t nx); + +/*************************************************** +Types for Functions for FMI2 for Co-Simulation +****************************************************/ + +/* Simulating the slave */ +FMI_STATIC FMIStatus FMI2SetRealInputDerivatives(FMIInstance *instance, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + const fmi2Real value[]); + +FMI_STATIC FMIStatus FMI2GetRealOutputDerivatives(FMIInstance *instance, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + fmi2Real value[]); + +FMI_STATIC FMIStatus FMI2DoStep(FMIInstance *instance, + fmi2Real currentCommunicationPoint, + fmi2Real communicationStepSize, + fmi2Boolean noSetFMUStatePriorToCurrentPoint); + +FMI_STATIC FMIStatus FMI2CancelStep(FMIInstance *instance); + +/* Inquire slave status */ +FMI_STATIC FMIStatus FMI2GetStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Status *value); + +FMI_STATIC FMIStatus FMI2GetRealStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Real *value); + +FMI_STATIC FMIStatus FMI2GetIntegerStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Integer *value); + +FMI_STATIC FMIStatus FMI2GetBooleanStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Boolean *value); + +FMI_STATIC FMIStatus FMI2GetStringStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2String *value); + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/FMI3.h b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/FMI3.h new file mode 100644 index 000000000..82dbe8034 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/FMI3.h @@ -0,0 +1,560 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "FMI.h" +#include "fmi3FunctionTypes.h" + +struct FMI3Functions_ { + + fmi3Boolean eventModeUsed; + + fmi3Boolean discreteStatesNeedUpdate; + fmi3Boolean terminateSimulation; + fmi3Boolean nominalsOfContinuousStatesChanged; + fmi3Boolean valuesOfContinuousStatesChanged; + fmi3Boolean nextEventTimeDefined; + fmi3Float64 nextEventTime; + + /*************************************************** + Common Functions for FMI 3.0 + ****************************************************/ + + /* Inquire version numbers and set debug logging */ + fmi3GetVersionTYPE *fmi3GetVersion; + fmi3SetDebugLoggingTYPE *fmi3SetDebugLogging; + + /* Creation and destruction of FMU instances */ + fmi3InstantiateModelExchangeTYPE *fmi3InstantiateModelExchange; + fmi3InstantiateCoSimulationTYPE *fmi3InstantiateCoSimulation; + fmi3InstantiateScheduledExecutionTYPE *fmi3InstantiateScheduledExecution; + fmi3FreeInstanceTYPE *fmi3FreeInstance; + + /* Enter and exit initialization mode, terminate and reset */ + fmi3EnterInitializationModeTYPE *fmi3EnterInitializationMode; + fmi3ExitInitializationModeTYPE *fmi3ExitInitializationMode; + fmi3EnterEventModeTYPE *fmi3EnterEventMode; + fmi3TerminateTYPE *fmi3Terminate; + fmi3ResetTYPE *fmi3Reset; + + /* Getting and setting variable values */ + fmi3GetFloat32TYPE *fmi3GetFloat32; + fmi3GetFloat64TYPE *fmi3GetFloat64; + fmi3GetInt8TYPE *fmi3GetInt8; + fmi3GetUInt8TYPE *fmi3GetUInt8; + fmi3GetInt16TYPE *fmi3GetInt16; + fmi3GetUInt16TYPE *fmi3GetUInt16; + fmi3GetInt32TYPE *fmi3GetInt32; + fmi3GetUInt32TYPE *fmi3GetUInt32; + fmi3GetInt64TYPE *fmi3GetInt64; + fmi3GetUInt64TYPE *fmi3GetUInt64; + fmi3GetBooleanTYPE *fmi3GetBoolean; + fmi3GetStringTYPE *fmi3GetString; + fmi3GetBinaryTYPE *fmi3GetBinary; + fmi3GetClockTYPE *fmi3GetClock; + fmi3SetFloat32TYPE *fmi3SetFloat32; + fmi3SetFloat64TYPE *fmi3SetFloat64; + fmi3SetInt8TYPE *fmi3SetInt8; + fmi3SetUInt8TYPE *fmi3SetUInt8; + fmi3SetInt16TYPE *fmi3SetInt16; + fmi3SetUInt16TYPE *fmi3SetUInt16; + fmi3SetInt32TYPE *fmi3SetInt32; + fmi3SetUInt32TYPE *fmi3SetUInt32; + fmi3SetInt64TYPE *fmi3SetInt64; + fmi3SetUInt64TYPE *fmi3SetUInt64; + fmi3SetBooleanTYPE *fmi3SetBoolean; + fmi3SetStringTYPE *fmi3SetString; + fmi3SetBinaryTYPE *fmi3SetBinary; + fmi3SetClockTYPE *fmi3SetClock; + + /* Getting Variable Dependency Information */ + fmi3GetNumberOfVariableDependenciesTYPE *fmi3GetNumberOfVariableDependencies; + fmi3GetVariableDependenciesTYPE *fmi3GetVariableDependencies; + + /* Getting and setting the internal FMU state */ + fmi3GetFMUStateTYPE *fmi3GetFMUState; + fmi3SetFMUStateTYPE *fmi3SetFMUState; + fmi3FreeFMUStateTYPE *fmi3FreeFMUState; + fmi3SerializedFMUStateSizeTYPE *fmi3SerializedFMUStateSize; + fmi3SerializeFMUStateTYPE *fmi3SerializeFMUState; + fmi3DeserializeFMUStateTYPE *fmi3DeserializeFMUState; + + /* Getting partial derivatives */ + fmi3GetDirectionalDerivativeTYPE *fmi3GetDirectionalDerivative; + fmi3GetAdjointDerivativeTYPE *fmi3GetAdjointDerivative; + + /* Entering and exiting the Configuration or Reconfiguration Mode */ + fmi3EnterConfigurationModeTYPE *fmi3EnterConfigurationMode; + fmi3ExitConfigurationModeTYPE *fmi3ExitConfigurationMode; + + /* Clock related functions */ + fmi3GetIntervalDecimalTYPE *fmi3GetIntervalDecimal; + fmi3GetIntervalFractionTYPE *fmi3GetIntervalFraction; + fmi3GetShiftDecimalTYPE *fmi3GetShiftDecimal; + fmi3GetShiftFractionTYPE *fmi3GetShiftFraction; + fmi3SetIntervalDecimalTYPE *fmi3SetIntervalDecimal; + fmi3SetIntervalFractionTYPE *fmi3SetIntervalFraction; + fmi3SetShiftDecimalTYPE *fmi3SetShiftDecimal; + fmi3SetShiftFractionTYPE *fmi3SetShiftFraction; + fmi3EvaluateDiscreteStatesTYPE *fmi3EvaluateDiscreteStates; + fmi3UpdateDiscreteStatesTYPE *fmi3UpdateDiscreteStates; + + /*************************************************** + Functions for Model Exchange + ****************************************************/ + + fmi3EnterContinuousTimeModeTYPE *fmi3EnterContinuousTimeMode; + fmi3CompletedIntegratorStepTYPE *fmi3CompletedIntegratorStep; + + /* Providing independent variables and re-initialization of caching */ + fmi3SetTimeTYPE *fmi3SetTime; + fmi3SetContinuousStatesTYPE *fmi3SetContinuousStates; + + /* Evaluation of the model equations */ + fmi3GetContinuousStateDerivativesTYPE *fmi3GetContinuousStateDerivatives; + fmi3GetEventIndicatorsTYPE *fmi3GetEventIndicators; + fmi3GetContinuousStatesTYPE *fmi3GetContinuousStates; + fmi3GetNominalsOfContinuousStatesTYPE *fmi3GetNominalsOfContinuousStates; + fmi3GetNumberOfEventIndicatorsTYPE *fmi3GetNumberOfEventIndicators; + fmi3GetNumberOfContinuousStatesTYPE *fmi3GetNumberOfContinuousStates; + + /*************************************************** + Functions for FMI 3.0 for Co-Simulation + ****************************************************/ + + fmi3EnterStepModeTYPE *fmi3EnterStepMode; + fmi3GetOutputDerivativesTYPE *fmi3GetOutputDerivatives; + fmi3DoStepTYPE *fmi3DoStep; + + /*************************************************** + Functions for Scheduled Execution + ****************************************************/ + + fmi3ActivateModelPartitionTYPE *fmi3ActivateModelPartition; +}; + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers and setting logging status */ +FMI_STATIC const char *FMI3GetVersion(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3SetDebugLogging(FMIInstance *instance, + fmi3Boolean loggingOn, + size_t nCategories, + const fmi3String categories[]); + +/* Creation and destruction of FMU instances and setting debug status */ +FMI_STATIC FMIStatus FMI3InstantiateModelExchange( + FMIInstance *instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn); + +FMI_STATIC FMIStatus FMI3InstantiateCoSimulation( + FMIInstance *instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3Boolean eventModeUsed, + fmi3Boolean earlyReturnAllowed, + const fmi3ValueReference requiredIntermediateVariables[], + size_t nRequiredIntermediateVariables, + fmi3IntermediateUpdateCallback intermediateUpdate); + +FMI_STATIC FMIStatus FMI3InstantiateScheduledExecution( + FMIInstance *instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3ClockUpdateCallback clockUpdate, + fmi3LockPreemptionCallback lockPreemption, + fmi3UnlockPreemptionCallback unlockPreemption); + +FMI_STATIC FMIStatus FMI3FreeInstance(FMIInstance *instance); + +/* Enter and exit initialization mode, enter event mode, terminate and reset */ +FMI_STATIC FMIStatus FMI3EnterInitializationMode(FMIInstance *instance, + fmi3Boolean toleranceDefined, + fmi3Float64 tolerance, + fmi3Float64 startTime, + fmi3Boolean stopTimeDefined, + fmi3Float64 stopTime); + +FMI_STATIC FMIStatus FMI3ExitInitializationMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3EnterEventMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3Terminate(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3Reset(FMIInstance *instance); + +/* Getting and setting variable values */ +FMI_STATIC FMIStatus FMI3GetFloat32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetFloat64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetInt8(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int8 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetUInt8(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt8 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetInt16(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int16 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetUInt16(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt16 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetInt32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetUInt32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetInt64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetUInt64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetBoolean(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Boolean values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetString(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3String values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetBinary(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + size_t sizes[], + fmi3Binary values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetClock(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Clock values[]); + +FMI_STATIC FMIStatus FMI3SetFloat32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetFloat64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetInt8(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int8 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetUInt8(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt8 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetInt16(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int16 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetUInt16(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt16 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetInt32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetUInt32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetInt64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetUInt64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetBoolean(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Boolean values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetString(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3String values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetBinary(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const size_t sizes[], + const fmi3Binary values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetClock(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Clock values[]); + +/* Getting Variable Dependency Information */ +FMI_STATIC FMIStatus FMI3GetNumberOfVariableDependencies(FMIInstance *instance, + fmi3ValueReference valueReference, + size_t *nDependencies); + +FMI_STATIC FMIStatus FMI3GetVariableDependencies(FMIInstance *instance, + fmi3ValueReference dependent, + size_t elementIndicesOfDependent[], + fmi3ValueReference independents[], + size_t elementIndicesOfIndependents[], + fmi3DependencyKind dependencyKinds[], + size_t nDependencies); + +/* Getting and setting the internal FMU state */ +FMI_STATIC FMIStatus FMI3GetFMUState(FMIInstance *instance, fmi3FMUState *FMUState); + +FMI_STATIC FMIStatus FMI3SetFMUState(FMIInstance *instance, fmi3FMUState FMUState); + +FMI_STATIC FMIStatus FMI3FreeFMUState(FMIInstance *instance, fmi3FMUState *FMUState); + +FMI_STATIC FMIStatus FMI3SerializedFMUStateSize(FMIInstance *instance, + fmi3FMUState FMUState, + size_t *size); + +FMI_STATIC FMIStatus FMI3SerializeFMUState(FMIInstance *instance, + fmi3FMUState FMUState, + fmi3Byte serializedState[], + size_t size); + +FMI_STATIC FMIStatus FMI3DeserializeFMUState(FMIInstance *instance, + const fmi3Byte serializedState[], + size_t size, + fmi3FMUState *FMUState); + +/* Getting partial derivatives */ +FMI_STATIC FMIStatus FMI3GetDirectionalDerivative(FMIInstance *instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity); + +FMI_STATIC FMIStatus FMI3GetAdjointDerivative(FMIInstance *instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity); + +/* Entering and exiting the Configuration or Reconfiguration Mode */ +FMI_STATIC FMIStatus FMI3EnterConfigurationMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3ExitConfigurationMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3GetIntervalDecimal(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 intervals[], + fmi3IntervalQualifier qualifiers[]); + +FMI_STATIC FMIStatus FMI3GetIntervalFraction(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 intervalCounters[], + fmi3UInt64 resolutions[], + fmi3IntervalQualifier qualifiers[]); + +FMI_STATIC FMIStatus FMI3GetShiftDecimal(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 shifts[]); + +FMI_STATIC FMIStatus FMI3GetShiftFraction(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 shiftCounters[], + fmi3UInt64 resolutions[]); + +FMI_STATIC FMIStatus FMI3SetIntervalDecimal(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 intervals[]); + +FMI_STATIC FMIStatus FMI3SetIntervalFraction(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 intervalCounters[], + const fmi3UInt64 resolutions[]); + +FMI_STATIC FMIStatus FMI3SetShiftDecimal(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 shifts[]); + +FMI_STATIC FMIStatus FMI3SetShiftFraction(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 shiftCounters[], + const fmi3UInt64 resolutions[]); + +FMI_STATIC FMIStatus FMI3EvaluateDiscreteStates(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3UpdateDiscreteStates(FMIInstance *instance, + fmi3Boolean *discreteStatesNeedUpdate, + fmi3Boolean *terminateSimulation, + fmi3Boolean *nominalsOfContinuousStatesChanged, + fmi3Boolean *valuesOfContinuousStatesChanged, + fmi3Boolean *nextEventTimeDefined, + fmi3Float64 *nextEventTime); + +/*************************************************** +Functions for Model Exchange +****************************************************/ + +FMI_STATIC FMIStatus FMI3EnterContinuousTimeMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3CompletedIntegratorStep(FMIInstance *instance, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *enterEventMode, + fmi3Boolean *terminateSimulation); + +/* Providing independent variables and re-initialization of caching */ +FMI_STATIC FMIStatus FMI3SetTime(FMIInstance *instance, fmi3Float64 time); + +FMI_STATIC FMIStatus FMI3SetContinuousStates(FMIInstance *instance, + const fmi3Float64 continuousStates[], + size_t nContinuousStates); + +/* Evaluation of the model equations */ +FMI_STATIC FMIStatus FMI3GetContinuousStateDerivatives(FMIInstance *instance, + fmi3Float64 derivatives[], + size_t nContinuousStates); + +FMI_STATIC FMIStatus FMI3GetEventIndicators(FMIInstance *instance, + fmi3Float64 eventIndicators[], + size_t nEventIndicators); + +FMI_STATIC FMIStatus FMI3GetContinuousStates(FMIInstance *instance, + fmi3Float64 continuousStates[], + size_t nContinuousStates); + +FMI_STATIC FMIStatus FMI3GetNominalsOfContinuousStates(FMIInstance *instance, + fmi3Float64 nominals[], + size_t nContinuousStates); + +FMI_STATIC FMIStatus FMI3GetNumberOfEventIndicators(FMIInstance *instance, + size_t *nEventIndicators); + +FMI_STATIC FMIStatus FMI3GetNumberOfContinuousStates(FMIInstance *instance, + size_t *nContinuousStates); + +/*************************************************** +Functions for Co-Simulation +****************************************************/ + +/* Simulating the FMU */ + +FMI_STATIC FMIStatus FMI3EnterStepMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3GetOutputDerivatives(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 orders[], + fmi3Float64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3DoStep(FMIInstance *instance, + fmi3Float64 currentCommunicationPoint, + fmi3Float64 communicationStepSize, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *eventHandlingNeeded, + fmi3Boolean *terminateSimulation, + fmi3Boolean *earlyReturn, + fmi3Float64 *lastSuccessfulTime); + +/*************************************************** +Functions for Scheduled Execution +****************************************************/ + +FMI_STATIC FMIStatus FMI3ActivateModelPartition(FMIInstance *instance, + fmi3ValueReference clockReference, + fmi3Float64 activationTime); + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/cosimulation.h b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/cosimulation.h new file mode 100644 index 000000000..03cf8fe80 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/cosimulation.h @@ -0,0 +1,8 @@ +#pragma once + +#include "model.h" + +#define EPSILON (FIXED_SOLVER_STEP * 1e-6) + +void doFixedStep(ModelInstance *comp, bool *stateEvent, bool *timeEvent); +void doAdaptiveStep(ModelInstance *comp, bool *stateEvent, bool *timeEvent); diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi2FunctionTypes.h b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi2FunctionTypes.h new file mode 100644 index 000000000..345a4449e --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi2FunctionTypes.h @@ -0,0 +1,266 @@ +#ifndef fmi2FunctionTypes_h +#define fmi2FunctionTypes_h + +#include "fmi2TypesPlatform.h" + +/* This header file must be utilized when compiling an FMU or an FMI master. + It declares data and function types for FMI 2.0.1 + + Revisions: + - Sep. 30, 2019: License changed to 2-clause BSD License (without extensions) + - Jul. 5, 2019: Remove const modifier from fields of fmi2CallbackFunctions (#216) + - Sep. 6, 2018: Parameter names added to function prototypes + - Apr. 9, 2014: all prefixes "fmi" renamed to "fmi2" (decision from April 8) + - Apr. 3, 2014: Added #include for size_t definition + - Mar. 27, 2014: Added #include "fmiTypesPlatform.h" (#179) + - Mar. 26, 2014: Introduced function argument "void" for the functions (#171) + fmiGetTypesPlatformTYPE and fmiGetVersionTYPE + - Oct. 11, 2013: Functions of ModelExchange and CoSimulation merged: + fmiInstantiateModelTYPE , fmiInstantiateSlaveTYPE -> fmiInstantiateTYPE + fmiFreeModelInstanceTYPE, fmiFreeSlaveInstanceTYPE -> fmiFreeInstanceTYPE + fmiEnterModelInitializationModeTYPE, fmiEnterSlaveInitializationModeTYPE -> fmiEnterInitializationModeTYPE + fmiExitModelInitializationModeTYPE , fmiExitSlaveInitializationModeTYPE -> fmiExitInitializationModeTYPE + fmiTerminateModelTYPE , fmiTerminateSlaveTYPE -> fmiTerminate + fmiResetSlave -> fmiReset (now also for ModelExchange and not only for CoSimulation) + Functions renamed + fmiUpdateDiscreteStatesTYPE -> fmiNewDiscreteStatesTYPE + Renamed elements of the enumeration fmiEventInfo + upcomingTimeEvent -> nextEventTimeDefined // due to generic naming scheme: varDefined + var + newUpdateDiscreteStatesNeeded -> newDiscreteStatesNeeded; + - June 13, 2013: Changed type fmiEventInfo + Functions removed: + fmiInitializeModelTYPE + fmiEventUpdateTYPE + fmiCompletedEventIterationTYPE + fmiInitializeSlaveTYPE + Functions added: + fmiEnterModelInitializationModeTYPE + fmiExitModelInitializationModeTYPE + fmiEnterEventModeTYPE + fmiUpdateDiscreteStatesTYPE + fmiEnterContinuousTimeModeTYPE + fmiEnterSlaveInitializationModeTYPE; + fmiExitSlaveInitializationModeTYPE; + - Feb. 17, 2013: Added third argument to fmiCompletedIntegratorStepTYPE + Changed function name "fmiTerminateType" to "fmiTerminateModelType" (due to #113) + Changed function name "fmiGetNominalContinuousStateTYPE" to + "fmiGetNominalsOfContinuousStatesTYPE" + Removed fmiGetStateValueReferencesTYPE. + - Nov. 14, 2011: First public Version + + + Copyright (C) 2008-2011 MODELISAR consortium, + 2012-2019 Modelica Association Project "FMI" + All rights reserved. + + This file is licensed by the copyright holders under the 2-Clause BSD License + (https://opensource.org/licenses/BSD-2-Clause): + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* make sure all compiler use the same alignment policies for structures */ +#if defined _MSC_VER || defined __GNUC__ +#pragma pack(push, 8) +#endif + +/* Include stddef.h, in order that size_t etc. is defined */ +#include + +/* Type definitions */ +typedef enum { + fmi2OK, + fmi2Warning, + fmi2Discard, + fmi2Error, + fmi2Fatal, + fmi2Pending +} fmi2Status; + +typedef enum { + fmi2ModelExchange, + fmi2CoSimulation +} fmi2Type; + +typedef enum { + fmi2DoStepStatus, + fmi2PendingStatus, + fmi2LastSuccessfulTime, + fmi2Terminated +} fmi2StatusKind; + +typedef void (*fmi2CallbackLogger)(fmi2ComponentEnvironment componentEnvironment, + fmi2String instanceName, + fmi2Status status, + fmi2String category, + fmi2String message, + ...); +typedef void *(*fmi2CallbackAllocateMemory)(size_t nobj, size_t size); +typedef void (*fmi2CallbackFreeMemory)(void *obj); +typedef void (*fmi2StepFinished)(fmi2ComponentEnvironment componentEnvironment, + fmi2Status status); + +typedef struct { + fmi2CallbackLogger logger; + fmi2CallbackAllocateMemory allocateMemory; + fmi2CallbackFreeMemory freeMemory; + fmi2StepFinished stepFinished; + fmi2ComponentEnvironment componentEnvironment; +} fmi2CallbackFunctions; + +typedef struct { + fmi2Boolean newDiscreteStatesNeeded; + fmi2Boolean terminateSimulation; + fmi2Boolean nominalsOfContinuousStatesChanged; + fmi2Boolean valuesOfContinuousStatesChanged; + fmi2Boolean nextEventTimeDefined; + fmi2Real nextEventTime; +} fmi2EventInfo; + +/* reset alignment policy to the one set before reading this file */ +#if defined _MSC_VER || defined __GNUC__ +#pragma pack(pop) +#endif + +/* Define fmi2 function pointer types to simplify dynamic loading */ + +/*************************************************** +Types for Common Functions +****************************************************/ + +/* Inquire version numbers of header files and setting logging status */ +typedef const char *fmi2GetTypesPlatformTYPE(void); +typedef const char *fmi2GetVersionTYPE(void); +typedef fmi2Status fmi2SetDebugLoggingTYPE(fmi2Component c, + fmi2Boolean loggingOn, + size_t nCategories, + const fmi2String categories[]); + +/* Creation and destruction of FMU instances and setting debug status */ +typedef fmi2Component fmi2InstantiateTYPE(fmi2String instanceName, + fmi2Type fmuType, + fmi2String fmuGUID, + fmi2String fmuResourceLocation, + const fmi2CallbackFunctions *functions, + fmi2Boolean visible, + fmi2Boolean loggingOn); +typedef void fmi2FreeInstanceTYPE(fmi2Component c); + +/* Enter and exit initialization mode, terminate and reset */ +typedef fmi2Status fmi2SetupExperimentTYPE(fmi2Component c, + fmi2Boolean toleranceDefined, + fmi2Real tolerance, + fmi2Real startTime, + fmi2Boolean stopTimeDefined, + fmi2Real stopTime); +typedef fmi2Status fmi2EnterInitializationModeTYPE(fmi2Component c); +typedef fmi2Status fmi2ExitInitializationModeTYPE(fmi2Component c); +typedef fmi2Status fmi2TerminateTYPE(fmi2Component c); +typedef fmi2Status fmi2ResetTYPE(fmi2Component c); + +/* Getting and setting variable values */ +typedef fmi2Status fmi2GetRealTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]); +typedef fmi2Status fmi2GetIntegerTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]); +typedef fmi2Status fmi2GetBooleanTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]); +typedef fmi2Status fmi2GetStringTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]); + +typedef fmi2Status fmi2SetRealTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]); +typedef fmi2Status fmi2SetIntegerTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]); +typedef fmi2Status fmi2SetBooleanTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]); +typedef fmi2Status fmi2SetStringTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]); + +/* Getting and setting the internal FMU state */ +typedef fmi2Status fmi2GetFMUstateTYPE(fmi2Component c, fmi2FMUstate *FMUstate); +typedef fmi2Status fmi2SetFMUstateTYPE(fmi2Component c, fmi2FMUstate FMUstate); +typedef fmi2Status fmi2FreeFMUstateTYPE(fmi2Component c, fmi2FMUstate *FMUstate); +typedef fmi2Status fmi2SerializedFMUstateSizeTYPE(fmi2Component c, fmi2FMUstate FMUstate, size_t *size); +typedef fmi2Status fmi2SerializeFMUstateTYPE(fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte[], size_t size); +typedef fmi2Status fmi2DeSerializeFMUstateTYPE(fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate *FMUstate); + +/* Getting partial derivatives */ +typedef fmi2Status fmi2GetDirectionalDerivativeTYPE(fmi2Component c, + const fmi2ValueReference vUnknown_ref[], size_t nUnknown, + const fmi2ValueReference vKnown_ref[], size_t nKnown, + const fmi2Real dvKnown[], + fmi2Real dvUnknown[]); + +/*************************************************** +Types for Functions for FMI2 for Model Exchange +****************************************************/ + +/* Enter and exit the different modes */ +typedef fmi2Status fmi2EnterEventModeTYPE(fmi2Component c); +typedef fmi2Status fmi2NewDiscreteStatesTYPE(fmi2Component c, fmi2EventInfo *fmi2eventInfo); +typedef fmi2Status fmi2EnterContinuousTimeModeTYPE(fmi2Component c); +typedef fmi2Status fmi2CompletedIntegratorStepTYPE(fmi2Component c, + fmi2Boolean noSetFMUStatePriorToCurrentPoint, + fmi2Boolean *enterEventMode, + fmi2Boolean *terminateSimulation); + +/* Providing independent variables and re-initialization of caching */ +typedef fmi2Status fmi2SetTimeTYPE(fmi2Component c, fmi2Real time); +typedef fmi2Status fmi2SetContinuousStatesTYPE(fmi2Component c, const fmi2Real x[], size_t nx); + +/* Evaluation of the model equations */ +typedef fmi2Status fmi2GetDerivativesTYPE(fmi2Component c, fmi2Real derivatives[], size_t nx); +typedef fmi2Status fmi2GetEventIndicatorsTYPE(fmi2Component c, fmi2Real eventIndicators[], size_t ni); +typedef fmi2Status fmi2GetContinuousStatesTYPE(fmi2Component c, fmi2Real x[], size_t nx); +typedef fmi2Status fmi2GetNominalsOfContinuousStatesTYPE(fmi2Component c, fmi2Real x_nominal[], size_t nx); + +/*************************************************** +Types for Functions for FMI2 for Co-Simulation +****************************************************/ + +/* Simulating the slave */ +typedef fmi2Status fmi2SetRealInputDerivativesTYPE(fmi2Component c, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + const fmi2Real value[]); +typedef fmi2Status fmi2GetRealOutputDerivativesTYPE(fmi2Component c, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + fmi2Real value[]); +typedef fmi2Status fmi2DoStepTYPE(fmi2Component c, + fmi2Real currentCommunicationPoint, + fmi2Real communicationStepSize, + fmi2Boolean noSetFMUStatePriorToCurrentPoint); +typedef fmi2Status fmi2CancelStepTYPE(fmi2Component c); + +/* Inquire slave status */ +typedef fmi2Status fmi2GetStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Status *value); +typedef fmi2Status fmi2GetRealStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Real *value); +typedef fmi2Status fmi2GetIntegerStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Integer *value); +typedef fmi2Status fmi2GetBooleanStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Boolean *value); +typedef fmi2Status fmi2GetStringStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2String *value); + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif + +#endif /* fmi2FunctionTypes_h */ diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi2Functions.h b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi2Functions.h new file mode 100644 index 000000000..f177e5611 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi2Functions.h @@ -0,0 +1,321 @@ +#ifndef fmi2Functions_h +#define fmi2Functions_h + +/* This header file must be utilized when compiling a FMU. + It defines all functions of the + FMI 2.0.1 Model Exchange and Co-Simulation Interface. + + In order to have unique function names even if several FMUs + are compiled together (e.g. for embedded systems), every "real" function name + is constructed by prepending the function name by "FMI2_FUNCTION_PREFIX". + Therefore, the typical usage is: + + #define FMI2_FUNCTION_PREFIX MyModel_ + #include "fmi2Functions.h" + + As a result, a function that is defined as "fmi2GetDerivatives" in this header file, + is actually getting the name "MyModel_fmi2GetDerivatives". + + This only holds if the FMU is shipped in C source code, or is compiled in a + static link library. For FMUs compiled in a DLL/sharedObject, the "actual" function + names are used and "FMI2_FUNCTION_PREFIX" must not be defined. + + Revisions: + - Sep. 29, 2019: License changed to 2-clause BSD License (without extensions) + - Apr. 9, 2014: All prefixes "fmi" renamed to "fmi2" (decision from April 8) + - Mar. 26, 2014: FMI_Export set to empty value if FMI_Export and FMI_FUNCTION_PREFIX + are not defined (#173) + - Oct. 11, 2013: Functions of ModelExchange and CoSimulation merged: + fmiInstantiateModel , fmiInstantiateSlave -> fmiInstantiate + fmiFreeModelInstance, fmiFreeSlaveInstance -> fmiFreeInstance + fmiEnterModelInitializationMode, fmiEnterSlaveInitializationMode -> fmiEnterInitializationMode + fmiExitModelInitializationMode , fmiExitSlaveInitializationMode -> fmiExitInitializationMode + fmiTerminateModel, fmiTerminateSlave -> fmiTerminate + fmiResetSlave -> fmiReset (now also for ModelExchange and not only for CoSimulation) + Functions renamed: + fmiUpdateDiscreteStates -> fmiNewDiscreteStates + - June 13, 2013: Functions removed: + fmiInitializeModel + fmiEventUpdate + fmiCompletedEventIteration + fmiInitializeSlave + Functions added: + fmiEnterModelInitializationMode + fmiExitModelInitializationMode + fmiEnterEventMode + fmiUpdateDiscreteStates + fmiEnterContinuousTimeMode + fmiEnterSlaveInitializationMode; + fmiExitSlaveInitializationMode; + - Feb. 17, 2013: Portability improvements: + o DllExport changed to FMI_Export + o FUNCTION_PREFIX changed to FMI_FUNCTION_PREFIX + o Allow undefined FMI_FUNCTION_PREFIX (meaning no prefix is used) + Changed function name "fmiTerminate" to "fmiTerminateModel" (due to #113) + Changed function name "fmiGetNominalContinuousState" to + "fmiGetNominalsOfContinuousStates" + Removed fmiGetStateValueReferences. + - Nov. 14, 2011: Adapted to FMI 2.0: + o Split into two files (fmiFunctions.h, fmiTypes.h) in order + that code that dynamically loads an FMU can directly + utilize the header files). + o Added C++ encapsulation of C-part, in order that the header + file can be directly utilized in C++ code. + o fmiCallbackFunctions is passed as pointer to fmiInstantiateXXX + o stepFinished within fmiCallbackFunctions has as first + argument "fmiComponentEnvironment" and not "fmiComponent". + o New functions to get and set the complete FMU state + and to compute partial derivatives. + - Nov. 4, 2010: Adapted to specification text: + o fmiGetModelTypesPlatform renamed to fmiGetTypesPlatform + o fmiInstantiateSlave: Argument GUID replaced by fmuGUID + Argument mimetype replaced by mimeType + o tabs replaced by spaces + - Oct. 16, 2010: Functions for FMI for Co-simulation added + - Jan. 20, 2010: stateValueReferencesChanged added to struct fmiEventInfo (ticket #27) + (by M. Otter, DLR) + Added WIN32 pragma to define the struct layout (ticket #34) + (by J. Mauss, QTronic) + - Jan. 4, 2010: Removed argument intermediateResults from fmiInitialize + Renamed macro fmiGetModelFunctionsVersion to fmiGetVersion + Renamed macro fmiModelFunctionsVersion to fmiVersion + Replaced fmiModel by fmiComponent in decl of fmiInstantiateModel + (by J. Mauss, QTronic) + - Dec. 17, 2009: Changed extension "me" to "fmi" (by Martin Otter, DLR). + - Dez. 14, 2009: Added eventInfo to meInitialize and added + meGetNominalContinuousStates (by Martin Otter, DLR) + - Sept. 9, 2009: Added DllExport (according to Peter Nilsson's suggestion) + (by A. Junghanns, QTronic) + - Sept. 9, 2009: Changes according to FMI-meeting on July 21: + meInquireModelTypesVersion -> meGetModelTypesPlatform + meInquireModelFunctionsVersion -> meGetModelFunctionsVersion + meSetStates -> meSetContinuousStates + meGetStates -> meGetContinuousStates + removal of meInitializeModelClass + removal of meGetTime + change of arguments of meInstantiateModel + change of arguments of meCompletedIntegratorStep + (by Martin Otter, DLR): + - July 19, 2009: Added "me" as prefix to file names (by Martin Otter, DLR). + - March 2, 2009: Changed function definitions according to the last design + meeting with additional improvements (by Martin Otter, DLR). + - Dec. 3 , 2008: First version by Martin Otter (DLR) and Hans Olsson (Dynasim). + + + Copyright (C) 2008-2011 MODELISAR consortium, + 2012-2019 Modelica Association Project "FMI" + All rights reserved. + + This file is licensed by the copyright holders under the 2-Clause BSD License + (https://opensource.org/licenses/BSD-2-Clause): + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "fmi2FunctionTypes.h" +#include "fmi2TypesPlatform.h" + +/* + Export FMI2 API functions on Windows and under GCC. + If custom linking is desired then the FMI2_Export must be + defined before including this file. For instance, + it may be set to __declspec(dllimport). +*/ +#if !defined(FMI2_Export) +#if !defined(FMI2_FUNCTION_PREFIX) +#if defined _WIN32 || defined __CYGWIN__ +/* Note: both gcc & MSVC on Windows support this syntax. */ +#define FMI2_Export __declspec(dllexport) +#else +#if __GNUC__ >= 4 +#define FMI2_Export __attribute__((visibility("default"))) +#else +#define FMI2_Export +#endif +#endif +#else +#define FMI2_Export +#endif +#endif + +/* Macros to construct the real function name + (prepend function name by FMI2_FUNCTION_PREFIX) */ +#if defined(FMI2_FUNCTION_PREFIX) +#define fmi2Paste(a, b) a##b +#define fmi2PasteB(a, b) fmi2Paste(a, b) +#define fmi2FullName(name) fmi2PasteB(FMI2_FUNCTION_PREFIX, name) +#else +#define fmi2FullName(name) name +#endif + +/*************************************************** +Common Functions +****************************************************/ +#define fmi2GetTypesPlatform fmi2FullName(fmi2GetTypesPlatform) +#define fmi2GetVersion fmi2FullName(fmi2GetVersion) +#define fmi2SetDebugLogging fmi2FullName(fmi2SetDebugLogging) +#define fmi2Instantiate fmi2FullName(fmi2Instantiate) +#define fmi2FreeInstance fmi2FullName(fmi2FreeInstance) +#define fmi2SetupExperiment fmi2FullName(fmi2SetupExperiment) +#define fmi2EnterInitializationMode fmi2FullName(fmi2EnterInitializationMode) +#define fmi2ExitInitializationMode fmi2FullName(fmi2ExitInitializationMode) +#define fmi2Terminate fmi2FullName(fmi2Terminate) +#define fmi2Reset fmi2FullName(fmi2Reset) +#define fmi2GetReal fmi2FullName(fmi2GetReal) +#define fmi2GetInteger fmi2FullName(fmi2GetInteger) +#define fmi2GetBoolean fmi2FullName(fmi2GetBoolean) +#define fmi2GetString fmi2FullName(fmi2GetString) +#define fmi2SetReal fmi2FullName(fmi2SetReal) +#define fmi2SetInteger fmi2FullName(fmi2SetInteger) +#define fmi2SetBoolean fmi2FullName(fmi2SetBoolean) +#define fmi2SetString fmi2FullName(fmi2SetString) +#define fmi2GetFMUstate fmi2FullName(fmi2GetFMUstate) +#define fmi2SetFMUstate fmi2FullName(fmi2SetFMUstate) +#define fmi2FreeFMUstate fmi2FullName(fmi2FreeFMUstate) +#define fmi2SerializedFMUstateSize fmi2FullName(fmi2SerializedFMUstateSize) +#define fmi2SerializeFMUstate fmi2FullName(fmi2SerializeFMUstate) +#define fmi2DeSerializeFMUstate fmi2FullName(fmi2DeSerializeFMUstate) +#define fmi2GetDirectionalDerivative fmi2FullName(fmi2GetDirectionalDerivative) + +/*************************************************** +Functions for FMI2 for Model Exchange +****************************************************/ +#define fmi2EnterEventMode fmi2FullName(fmi2EnterEventMode) +#define fmi2NewDiscreteStates fmi2FullName(fmi2NewDiscreteStates) +#define fmi2EnterContinuousTimeMode fmi2FullName(fmi2EnterContinuousTimeMode) +#define fmi2CompletedIntegratorStep fmi2FullName(fmi2CompletedIntegratorStep) +#define fmi2SetTime fmi2FullName(fmi2SetTime) +#define fmi2SetContinuousStates fmi2FullName(fmi2SetContinuousStates) +#define fmi2GetDerivatives fmi2FullName(fmi2GetDerivatives) +#define fmi2GetEventIndicators fmi2FullName(fmi2GetEventIndicators) +#define fmi2GetContinuousStates fmi2FullName(fmi2GetContinuousStates) +#define fmi2GetNominalsOfContinuousStates fmi2FullName(fmi2GetNominalsOfContinuousStates) + +/*************************************************** +Functions for FMI2 for Co-Simulation +****************************************************/ +#define fmi2SetRealInputDerivatives fmi2FullName(fmi2SetRealInputDerivatives) +#define fmi2GetRealOutputDerivatives fmi2FullName(fmi2GetRealOutputDerivatives) +#define fmi2DoStep fmi2FullName(fmi2DoStep) +#define fmi2CancelStep fmi2FullName(fmi2CancelStep) +#define fmi2GetStatus fmi2FullName(fmi2GetStatus) +#define fmi2GetRealStatus fmi2FullName(fmi2GetRealStatus) +#define fmi2GetIntegerStatus fmi2FullName(fmi2GetIntegerStatus) +#define fmi2GetBooleanStatus fmi2FullName(fmi2GetBooleanStatus) +#define fmi2GetStringStatus fmi2FullName(fmi2GetStringStatus) + +/* Version number */ +#define fmi2Version "2.0" + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers of header files */ +FMI2_Export fmi2GetTypesPlatformTYPE fmi2GetTypesPlatform; +FMI2_Export fmi2GetVersionTYPE fmi2GetVersion; +FMI2_Export fmi2SetDebugLoggingTYPE fmi2SetDebugLogging; + +/* Creation and destruction of FMU instances */ +FMI2_Export fmi2InstantiateTYPE fmi2Instantiate; +FMI2_Export fmi2FreeInstanceTYPE fmi2FreeInstance; + +/* Enter and exit initialization mode, terminate and reset */ +FMI2_Export fmi2SetupExperimentTYPE fmi2SetupExperiment; +FMI2_Export fmi2EnterInitializationModeTYPE fmi2EnterInitializationMode; +FMI2_Export fmi2ExitInitializationModeTYPE fmi2ExitInitializationMode; +FMI2_Export fmi2TerminateTYPE fmi2Terminate; +FMI2_Export fmi2ResetTYPE fmi2Reset; + +/* Getting and setting variables values */ +FMI2_Export fmi2GetRealTYPE fmi2GetReal; +FMI2_Export fmi2GetIntegerTYPE fmi2GetInteger; +FMI2_Export fmi2GetBooleanTYPE fmi2GetBoolean; +FMI2_Export fmi2GetStringTYPE fmi2GetString; + +FMI2_Export fmi2SetRealTYPE fmi2SetReal; +FMI2_Export fmi2SetIntegerTYPE fmi2SetInteger; +FMI2_Export fmi2SetBooleanTYPE fmi2SetBoolean; +FMI2_Export fmi2SetStringTYPE fmi2SetString; + +/* Getting and setting the internal FMU state */ +FMI2_Export fmi2GetFMUstateTYPE fmi2GetFMUstate; +FMI2_Export fmi2SetFMUstateTYPE fmi2SetFMUstate; +FMI2_Export fmi2FreeFMUstateTYPE fmi2FreeFMUstate; +FMI2_Export fmi2SerializedFMUstateSizeTYPE fmi2SerializedFMUstateSize; +FMI2_Export fmi2SerializeFMUstateTYPE fmi2SerializeFMUstate; +FMI2_Export fmi2DeSerializeFMUstateTYPE fmi2DeSerializeFMUstate; + +/* Getting partial derivatives */ +FMI2_Export fmi2GetDirectionalDerivativeTYPE fmi2GetDirectionalDerivative; + +/*************************************************** +Functions for FMI2 for Model Exchange +****************************************************/ + +/* Enter and exit the different modes */ +FMI2_Export fmi2EnterEventModeTYPE fmi2EnterEventMode; +FMI2_Export fmi2NewDiscreteStatesTYPE fmi2NewDiscreteStates; +FMI2_Export fmi2EnterContinuousTimeModeTYPE fmi2EnterContinuousTimeMode; +FMI2_Export fmi2CompletedIntegratorStepTYPE fmi2CompletedIntegratorStep; + +/* Providing independent variables and re-initialization of caching */ +FMI2_Export fmi2SetTimeTYPE fmi2SetTime; +FMI2_Export fmi2SetContinuousStatesTYPE fmi2SetContinuousStates; + +/* Evaluation of the model equations */ +FMI2_Export fmi2GetDerivativesTYPE fmi2GetDerivatives; +FMI2_Export fmi2GetEventIndicatorsTYPE fmi2GetEventIndicators; +FMI2_Export fmi2GetContinuousStatesTYPE fmi2GetContinuousStates; +FMI2_Export fmi2GetNominalsOfContinuousStatesTYPE fmi2GetNominalsOfContinuousStates; + +/*************************************************** +Functions for FMI2 for Co-Simulation +****************************************************/ + +/* Simulating the slave */ +FMI2_Export fmi2SetRealInputDerivativesTYPE fmi2SetRealInputDerivatives; +FMI2_Export fmi2GetRealOutputDerivativesTYPE fmi2GetRealOutputDerivatives; + +FMI2_Export fmi2DoStepTYPE fmi2DoStep; +FMI2_Export fmi2CancelStepTYPE fmi2CancelStep; + +/* Inquire slave status */ +FMI2_Export fmi2GetStatusTYPE fmi2GetStatus; +FMI2_Export fmi2GetRealStatusTYPE fmi2GetRealStatus; +FMI2_Export fmi2GetIntegerStatusTYPE fmi2GetIntegerStatus; +FMI2_Export fmi2GetBooleanStatusTYPE fmi2GetBooleanStatus; +FMI2_Export fmi2GetStringStatusTYPE fmi2GetStringStatus; + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif + +#endif /* fmi2Functions_h */ diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi2TypesPlatform.h b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi2TypesPlatform.h new file mode 100644 index 000000000..6b63cb1c5 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi2TypesPlatform.h @@ -0,0 +1,107 @@ +#ifndef fmi2TypesPlatform_h +#define fmi2TypesPlatform_h + +/* Standard header file to define the argument types of the + functions of the Functional Mock-up Interface 2.0.1 + This header file must be utilized both by the model and + by the simulation engine. + + Revisions: + - Sep. 29, 2019: License changed to 2-clause BSD License (without extensions) + - Apr. 9, 2014: All prefixes "fmi" renamed to "fmi2" (decision from April 8) + - Mar 31, 2014: New datatype fmiChar introduced. + - Feb. 17, 2013: Changed fmiTypesPlatform from "standard32" to "default". + Removed fmiUndefinedValueReference since no longer needed + (because every state is defined in ScalarVariables). + - March 20, 2012: Renamed from fmiPlatformTypes.h to fmiTypesPlatform.h + - Nov. 14, 2011: Use the header file "fmiPlatformTypes.h" for FMI 2.0 + both for "FMI for model exchange" and for "FMI for co-simulation" + New types "fmiComponentEnvironment", "fmiState", and "fmiByte". + The implementation of "fmiBoolean" is change from "char" to "int". + The #define "fmiPlatform" changed to "fmiTypesPlatform" + (in order that #define and function call are consistent) + - Oct. 4, 2010: Renamed header file from "fmiModelTypes.h" to fmiPlatformTypes.h" + for the co-simulation interface + - Jan. 4, 2010: Renamed meModelTypes_h to fmiModelTypes_h (by Mauss, QTronic) + - Dec. 21, 2009: Changed "me" to "fmi" and "meModel" to "fmiComponent" + according to meeting on Dec. 18 (by Martin Otter, DLR) + - Dec. 6, 2009: Added meUndefinedValueReference (by Martin Otter, DLR) + - Sept. 9, 2009: Changes according to FMI-meeting on July 21: + Changed "version" to "platform", "standard" to "standard32", + Added a precise definition of "standard32" as comment + (by Martin Otter, DLR) + - July 19, 2009: Added "me" as prefix to file names, added meTrue/meFalse, + and changed meValueReferenced from int to unsigned int + (by Martin Otter, DLR). + - March 2, 2009: Moved enums and function pointer definitions to + ModelFunctions.h (by Martin Otter, DLR). + - Dec. 3, 2008 : First version by Martin Otter (DLR) and + Hans Olsson (Dynasim). + + + Copyright (C) 2008-2011 MODELISAR consortium, + 2012-2019 Modelica Association Project "FMI" + All rights reserved. + + This file is licensed by the copyright holders under the 2-Clause BSD License + (https://opensource.org/licenses/BSD-2-Clause): + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- +*/ + +/* Platform (unique identification of this header file) */ +#define fmi2TypesPlatform "default" + +/* Type definitions of variables passed as arguments + Version "default" means: + + fmi2Component : an opaque object pointer + fmi2ComponentEnvironment: an opaque object pointer + fmi2FMUstate : an opaque object pointer + fmi2ValueReference : handle to the value of a variable + fmi2Real : double precision floating-point data type + fmi2Integer : basic signed integer data type + fmi2Boolean : basic signed integer data type + fmi2Char : character data type + fmi2String : a pointer to a vector of fmi2Char characters + ('\0' terminated, UTF8 encoded) + fmi2Byte : smallest addressable unit of the machine, typically one byte. +*/ +typedef void *fmi2Component; /* Pointer to FMU instance */ +typedef void *fmi2ComponentEnvironment; /* Pointer to FMU environment */ +typedef void *fmi2FMUstate; /* Pointer to internal FMU state */ +typedef unsigned int fmi2ValueReference; +typedef double fmi2Real; +typedef int fmi2Integer; +typedef int fmi2Boolean; +typedef char fmi2Char; +typedef const fmi2Char *fmi2String; +typedef char fmi2Byte; + +/* Values for fmi2Boolean */ +#define fmi2True 1 +#define fmi2False 0 + +#endif /* fmi2TypesPlatform_h */ diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi3FunctionTypes.h b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi3FunctionTypes.h new file mode 100644 index 000000000..8af7f89bd --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi3FunctionTypes.h @@ -0,0 +1,637 @@ +#ifndef fmi3FunctionTypes_h +#define fmi3FunctionTypes_h + +#include "fmi3PlatformTypes.h" + +/* +This header file defines the data and function types of FMI 3.0. +It must be used when compiling an FMU or an FMI importer. + +Copyright (C) 2011 MODELISAR consortium, + 2012-2022 Modelica Association Project "FMI" + All rights reserved. + +This file is licensed by the copyright holders under the 2-Clause BSD License +(https://opensource.org/licenses/BSD-2-Clause): + +---------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +---------------------------------------------------------------------------- +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Include stddef.h, in order that size_t etc. is defined */ +#include + +/* Type definitions */ + +/* tag::Status[] */ +typedef enum { + fmi3OK, + fmi3Warning, + fmi3Discard, + fmi3Error, + fmi3Fatal, +} fmi3Status; +/* end::Status[] */ + +/* tag::DependencyKind[] */ +typedef enum { + fmi3Independent, + fmi3Constant, + fmi3Fixed, + fmi3Tunable, + fmi3Discrete, + fmi3Dependent +} fmi3DependencyKind; +/* end::DependencyKind[] */ + +/* tag::IntervalQualifier[] */ +typedef enum { + fmi3IntervalNotYetKnown, + fmi3IntervalUnchanged, + fmi3IntervalChanged +} fmi3IntervalQualifier; +/* end::IntervalQualifier[] */ + +/* tag::CallbackLogMessage[] */ +typedef void (*fmi3LogMessageCallback)(fmi3InstanceEnvironment instanceEnvironment, + fmi3Status status, + fmi3String category, + fmi3String message); +/* end::CallbackLogMessage[] */ + +/* tag::CallbackClockUpdate[] */ +typedef void (*fmi3ClockUpdateCallback)( + fmi3InstanceEnvironment instanceEnvironment); +/* end::CallbackClockUpdate[] */ + +/* tag::CallbackIntermediateUpdate[] */ +typedef void (*fmi3IntermediateUpdateCallback)( + fmi3InstanceEnvironment instanceEnvironment, + fmi3Float64 intermediateUpdateTime, + fmi3Boolean intermediateVariableSetRequested, + fmi3Boolean intermediateVariableGetAllowed, + fmi3Boolean intermediateStepFinished, + fmi3Boolean canReturnEarly, + fmi3Boolean *earlyReturnRequested, + fmi3Float64 *earlyReturnTime); +/* end::CallbackIntermediateUpdate[] */ + +/* tag::CallbackPreemptionLock[] */ +typedef void (*fmi3LockPreemptionCallback)(); +typedef void (*fmi3UnlockPreemptionCallback)(); +/* end::CallbackPreemptionLock[] */ + +/* Define fmi3 function pointer types to simplify dynamic loading */ + +/*************************************************** +Types for Common Functions +****************************************************/ + +/* Inquire version numbers and setting logging status */ +/* tag::GetVersion[] */ +typedef const char *fmi3GetVersionTYPE(void); +/* end::GetVersion[] */ + +/* tag::SetDebugLogging[] */ +typedef fmi3Status fmi3SetDebugLoggingTYPE(fmi3Instance instance, + fmi3Boolean loggingOn, + size_t nCategories, + const fmi3String categories[]); +/* end::SetDebugLogging[] */ + +/* Creation and destruction of FMU instances and setting debug status */ +/* tag::Instantiate[] */ +typedef fmi3Instance fmi3InstantiateModelExchangeTYPE( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage); + +typedef fmi3Instance fmi3InstantiateCoSimulationTYPE( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3Boolean eventModeUsed, + fmi3Boolean earlyReturnAllowed, + const fmi3ValueReference requiredIntermediateVariables[], + size_t nRequiredIntermediateVariables, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3IntermediateUpdateCallback intermediateUpdate); + +typedef fmi3Instance fmi3InstantiateScheduledExecutionTYPE( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3ClockUpdateCallback clockUpdate, + fmi3LockPreemptionCallback lockPreemption, + fmi3UnlockPreemptionCallback unlockPreemption); +/* end::Instantiate[] */ + +/* tag::FreeInstance[] */ +typedef void fmi3FreeInstanceTYPE(fmi3Instance instance); +/* end::FreeInstance[] */ + +/* Enter and exit initialization mode, enter event mode, terminate and reset */ +/* tag::EnterInitializationMode[] */ +typedef fmi3Status fmi3EnterInitializationModeTYPE(fmi3Instance instance, + fmi3Boolean toleranceDefined, + fmi3Float64 tolerance, + fmi3Float64 startTime, + fmi3Boolean stopTimeDefined, + fmi3Float64 stopTime); +/* end::EnterInitializationMode[] */ + +/* tag::ExitInitializationMode[] */ +typedef fmi3Status fmi3ExitInitializationModeTYPE(fmi3Instance instance); +/* end::ExitInitializationMode[] */ + +/* tag::EnterEventMode[] */ +typedef fmi3Status fmi3EnterEventModeTYPE(fmi3Instance instance); +/* end::EnterEventMode[] */ + +/* tag::Terminate[] */ +typedef fmi3Status fmi3TerminateTYPE(fmi3Instance instance); +/* end::Terminate[] */ + +/* tag::Reset[] */ +typedef fmi3Status fmi3ResetTYPE(fmi3Instance instance); +/* end::Reset[] */ + +/* Getting and setting variable values */ +/* tag::Getters[] */ +typedef fmi3Status fmi3GetFloat32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float32 values[], + size_t nValues); + +typedef fmi3Status fmi3GetFloat64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 values[], + size_t nValues); + +typedef fmi3Status fmi3GetInt8TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int8 values[], + size_t nValues); + +typedef fmi3Status fmi3GetUInt8TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt8 values[], + size_t nValues); + +typedef fmi3Status fmi3GetInt16TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int16 values[], + size_t nValues); + +typedef fmi3Status fmi3GetUInt16TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt16 values[], + size_t nValues); + +typedef fmi3Status fmi3GetInt32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int32 values[], + size_t nValues); + +typedef fmi3Status fmi3GetUInt32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt32 values[], + size_t nValues); + +typedef fmi3Status fmi3GetInt64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int64 values[], + size_t nValues); + +typedef fmi3Status fmi3GetUInt64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 values[], + size_t nValues); + +typedef fmi3Status fmi3GetBooleanTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Boolean values[], + size_t nValues); + +typedef fmi3Status fmi3GetStringTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3String values[], + size_t nValues); + +typedef fmi3Status fmi3GetBinaryTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + size_t valueSizes[], + fmi3Binary values[], + size_t nValues); +/* end::Getters[] */ + +/* tag::GetClock[] */ +typedef fmi3Status fmi3GetClockTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Clock values[]); +/* end::GetClock[] */ + +/* tag::Setters[] */ +typedef fmi3Status fmi3SetFloat32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float32 values[], + size_t nValues); + +typedef fmi3Status fmi3SetFloat64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 values[], + size_t nValues); + +typedef fmi3Status fmi3SetInt8TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int8 values[], + size_t nValues); + +typedef fmi3Status fmi3SetUInt8TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt8 values[], + size_t nValues); + +typedef fmi3Status fmi3SetInt16TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int16 values[], + size_t nValues); + +typedef fmi3Status fmi3SetUInt16TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt16 values[], + size_t nValues); + +typedef fmi3Status fmi3SetInt32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 values[], + size_t nValues); + +typedef fmi3Status fmi3SetUInt32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt32 values[], + size_t nValues); + +typedef fmi3Status fmi3SetInt64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int64 values[], + size_t nValues); + +typedef fmi3Status fmi3SetUInt64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 values[], + size_t nValues); + +typedef fmi3Status fmi3SetBooleanTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Boolean values[], + size_t nValues); + +typedef fmi3Status fmi3SetStringTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3String values[], + size_t nValues); + +typedef fmi3Status fmi3SetBinaryTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const size_t valueSizes[], + const fmi3Binary values[], + size_t nValues); +/* end::Setters[] */ +/* tag::SetClock[] */ +typedef fmi3Status fmi3SetClockTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Clock values[]); +/* end::SetClock[] */ + +/* Getting Variable Dependency Information */ +/* tag::GetNumberOfVariableDependencies[] */ +typedef fmi3Status fmi3GetNumberOfVariableDependenciesTYPE(fmi3Instance instance, + fmi3ValueReference valueReference, + size_t *nDependencies); +/* end::GetNumberOfVariableDependencies[] */ + +/* tag::GetVariableDependencies[] */ +typedef fmi3Status fmi3GetVariableDependenciesTYPE(fmi3Instance instance, + fmi3ValueReference dependent, + size_t elementIndicesOfDependent[], + fmi3ValueReference independents[], + size_t elementIndicesOfIndependents[], + fmi3DependencyKind dependencyKinds[], + size_t nDependencies); +/* end::GetVariableDependencies[] */ + +/* Getting and setting the internal FMU state */ +/* tag::GetFMUState[] */ +typedef fmi3Status fmi3GetFMUStateTYPE(fmi3Instance instance, fmi3FMUState *FMUState); +/* end::GetFMUState[] */ + +/* tag::SetFMUState[] */ +typedef fmi3Status fmi3SetFMUStateTYPE(fmi3Instance instance, fmi3FMUState FMUState); +/* end::SetFMUState[] */ + +/* tag::FreeFMUState[] */ +typedef fmi3Status fmi3FreeFMUStateTYPE(fmi3Instance instance, fmi3FMUState *FMUState); +/* end::FreeFMUState[] */ + +/* tag::SerializedFMUStateSize[] */ +typedef fmi3Status fmi3SerializedFMUStateSizeTYPE(fmi3Instance instance, + fmi3FMUState FMUState, + size_t *size); +/* end::SerializedFMUStateSize[] */ + +/* tag::SerializeFMUState[] */ +typedef fmi3Status fmi3SerializeFMUStateTYPE(fmi3Instance instance, + fmi3FMUState FMUState, + fmi3Byte serializedState[], + size_t size); +/* end::SerializeFMUState[] */ + +/* tag::DeserializeFMUState[] */ +typedef fmi3Status fmi3DeserializeFMUStateTYPE(fmi3Instance instance, + const fmi3Byte serializedState[], + size_t size, + fmi3FMUState *FMUState); +/* end::DeserializeFMUState[] */ + +/* Getting partial derivatives */ +/* tag::GetDirectionalDerivative[] */ +typedef fmi3Status fmi3GetDirectionalDerivativeTYPE(fmi3Instance instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity); +/* end::GetDirectionalDerivative[] */ + +/* tag::GetAdjointDerivative[] */ +typedef fmi3Status fmi3GetAdjointDerivativeTYPE(fmi3Instance instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity); +/* end::GetAdjointDerivative[] */ + +/* Entering and exiting the Configuration or Reconfiguration Mode */ + +/* tag::EnterConfigurationMode[] */ +typedef fmi3Status fmi3EnterConfigurationModeTYPE(fmi3Instance instance); +/* end::EnterConfigurationMode[] */ + +/* tag::ExitConfigurationMode[] */ +typedef fmi3Status fmi3ExitConfigurationModeTYPE(fmi3Instance instance); +/* end::ExitConfigurationMode[] */ + +/* tag::GetIntervalDecimal[] */ +typedef fmi3Status fmi3GetIntervalDecimalTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 intervals[], + fmi3IntervalQualifier qualifiers[]); +/* end::GetIntervalDecimal[] */ + +/* tag::GetIntervalFraction[] */ +typedef fmi3Status fmi3GetIntervalFractionTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 counters[], + fmi3UInt64 resolutions[], + fmi3IntervalQualifier qualifiers[]); +/* end::GetIntervalFraction[] */ + +/* tag::GetShiftDecimal[] */ +typedef fmi3Status fmi3GetShiftDecimalTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 shifts[]); +/* end::GetShiftDecimal[] */ + +/* tag::GetShiftFraction[] */ +typedef fmi3Status fmi3GetShiftFractionTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 counters[], + fmi3UInt64 resolutions[]); +/* end::GetShiftFraction[] */ + +/* tag::SetIntervalDecimal[] */ +typedef fmi3Status fmi3SetIntervalDecimalTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 intervals[]); +/* end::SetIntervalDecimal[] */ + +/* tag::SetIntervalFraction[] */ +typedef fmi3Status fmi3SetIntervalFractionTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 counters[], + const fmi3UInt64 resolutions[]); +/* end::SetIntervalFraction[] */ + +/* tag::SetShiftDecimal[] */ +typedef fmi3Status fmi3SetShiftDecimalTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 shifts[]); +/* end::SetShiftDecimal[] */ + +/* tag::SetShiftFraction[] */ +typedef fmi3Status fmi3SetShiftFractionTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 counters[], + const fmi3UInt64 resolutions[]); +/* end::SetShiftFraction[] */ + +/* tag::EvaluateDiscreteStates[] */ +typedef fmi3Status fmi3EvaluateDiscreteStatesTYPE(fmi3Instance instance); +/* end::EvaluateDiscreteStates[] */ + +/* tag::UpdateDiscreteStates[] */ +typedef fmi3Status fmi3UpdateDiscreteStatesTYPE(fmi3Instance instance, + fmi3Boolean *discreteStatesNeedUpdate, + fmi3Boolean *terminateSimulation, + fmi3Boolean *nominalsOfContinuousStatesChanged, + fmi3Boolean *valuesOfContinuousStatesChanged, + fmi3Boolean *nextEventTimeDefined, + fmi3Float64 *nextEventTime); +/* end::UpdateDiscreteStates[] */ + +/*************************************************** +Types for Functions for Model Exchange +****************************************************/ + +/* tag::EnterContinuousTimeMode[] */ +typedef fmi3Status fmi3EnterContinuousTimeModeTYPE(fmi3Instance instance); +/* end::EnterContinuousTimeMode[] */ + +/* tag::CompletedIntegratorStep[] */ +typedef fmi3Status fmi3CompletedIntegratorStepTYPE(fmi3Instance instance, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *enterEventMode, + fmi3Boolean *terminateSimulation); +/* end::CompletedIntegratorStep[] */ + +/* Providing independent variables and re-initialization of caching */ +/* tag::SetTime[] */ +typedef fmi3Status fmi3SetTimeTYPE(fmi3Instance instance, fmi3Float64 time); +/* end::SetTime[] */ + +/* tag::SetContinuousStates[] */ +typedef fmi3Status fmi3SetContinuousStatesTYPE(fmi3Instance instance, + const fmi3Float64 continuousStates[], + size_t nContinuousStates); +/* end::SetContinuousStates[] */ + +/* Evaluation of the model equations */ +/* tag::GetDerivatives[] */ +typedef fmi3Status fmi3GetContinuousStateDerivativesTYPE(fmi3Instance instance, + fmi3Float64 derivatives[], + size_t nContinuousStates); +/* end::GetDerivatives[] */ + +/* tag::GetEventIndicators[] */ +typedef fmi3Status fmi3GetEventIndicatorsTYPE(fmi3Instance instance, + fmi3Float64 eventIndicators[], + size_t nEventIndicators); +/* end::GetEventIndicators[] */ + +/* tag::GetContinuousStates[] */ +typedef fmi3Status fmi3GetContinuousStatesTYPE(fmi3Instance instance, + fmi3Float64 continuousStates[], + size_t nContinuousStates); +/* end::GetContinuousStates[] */ + +/* tag::GetNominalsOfContinuousStates[] */ +typedef fmi3Status fmi3GetNominalsOfContinuousStatesTYPE(fmi3Instance instance, + fmi3Float64 nominals[], + size_t nContinuousStates); +/* end::GetNominalsOfContinuousStates[] */ + +/* tag::GetNumberOfEventIndicators[] */ +typedef fmi3Status fmi3GetNumberOfEventIndicatorsTYPE(fmi3Instance instance, + size_t *nEventIndicators); +/* end::GetNumberOfEventIndicators[] */ + +/* tag::GetNumberOfContinuousStates[] */ +typedef fmi3Status fmi3GetNumberOfContinuousStatesTYPE(fmi3Instance instance, + size_t *nContinuousStates); +/* end::GetNumberOfContinuousStates[] */ + +/*************************************************** +Types for Functions for Co-Simulation +****************************************************/ + +/* Simulating the FMU */ + +/* tag::EnterStepMode[] */ +typedef fmi3Status fmi3EnterStepModeTYPE(fmi3Instance instance); +/* end::EnterStepMode[] */ + +/* tag::GetOutputDerivatives[] */ +typedef fmi3Status fmi3GetOutputDerivativesTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 orders[], + fmi3Float64 values[], + size_t nValues); +/* end::GetOutputDerivatives[] */ + +/* tag::DoStep[] */ +typedef fmi3Status fmi3DoStepTYPE(fmi3Instance instance, + fmi3Float64 currentCommunicationPoint, + fmi3Float64 communicationStepSize, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *eventHandlingNeeded, + fmi3Boolean *terminateSimulation, + fmi3Boolean *earlyReturn, + fmi3Float64 *lastSuccessfulTime); +/* end::DoStep[] */ + +/*************************************************** +Types for Functions for Scheduled Execution +****************************************************/ + +/* tag::ActivateModelPartition[] */ +typedef fmi3Status fmi3ActivateModelPartitionTYPE(fmi3Instance instance, + fmi3ValueReference clockReference, + fmi3Float64 activationTime); +/* end::ActivateModelPartition[] */ + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif + +#endif /* fmi3FunctionTypes_h */ diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi3Functions.h b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi3Functions.h new file mode 100644 index 000000000..68e6814b8 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi3Functions.h @@ -0,0 +1,343 @@ +#ifndef fmi3Functions_h +#define fmi3Functions_h + +/* +This header file declares the functions of FMI 3.0. +It must be used when compiling an FMU. + +In order to have unique function names even if several FMUs +are compiled together (e.g. for embedded systems), every "real" function name +is constructed by prepending the function name by "FMI3_FUNCTION_PREFIX". +Therefore, the typical usage is: + + #define FMI3_FUNCTION_PREFIX MyModel_ + #include "fmi3Functions.h" + +As a result, a function that is defined as "fmi3GetContinuousStateDerivatives" in this header file, +is actually getting the name "MyModel_fmi3GetContinuousStateDerivatives". + +This only holds if the FMU is shipped in C source code, or is compiled in a +static link library. For FMUs compiled in a DLL/sharedObject, the "actual" function +names are used and "FMI3_FUNCTION_PREFIX" must not be defined. + +Copyright (C) 2008-2011 MODELISAR consortium, + 2012-2022 Modelica Association Project "FMI" + All rights reserved. + +This file is licensed by the copyright holders under the 2-Clause BSD License +(https://opensource.org/licenses/BSD-2-Clause): + +---------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +---------------------------------------------------------------------------- +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "fmi3FunctionTypes.h" +#include "fmi3PlatformTypes.h" + +/* +Allow override of FMI3_FUNCTION_PREFIX: If FMI3_OVERRIDE_FUNCTION_PREFIX +is defined, then FMI3_ACTUAL_FUNCTION_PREFIX will be used, if defined, +or no prefix if undefined. Otherwise FMI3_FUNCTION_PREFIX will be used, +if defined. +*/ +#if !defined(FMI3_OVERRIDE_FUNCTION_PREFIX) && defined(FMI3_FUNCTION_PREFIX) +#define FMI3_ACTUAL_FUNCTION_PREFIX FMI3_FUNCTION_PREFIX +#endif + +/* +Export FMI3 API functions on Windows and under GCC. +If custom linking is desired then the FMI3_Export must be +defined before including this file. For instance, +it may be set to __declspec(dllimport). +*/ +#if !defined(FMI3_Export) +#if !defined(FMI3_ACTUAL_FUNCTION_PREFIX) +#if defined _WIN32 || defined __CYGWIN__ +/* Note: both gcc & MSVC on Windows support this syntax. */ +#define FMI3_Export __declspec(dllexport) +#else +#if __GNUC__ >= 4 +#define FMI3_Export __attribute__((visibility("default"))) +#else +#define FMI3_Export +#endif +#endif +#else +#define FMI3_Export +#endif +#endif + +/* Macros to construct the real function name (prepend function name by FMI3_FUNCTION_PREFIX) */ +#if defined(FMI3_ACTUAL_FUNCTION_PREFIX) +#define fmi3Paste(a, b) a##b +#define fmi3PasteB(a, b) fmi3Paste(a, b) +#define fmi3FullName(name) fmi3PasteB(FMI3_ACTUAL_FUNCTION_PREFIX, name) +#else +#define fmi3FullName(name) name +#endif + +/* FMI version */ +#define fmi3Version "3.0" + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers and set debug logging */ +#define fmi3GetVersion fmi3FullName(fmi3GetVersion) +#define fmi3SetDebugLogging fmi3FullName(fmi3SetDebugLogging) + +/* Creation and destruction of FMU instances */ +#define fmi3InstantiateModelExchange fmi3FullName(fmi3InstantiateModelExchange) +#define fmi3InstantiateCoSimulation fmi3FullName(fmi3InstantiateCoSimulation) +#define fmi3InstantiateScheduledExecution fmi3FullName(fmi3InstantiateScheduledExecution) +#define fmi3FreeInstance fmi3FullName(fmi3FreeInstance) + +/* Enter and exit initialization mode, terminate and reset */ +#define fmi3EnterInitializationMode fmi3FullName(fmi3EnterInitializationMode) +#define fmi3ExitInitializationMode fmi3FullName(fmi3ExitInitializationMode) +#define fmi3EnterEventMode fmi3FullName(fmi3EnterEventMode) +#define fmi3Terminate fmi3FullName(fmi3Terminate) +#define fmi3Reset fmi3FullName(fmi3Reset) + +/* Getting and setting variable values */ +#define fmi3GetFloat32 fmi3FullName(fmi3GetFloat32) +#define fmi3GetFloat64 fmi3FullName(fmi3GetFloat64) +#define fmi3GetInt8 fmi3FullName(fmi3GetInt8) +#define fmi3GetUInt8 fmi3FullName(fmi3GetUInt8) +#define fmi3GetInt16 fmi3FullName(fmi3GetInt16) +#define fmi3GetUInt16 fmi3FullName(fmi3GetUInt16) +#define fmi3GetInt32 fmi3FullName(fmi3GetInt32) +#define fmi3GetUInt32 fmi3FullName(fmi3GetUInt32) +#define fmi3GetInt64 fmi3FullName(fmi3GetInt64) +#define fmi3GetUInt64 fmi3FullName(fmi3GetUInt64) +#define fmi3GetBoolean fmi3FullName(fmi3GetBoolean) +#define fmi3GetString fmi3FullName(fmi3GetString) +#define fmi3GetBinary fmi3FullName(fmi3GetBinary) +#define fmi3GetClock fmi3FullName(fmi3GetClock) +#define fmi3SetFloat32 fmi3FullName(fmi3SetFloat32) +#define fmi3SetFloat64 fmi3FullName(fmi3SetFloat64) +#define fmi3SetInt8 fmi3FullName(fmi3SetInt8) +#define fmi3SetUInt8 fmi3FullName(fmi3SetUInt8) +#define fmi3SetInt16 fmi3FullName(fmi3SetInt16) +#define fmi3SetUInt16 fmi3FullName(fmi3SetUInt16) +#define fmi3SetInt32 fmi3FullName(fmi3SetInt32) +#define fmi3SetUInt32 fmi3FullName(fmi3SetUInt32) +#define fmi3SetInt64 fmi3FullName(fmi3SetInt64) +#define fmi3SetUInt64 fmi3FullName(fmi3SetUInt64) +#define fmi3SetBoolean fmi3FullName(fmi3SetBoolean) +#define fmi3SetString fmi3FullName(fmi3SetString) +#define fmi3SetBinary fmi3FullName(fmi3SetBinary) +#define fmi3SetClock fmi3FullName(fmi3SetClock) + +/* Getting Variable Dependency Information */ +#define fmi3GetNumberOfVariableDependencies fmi3FullName(fmi3GetNumberOfVariableDependencies) +#define fmi3GetVariableDependencies fmi3FullName(fmi3GetVariableDependencies) + +/* Getting and setting the internal FMU state */ +#define fmi3GetFMUState fmi3FullName(fmi3GetFMUState) +#define fmi3SetFMUState fmi3FullName(fmi3SetFMUState) +#define fmi3FreeFMUState fmi3FullName(fmi3FreeFMUState) +#define fmi3SerializedFMUStateSize fmi3FullName(fmi3SerializedFMUStateSize) +#define fmi3SerializeFMUState fmi3FullName(fmi3SerializeFMUState) +#define fmi3DeserializeFMUState fmi3FullName(fmi3DeserializeFMUState) + +/* Getting partial derivatives */ +#define fmi3GetDirectionalDerivative fmi3FullName(fmi3GetDirectionalDerivative) +#define fmi3GetAdjointDerivative fmi3FullName(fmi3GetAdjointDerivative) + +/* Entering and exiting the Configuration or Reconfiguration Mode */ +#define fmi3EnterConfigurationMode fmi3FullName(fmi3EnterConfigurationMode) +#define fmi3ExitConfigurationMode fmi3FullName(fmi3ExitConfigurationMode) + +/* Clock related functions */ +#define fmi3GetIntervalDecimal fmi3FullName(fmi3GetIntervalDecimal) +#define fmi3GetIntervalFraction fmi3FullName(fmi3GetIntervalFraction) +#define fmi3GetShiftDecimal fmi3FullName(fmi3GetShiftDecimal) +#define fmi3GetShiftFraction fmi3FullName(fmi3GetShiftFraction) +#define fmi3SetIntervalDecimal fmi3FullName(fmi3SetIntervalDecimal) +#define fmi3SetIntervalFraction fmi3FullName(fmi3SetIntervalFraction) +#define fmi3SetShiftDecimal fmi3FullName(fmi3SetShiftDecimal) +#define fmi3SetShiftFraction fmi3FullName(fmi3SetShiftFraction) +#define fmi3EvaluateDiscreteStates fmi3FullName(fmi3EvaluateDiscreteStates) +#define fmi3UpdateDiscreteStates fmi3FullName(fmi3UpdateDiscreteStates) + +/*************************************************** +Functions for Model Exchange +****************************************************/ + +#define fmi3EnterContinuousTimeMode fmi3FullName(fmi3EnterContinuousTimeMode) +#define fmi3CompletedIntegratorStep fmi3FullName(fmi3CompletedIntegratorStep) + +/* Providing independent variables and re-initialization of caching */ +#define fmi3SetTime fmi3FullName(fmi3SetTime) +#define fmi3SetContinuousStates fmi3FullName(fmi3SetContinuousStates) + +/* Evaluation of the model equations */ +#define fmi3GetContinuousStateDerivatives fmi3FullName(fmi3GetContinuousStateDerivatives) +#define fmi3GetEventIndicators fmi3FullName(fmi3GetEventIndicators) +#define fmi3GetContinuousStates fmi3FullName(fmi3GetContinuousStates) +#define fmi3GetNominalsOfContinuousStates fmi3FullName(fmi3GetNominalsOfContinuousStates) +#define fmi3GetNumberOfEventIndicators fmi3FullName(fmi3GetNumberOfEventIndicators) +#define fmi3GetNumberOfContinuousStates fmi3FullName(fmi3GetNumberOfContinuousStates) + +/*************************************************** +Functions for Co-Simulation +****************************************************/ + +/* Simulating the FMU */ +#define fmi3EnterStepMode fmi3FullName(fmi3EnterStepMode) +#define fmi3GetOutputDerivatives fmi3FullName(fmi3GetOutputDerivatives) +#define fmi3DoStep fmi3FullName(fmi3DoStep) +#define fmi3ActivateModelPartition fmi3FullName(fmi3ActivateModelPartition) + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers and set debug logging */ +FMI3_Export fmi3GetVersionTYPE fmi3GetVersion; +FMI3_Export fmi3SetDebugLoggingTYPE fmi3SetDebugLogging; + +/* Creation and destruction of FMU instances */ +FMI3_Export fmi3InstantiateModelExchangeTYPE fmi3InstantiateModelExchange; +FMI3_Export fmi3InstantiateCoSimulationTYPE fmi3InstantiateCoSimulation; +FMI3_Export fmi3InstantiateScheduledExecutionTYPE fmi3InstantiateScheduledExecution; +FMI3_Export fmi3FreeInstanceTYPE fmi3FreeInstance; + +/* Enter and exit initialization mode, terminate and reset */ +FMI3_Export fmi3EnterInitializationModeTYPE fmi3EnterInitializationMode; +FMI3_Export fmi3ExitInitializationModeTYPE fmi3ExitInitializationMode; +FMI3_Export fmi3EnterEventModeTYPE fmi3EnterEventMode; +FMI3_Export fmi3TerminateTYPE fmi3Terminate; +FMI3_Export fmi3ResetTYPE fmi3Reset; + +/* Getting and setting variables values */ +FMI3_Export fmi3GetFloat32TYPE fmi3GetFloat32; +FMI3_Export fmi3GetFloat64TYPE fmi3GetFloat64; +FMI3_Export fmi3GetInt8TYPE fmi3GetInt8; +FMI3_Export fmi3GetUInt8TYPE fmi3GetUInt8; +FMI3_Export fmi3GetInt16TYPE fmi3GetInt16; +FMI3_Export fmi3GetUInt16TYPE fmi3GetUInt16; +FMI3_Export fmi3GetInt32TYPE fmi3GetInt32; +FMI3_Export fmi3GetUInt32TYPE fmi3GetUInt32; +FMI3_Export fmi3GetInt64TYPE fmi3GetInt64; +FMI3_Export fmi3GetUInt64TYPE fmi3GetUInt64; +FMI3_Export fmi3GetBooleanTYPE fmi3GetBoolean; +FMI3_Export fmi3GetStringTYPE fmi3GetString; +FMI3_Export fmi3GetBinaryTYPE fmi3GetBinary; +FMI3_Export fmi3GetClockTYPE fmi3GetClock; +FMI3_Export fmi3SetFloat32TYPE fmi3SetFloat32; +FMI3_Export fmi3SetFloat64TYPE fmi3SetFloat64; +FMI3_Export fmi3SetInt8TYPE fmi3SetInt8; +FMI3_Export fmi3SetUInt8TYPE fmi3SetUInt8; +FMI3_Export fmi3SetInt16TYPE fmi3SetInt16; +FMI3_Export fmi3SetUInt16TYPE fmi3SetUInt16; +FMI3_Export fmi3SetInt32TYPE fmi3SetInt32; +FMI3_Export fmi3SetUInt32TYPE fmi3SetUInt32; +FMI3_Export fmi3SetInt64TYPE fmi3SetInt64; +FMI3_Export fmi3SetUInt64TYPE fmi3SetUInt64; +FMI3_Export fmi3SetBooleanTYPE fmi3SetBoolean; +FMI3_Export fmi3SetStringTYPE fmi3SetString; +FMI3_Export fmi3SetBinaryTYPE fmi3SetBinary; +FMI3_Export fmi3SetClockTYPE fmi3SetClock; + +/* Getting Variable Dependency Information */ +FMI3_Export fmi3GetNumberOfVariableDependenciesTYPE fmi3GetNumberOfVariableDependencies; +FMI3_Export fmi3GetVariableDependenciesTYPE fmi3GetVariableDependencies; + +/* Getting and setting the internal FMU state */ +FMI3_Export fmi3GetFMUStateTYPE fmi3GetFMUState; +FMI3_Export fmi3SetFMUStateTYPE fmi3SetFMUState; +FMI3_Export fmi3FreeFMUStateTYPE fmi3FreeFMUState; +FMI3_Export fmi3SerializedFMUStateSizeTYPE fmi3SerializedFMUStateSize; +FMI3_Export fmi3SerializeFMUStateTYPE fmi3SerializeFMUState; +FMI3_Export fmi3DeserializeFMUStateTYPE fmi3DeserializeFMUState; + +/* Getting partial derivatives */ +FMI3_Export fmi3GetDirectionalDerivativeTYPE fmi3GetDirectionalDerivative; +FMI3_Export fmi3GetAdjointDerivativeTYPE fmi3GetAdjointDerivative; + +/* Entering and exiting the Configuration or Reconfiguration Mode */ +FMI3_Export fmi3EnterConfigurationModeTYPE fmi3EnterConfigurationMode; +FMI3_Export fmi3ExitConfigurationModeTYPE fmi3ExitConfigurationMode; + +/* Clock related functions */ +FMI3_Export fmi3GetIntervalDecimalTYPE fmi3GetIntervalDecimal; +FMI3_Export fmi3GetIntervalFractionTYPE fmi3GetIntervalFraction; +FMI3_Export fmi3GetShiftDecimalTYPE fmi3GetShiftDecimal; +FMI3_Export fmi3GetShiftFractionTYPE fmi3GetShiftFraction; +FMI3_Export fmi3SetIntervalDecimalTYPE fmi3SetIntervalDecimal; +FMI3_Export fmi3SetIntervalFractionTYPE fmi3SetIntervalFraction; +FMI3_Export fmi3SetShiftDecimalTYPE fmi3SetShiftDecimal; +FMI3_Export fmi3SetShiftFractionTYPE fmi3SetShiftFraction; +FMI3_Export fmi3EvaluateDiscreteStatesTYPE fmi3EvaluateDiscreteStates; +FMI3_Export fmi3UpdateDiscreteStatesTYPE fmi3UpdateDiscreteStates; + +/*************************************************** +Functions for Model Exchange +****************************************************/ + +FMI3_Export fmi3EnterContinuousTimeModeTYPE fmi3EnterContinuousTimeMode; +FMI3_Export fmi3CompletedIntegratorStepTYPE fmi3CompletedIntegratorStep; + +/* Providing independent variables and re-initialization of caching */ +/* tag::SetTimeTYPE[] */ +FMI3_Export fmi3SetTimeTYPE fmi3SetTime; +/* end::SetTimeTYPE[] */ +FMI3_Export fmi3SetContinuousStatesTYPE fmi3SetContinuousStates; + +/* Evaluation of the model equations */ +FMI3_Export fmi3GetContinuousStateDerivativesTYPE fmi3GetContinuousStateDerivatives; +FMI3_Export fmi3GetEventIndicatorsTYPE fmi3GetEventIndicators; +FMI3_Export fmi3GetContinuousStatesTYPE fmi3GetContinuousStates; +FMI3_Export fmi3GetNominalsOfContinuousStatesTYPE fmi3GetNominalsOfContinuousStates; +FMI3_Export fmi3GetNumberOfEventIndicatorsTYPE fmi3GetNumberOfEventIndicators; +FMI3_Export fmi3GetNumberOfContinuousStatesTYPE fmi3GetNumberOfContinuousStates; + +/*************************************************** +Functions for Co-Simulation +****************************************************/ + +/* Simulating the FMU */ +FMI3_Export fmi3EnterStepModeTYPE fmi3EnterStepMode; +FMI3_Export fmi3GetOutputDerivativesTYPE fmi3GetOutputDerivatives; +FMI3_Export fmi3DoStepTYPE fmi3DoStep; + +/*************************************************** +Functions for Scheduled Execution +****************************************************/ + +FMI3_Export fmi3ActivateModelPartitionTYPE fmi3ActivateModelPartition; + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif + +#endif /* fmi3Functions_h */ diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi3PlatformTypes.h b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi3PlatformTypes.h new file mode 100644 index 000000000..1f42b4159 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmi3PlatformTypes.h @@ -0,0 +1,93 @@ +#ifndef fmi3PlatformTypes_h +#define fmi3PlatformTypes_h + +/* +This header file defines the data types of FMI 3.0. +It must be used by both FMU and FMI master. + +Copyright (C) 2008-2011 MODELISAR consortium, + 2012-2022 Modelica Association Project "FMI" + All rights reserved. + +This file is licensed by the copyright holders under the 2-Clause BSD License +(https://opensource.org/licenses/BSD-2-Clause): + +---------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +---------------------------------------------------------------------------- +*/ + +/* Include the integer and boolean type definitions */ +#include +#include + +/* tag::Component[] */ +typedef void *fmi3Instance; /* Pointer to the FMU instance */ +/* end::Component[] */ + +/* tag::ComponentEnvironment[] */ +typedef void *fmi3InstanceEnvironment; /* Pointer to the FMU environment */ +/* end::ComponentEnvironment[] */ + +/* tag::FMUState[] */ +typedef void *fmi3FMUState; /* Pointer to the internal FMU state */ +/* end::FMUState[] */ + +/* tag::ValueReference[] */ +typedef uint32_t fmi3ValueReference; /* Handle to the value of a variable */ +/* end::ValueReference[] */ + +/* tag::VariableTypes[] */ +typedef float fmi3Float32; /* Single precision floating point (32-bit) */ +/* tag::fmi3Float64[] */ +typedef double fmi3Float64; /* Double precision floating point (64-bit) */ +/* end::fmi3Float64[] */ +typedef int8_t fmi3Int8; /* 8-bit signed integer */ +typedef uint8_t fmi3UInt8; /* 8-bit unsigned integer */ +typedef int16_t fmi3Int16; /* 16-bit signed integer */ +typedef uint16_t fmi3UInt16; /* 16-bit unsigned integer */ +typedef int32_t fmi3Int32; /* 32-bit signed integer */ +typedef uint32_t fmi3UInt32; /* 32-bit unsigned integer */ +typedef int64_t fmi3Int64; /* 64-bit signed integer */ +typedef uint64_t fmi3UInt64; /* 64-bit unsigned integer */ +typedef bool fmi3Boolean; /* Data type to be used with fmi3True and fmi3False */ +typedef char fmi3Char; /* Data type for one character */ +typedef const fmi3Char *fmi3String; /* Data type for character strings + ('\0' terminated, UTF-8 encoded) */ +typedef uint8_t fmi3Byte; /* Smallest addressable unit of the machine + (typically one byte) */ +typedef const fmi3Byte *fmi3Binary; /* Data type for binary data + (out-of-band length terminated) */ +typedef bool fmi3Clock; /* Data type to be used with fmi3ClockActive and + fmi3ClockInactive */ + +/* Values for fmi3Boolean */ +#define fmi3True true +#define fmi3False false + +/* Values for fmi3Clock */ +#define fmi3ClockActive true +#define fmi3ClockInactive false +/* end::VariableTypes[] */ + +#endif /* fmi3PlatformTypes_h */ diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmiFunctions.h b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmiFunctions.h new file mode 100644 index 000000000..635348509 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmiFunctions.h @@ -0,0 +1,228 @@ +#ifndef fmiFunctions_h +#define fmiFunctions_h + +/* This header file must be utilized when compiling a FMU. + It defines all functions of Co-Simulation Interface. + In order to have unique function names even if several FMUs + are compiled together (e.g. for embedded systems), every "real" function name + is constructed by prepending the function name by + "MODEL_IDENTIFIER" + "_" where "MODEL_IDENTIFIER" is the short name + of the model used as the name of the zip-file where the model is stored. + Therefore, the typical usage is: + + #define MODEL_IDENTIFIER MyModel + #include "fmiFunctions.h" + + As a result, a function that is defined as "fmiGetDerivatives" in this header file, + is actually getting the name "MyModel_fmiGetDerivatives". + + Revisions: + - November 4, 2010: Adapted to specification text: + o fmiGetModelTypesPlatform renamed to fmiGetTypesPlatform + o fmiInstantiateSlave: Argument GUID replaced by fmuGUID + Argument mimetype replaced by mimeType + o tabs replaced by spaces + - October 16, 2010: First public Version + + + Copyright(c) 2017, MODELICA Association Project FMI. All rights reserved. + This file is licensed by the copyright holders under the BSD License + (http://www.opensource.org/licenses/bsd-license.html): + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- +*/ + +#include +#include "fmiPlatformTypes.h" + +/* Export fmi functions on Windows */ +#ifdef _MSC_VER +#define DllExport __declspec(dllexport) +#else +#define DllExport +#endif + +/* Macros to construct the real function name + (prepend function name by MODEL_IDENTIFIER + "_") */ + +#define fmiPaste(a, b) a##b +#define fmiPasteB(a, b) fmiPaste(a, b) +#define fmiFullName(name) fmiPasteB(MODEL_IDENTIFIER, name) + +/*************************************************** +Common Functions +****************************************************/ +#define fmiGetTypesPlatform fmiFullName(_fmiGetTypesPlatform) +#define fmiGetVersion fmiFullName(_fmiGetVersion) +#define fmiSetDebugLogging fmiFullName(_fmiSetDebugLogging) + +/*Data Exchange*/ +#define fmiSetReal fmiFullName(_fmiSetReal) +#define fmiSetInteger fmiFullName(_fmiSetInteger) +#define fmiSetBoolean fmiFullName(_fmiSetBoolean) +#define fmiSetString fmiFullName(_fmiSetString) + +#define fmiGetReal fmiFullName(_fmiGetReal) +#define fmiGetInteger fmiFullName(_fmiGetInteger) +#define fmiGetBoolean fmiFullName(_fmiGetBoolean) +#define fmiGetString fmiFullName(_fmiGetString) + +/*************************************************** +Functions for FMI for Co-Simulation +****************************************************/ +#define fmiInstantiateSlave fmiFullName(_fmiInstantiateSlave) +#define fmiInitializeSlave fmiFullName(_fmiInitializeSlave) +#define fmiTerminateSlave fmiFullName(_fmiTerminateSlave) +#define fmiResetSlave fmiFullName(_fmiResetSlave) +#define fmiFreeSlaveInstance fmiFullName(_fmiFreeSlaveInstance) +#define fmiSetRealInputDerivatives fmiFullName(_fmiSetRealInputDerivatives) +#define fmiGetRealOutputDerivatives fmiFullName(_fmiGetRealOutputDerivatives) +#define fmiDoStep fmiFullName(_fmiDoStep) +#define fmiCancelStep fmiFullName(_fmiCancelStep) +#define fmiGetStatus fmiFullName(_fmiGetStatus) +#define fmiGetRealStatus fmiFullName(_fmiGetRealStatus) +#define fmiGetIntegerStatus fmiFullName(_fmiGetIntegerStatus) +#define fmiGetBooleanStatus fmiFullName(_fmiGetBooleanStatus) +#define fmiGetStringStatus fmiFullName(_fmiGetStringStatus) + +/* Version number */ +#define fmiVersion "1.0" + +/* make sure all compiler use the same alignment policies for structures */ +#ifdef WIN32 +#pragma pack(push, 8) +#endif + +/* Type definitions */ +typedef enum { fmiOK, + fmiWarning, + fmiDiscard, + fmiError, + fmiFatal, + fmiPending } fmiStatus; + +typedef void (*fmiCallbackLogger)(fmiComponent c, fmiString instanceName, fmiStatus status, + fmiString category, fmiString message, ...); +typedef void *(*fmiCallbackAllocateMemory)(size_t nobj, size_t size); +typedef void (*fmiCallbackFreeMemory)(void *obj); +typedef void (*fmiStepFinished)(fmiComponent c, fmiStatus status); + +typedef struct { + fmiCallbackLogger logger; + fmiCallbackAllocateMemory allocateMemory; + fmiCallbackFreeMemory freeMemory; + fmiStepFinished stepFinished; +} fmiCallbackFunctions; + +typedef struct { + fmiBoolean iterationConverged; + fmiBoolean stateValueReferencesChanged; + fmiBoolean stateValuesChanged; + fmiBoolean terminateSimulation; + fmiBoolean upcomingTimeEvent; + fmiReal nextEventTime; +} fmiEventInfo; + +/* reset alignment policy to the one set before reading this file */ +#ifdef WIN32 +#pragma pack(pop) +#endif + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers of header files */ +DllExport const char *fmiGetTypesPlatform(); +DllExport const char *fmiGetVersion(); + +DllExport fmiStatus fmiSetDebugLogging(fmiComponent c, fmiBoolean loggingOn); + +/* Data Exchange Functions*/ +DllExport fmiStatus fmiGetReal(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiReal value[]); +DllExport fmiStatus fmiGetInteger(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiInteger value[]); +DllExport fmiStatus fmiGetBoolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiBoolean value[]); +DllExport fmiStatus fmiGetString(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiString value[]); + +DllExport fmiStatus fmiSetReal(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiReal value[]); +DllExport fmiStatus fmiSetInteger(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger value[]); +DllExport fmiStatus fmiSetBoolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiBoolean value[]); +DllExport fmiStatus fmiSetString(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiString value[]); + +/*************************************************** +Functions for FMI for Co-Simulation +****************************************************/ + +/* Creation and destruction of slave instances and setting debug status */ +DllExport fmiComponent fmiInstantiateSlave(fmiString instanceName, + fmiString fmuGUID, + fmiString fmuLocation, + fmiString mimeType, + fmiReal timeout, + fmiBoolean visible, + fmiBoolean interactive, + fmiCallbackFunctions functions, + fmiBoolean loggingOn); + +DllExport fmiStatus fmiInitializeSlave(fmiComponent c, + fmiReal tStart, + fmiBoolean StopTimeDefined, + fmiReal tStop); + +DllExport fmiStatus fmiTerminateSlave(fmiComponent c); +DllExport fmiStatus fmiResetSlave(fmiComponent c); +DllExport void fmiFreeSlaveInstance(fmiComponent c); + +DllExport fmiStatus fmiSetRealInputDerivatives(fmiComponent c, + const fmiValueReference vr[], + size_t nvr, + const fmiInteger order[], + const fmiReal value[]); + +DllExport fmiStatus fmiGetRealOutputDerivatives(fmiComponent c, + const fmiValueReference vr[], + size_t nvr, + const fmiInteger order[], + fmiReal value[]); + +DllExport fmiStatus fmiCancelStep(fmiComponent c); +DllExport fmiStatus fmiDoStep(fmiComponent c, + fmiReal currentCommunicationPoint, + fmiReal communicationStepSize, + fmiBoolean newStep); + +typedef enum { fmiDoStepStatus, + fmiPendingStatus, + fmiLastSuccessfulTime } fmiStatusKind; + +DllExport fmiStatus fmiGetStatus(fmiComponent c, const fmiStatusKind s, fmiStatus *value); +DllExport fmiStatus fmiGetRealStatus(fmiComponent c, const fmiStatusKind s, fmiReal *value); +DllExport fmiStatus fmiGetIntegerStatus(fmiComponent c, const fmiStatusKind s, fmiInteger *value); +DllExport fmiStatus fmiGetBooleanStatus(fmiComponent c, const fmiStatusKind s, fmiBoolean *value); +DllExport fmiStatus fmiGetStringStatus(fmiComponent c, const fmiStatusKind s, fmiString *value); + +#endif // fmiFunctions_h diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmiModelFunctions.h b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmiModelFunctions.h new file mode 100644 index 000000000..d6632a084 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmiModelFunctions.h @@ -0,0 +1,207 @@ +#ifndef fmiModelFunctions_h +#define fmiModelFunctions_h + +/* This header file must be utilized when compiling a model. + It defines all functions of the Model Execution Interface. + In order to have unique function names even if several models + are compiled together (e.g. for embedded systems), every "real" function name + is constructed by prepending the function name by + "MODEL_IDENTIFIER" + "_" where "MODEL_IDENTIFIER" is the short name + of the model used as the name of the zip-file where the model is stored. + Therefore, the typical usage is: + + #define MODEL_IDENTIFIER MyModel + #include "fmiModelFunctions.h" + + As a result, a function that is defined as "fmiGetDerivatives" in this header file, + is actually getting the name "MyModel_fmiGetDerivatives". + + Revisions: + - Jan. 20, 2010: stateValueReferencesChanged added to struct fmiEventInfo (ticket #27) + (by M. Otter, DLR) + Added WIN32 pragma to define the struct layout (ticket #34) + (by J. Mauss, QTronic) + - Jan. 4, 2010: Removed argument intermediateResults from fmiInitialize + Renamed macro fmiGetModelFunctionsVersion to fmiGetVersion + Renamed macro fmiModelFunctionsVersion to fmiVersion + Replaced fmiModel by fmiComponent in decl of fmiInstantiateModel + (by J. Mauss, QTronic) + - Dec. 17, 2009: Changed extension "me" to "fmi" (by Martin Otter, DLR). + - Dez. 14, 2009: Added eventInfo to meInitialize and added + meGetNominalContinuousStates (by Martin Otter, DLR) + - Sept. 9, 2009: Added DllExport (according to Peter Nilsson's suggestion) + (by A. Junghanns, QTronic) + - Sept. 9, 2009: Changes according to FMI-meeting on July 21: + meInquireModelTypesVersion -> meGetModelTypesPlatform + meInquireModelFunctionsVersion -> meGetModelFunctionsVersion + meSetStates -> meSetContinuousStates + meGetStates -> meGetContinuousStates + removal of meInitializeModelClass + removal of meGetTime + change of arguments of meInstantiateModel + change of arguments of meCompletedIntegratorStep + (by Martin Otter, DLR): + - July 19, 2009: Added "me" as prefix to file names (by Martin Otter, DLR). + - March 2, 2009: Changed function definitions according to the last design + meeting with additional improvements (by Martin Otter, DLR). + - Dec. 3 , 2008: First version by Martin Otter (DLR) and Hans Olsson (Dynasim). + + + Copyright(c) 2017, MODELICA Association Project FMI. All rights reserved. + This file is licensed by the copyright holders under the BSD License + (http://www.opensource.org/licenses/bsd-license.html): + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- + + with the extension: + + You may distribute or publicly perform any modification only under the + terms of this license. +*/ + +#include +#include "fmiModelTypes.h" + +/* Export fmi functions on Windows */ +#ifdef _MSC_VER +#define DllExport __declspec(dllexport) +#else +#define DllExport +#endif + +/* Macros to construct the real function name + (prepend function name by MODEL_IDENTIFIER + "_") */ + +#define fmiPaste(a, b) a##b +#define fmiPasteB(a, b) fmiPaste(a, b) +#define fmiFullName(name) fmiPasteB(MODEL_IDENTIFIER, name) + +#define fmiGetModelTypesPlatform fmiFullName(_fmiGetModelTypesPlatform) +#define fmiGetVersion fmiFullName(_fmiGetVersion) +#define fmiInstantiateModel fmiFullName(_fmiInstantiateModel) +#define fmiFreeModelInstance fmiFullName(_fmiFreeModelInstance) +#define fmiSetDebugLogging fmiFullName(_fmiSetDebugLogging) +#define fmiSetTime fmiFullName(_fmiSetTime) +#define fmiSetContinuousStates fmiFullName(_fmiSetContinuousStates) +#define fmiCompletedIntegratorStep fmiFullName(_fmiCompletedIntegratorStep) +#define fmiSetReal fmiFullName(_fmiSetReal) +#define fmiSetInteger fmiFullName(_fmiSetInteger) +#define fmiSetBoolean fmiFullName(_fmiSetBoolean) +#define fmiSetString fmiFullName(_fmiSetString) +#define fmiInitialize fmiFullName(_fmiInitialize) +#define fmiGetDerivatives fmiFullName(_fmiGetDerivatives) +#define fmiGetEventIndicators fmiFullName(_fmiGetEventIndicators) +#define fmiGetReal fmiFullName(_fmiGetReal) +#define fmiGetInteger fmiFullName(_fmiGetInteger) +#define fmiGetBoolean fmiFullName(_fmiGetBoolean) +#define fmiGetString fmiFullName(_fmiGetString) +#define fmiEventUpdate fmiFullName(_fmiEventUpdate) +#define fmiGetContinuousStates fmiFullName(_fmiGetContinuousStates) +#define fmiGetNominalContinuousStates fmiFullName(_fmiGetNominalContinuousStates) +#define fmiGetStateValueReferences fmiFullName(_fmiGetStateValueReferences) +#define fmiTerminate fmiFullName(_fmiTerminate) + +/* Version number */ +#define fmiVersion "1.0" + +/* Inquire version numbers of header files */ +DllExport const char *fmiGetModelTypesPlatform(); +DllExport const char *fmiGetVersion(); + +/* make sure all compiler use the same alignment policies for structures */ +#ifdef WIN32 +#pragma pack(push, 8) +#endif + +/* Type definitions */ +typedef enum { fmiOK, + fmiWarning, + fmiDiscard, + fmiError, + fmiFatal } fmiStatus; + +typedef void (*fmiCallbackLogger)(fmiComponent c, fmiString instanceName, fmiStatus status, + fmiString category, fmiString message, ...); +typedef void *(*fmiCallbackAllocateMemory)(size_t nobj, size_t size); +typedef void (*fmiCallbackFreeMemory)(void *obj); + +typedef struct { + fmiCallbackLogger logger; + fmiCallbackAllocateMemory allocateMemory; + fmiCallbackFreeMemory freeMemory; +} fmiCallbackFunctions; + +typedef struct { + fmiBoolean iterationConverged; + fmiBoolean stateValueReferencesChanged; + fmiBoolean stateValuesChanged; + fmiBoolean terminateSimulation; + fmiBoolean upcomingTimeEvent; + fmiReal nextEventTime; +} fmiEventInfo; + +/* reset alignment policy to the one set before reading this file */ +#ifdef WIN32 +#pragma pack(pop) +#endif + +/* Creation and destruction of model instances and setting debug status */ +DllExport fmiComponent fmiInstantiateModel(fmiString instanceName, + fmiString GUID, + fmiCallbackFunctions functions, + fmiBoolean loggingOn); +DllExport void fmiFreeModelInstance(fmiComponent c); +DllExport fmiStatus fmiSetDebugLogging(fmiComponent c, fmiBoolean loggingOn); + +/* Providing independent variables and re-initialization of caching */ +DllExport fmiStatus fmiSetTime(fmiComponent c, fmiReal time); +DllExport fmiStatus fmiSetContinuousStates(fmiComponent c, const fmiReal x[], size_t nx); +DllExport fmiStatus fmiCompletedIntegratorStep(fmiComponent c, fmiBoolean *callEventUpdate); +DllExport fmiStatus fmiSetReal(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiReal value[]); +DllExport fmiStatus fmiSetInteger(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger value[]); +DllExport fmiStatus fmiSetBoolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiBoolean value[]); +DllExport fmiStatus fmiSetString(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiString value[]); + +/* Evaluation of the model equations */ +DllExport fmiStatus fmiInitialize(fmiComponent c, fmiBoolean toleranceControlled, + fmiReal relativeTolerance, fmiEventInfo *eventInfo); + +DllExport fmiStatus fmiGetDerivatives(fmiComponent c, fmiReal derivatives[], size_t nx); +DllExport fmiStatus fmiGetEventIndicators(fmiComponent c, fmiReal eventIndicators[], size_t ni); + +DllExport fmiStatus fmiGetReal(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiReal value[]); +DllExport fmiStatus fmiGetInteger(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiInteger value[]); +DllExport fmiStatus fmiGetBoolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiBoolean value[]); +DllExport fmiStatus fmiGetString(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiString value[]); + +DllExport fmiStatus fmiEventUpdate(fmiComponent c, fmiBoolean intermediateResults, fmiEventInfo *eventInfo); +DllExport fmiStatus fmiGetContinuousStates(fmiComponent c, fmiReal states[], size_t nx); +DllExport fmiStatus fmiGetNominalContinuousStates(fmiComponent c, fmiReal x_nominal[], size_t nx); +DllExport fmiStatus fmiGetStateValueReferences(fmiComponent c, fmiValueReference vrx[], size_t nx); +DllExport fmiStatus fmiTerminate(fmiComponent c); + +#endif // fmiModelFunctions_h diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmiModelTypes.h b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmiModelTypes.h new file mode 100644 index 000000000..da92984ad --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmiModelTypes.h @@ -0,0 +1,91 @@ +#ifndef fmiModelTypes_h +#define fmiModelTypes_h + +/* Standard header file to define the argument types of the + functions of the Model Execution Interface. + This header file must be utilized both by the model and + by the simulation engine. + + Revisions: + - Jan. 4, 2010: Renamed meModelTypes_h to fmiModelTypes_h (by Mauss, QTronic) + - Dec. 21, 2009: Changed "me" to "fmi" and "meModel" to "fmiComponent" + according to meeting on Dec. 18 (by Martin Otter, DLR) + - Dec. 6, 2009: Added meUndefinedValueReference (by Martin Otter, DLR) + - Sept. 9, 2009: Changes according to FMI-meeting on July 21: + Changed "version" to "platform", "standard" to "standard32", + Added a precise definition of "standard32" as comment + (by Martin Otter, DLR) + - July 19, 2009: Added "me" as prefix to file names, added meTrue/meFalse, + and changed meValueReferenced from int to unsigned int + (by Martin Otter, DLR). + - March 2, 2009: Moved enums and function pointer definitions to + ModelFunctions.h (by Martin Otter, DLR). + - Dec. 3, 2008 : First version by Martin Otter (DLR) and + Hans Olsson (Dynasim). + + + Copyright(c) 2017, MODELICA Association Project FMI. All rights reserved. + This file is licensed by the copyright holders under the BSD License + (http://www.opensource.org/licenses/bsd-license.html) + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- + + with the extension: + + You may distribute or publicly perform any modification only under the + terms of this license. +*/ + +/* Platform (combination of machine, compiler, operating system) */ +#define fmiModelTypesPlatform "standard32" + +/* Type definitions of variables passed as arguments + Version "standard32" means: + + fmiComponent : 32 bit pointer + fmiValueReference: 32 bit + fmiReal : 64 bit + fmiInteger : 32 bit + fmiBoolean : 8 bit + fmiString : 32 bit pointer + +*/ +typedef void *fmiComponent; +typedef unsigned int fmiValueReference; +typedef double fmiReal; +typedef int fmiInteger; +typedef char fmiBoolean; +typedef const char *fmiString; + +/* Values for fmiBoolean */ +#define fmiTrue 1 +#define fmiFalse 0 + +/* Undefined value for fmiValueReference (largest unsigned int value) */ +#define fmiUndefinedValueReference (fmiValueReference)(-1) + +#endif diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmiPlatformTypes.h b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmiPlatformTypes.h new file mode 100644 index 000000000..ef9a78514 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/fmiPlatformTypes.h @@ -0,0 +1,73 @@ +#ifndef fmiPlatformTypes_h +#define fmiPlatformTypes_h + +/* Standard header file to define the argument types of the + functions of the Model Execution Interface. + This header file must be utilized both by the model and + by the simulation engine. + + Revisions: + - October 2010: First public Version + + + Copyright(c) 2017, MODELICA Association Project FMI. All rights reserved. + This file is licensed by the copyright holders under the BSD License + (http://www.opensource.org/licenses/bsd-license.html): + + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- +*/ + +/* Platform (combination of machine, compiler, operating system) */ +#define fmiPlatform "standard32" + +/* Type definitions of variables passed as arguments + Version "standard32" means: + + fmiComponent : 32 bit pointer + fmiValueReference: 32 bit + fmiReal : 64 bit + fmiInteger : 32 bit + fmiBoolean : 8 bit + fmiString : 32 bit pointer + +*/ +typedef void *fmiComponent; +typedef unsigned int fmiValueReference; +typedef double fmiReal; +typedef int fmiInteger; +typedef char fmiBoolean; +typedef const char *fmiString; + +/* Values for fmiBoolean */ +#define fmiTrue 1 +#define fmiFalse 0 + +/* Undefined value for fmiValueReference (largest unsigned int value) */ +#define fmiUndefinedValueReference (fmiValueReference)(-1) + +#endif diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/model.h b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/model.h new file mode 100644 index 000000000..f27a3c99a --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/include/model.h @@ -0,0 +1,235 @@ +#pragma once + +#if FMI_VERSION != 1 && FMI_VERSION != 2 && FMI_VERSION != 3 +#error FMI_VERSION must be one of 1, 2 or 3 +#endif + +#define UNUSED(x) (void) (x) + +#include // for bool +#include // for size_t +#include + +#include "config.h" + +#if FMI_VERSION == 1 + +#define not_modelError (Instantiated | Initialized | Terminated) + +typedef enum { + Instantiated = 1 << 0, + Initialized = 1 << 1, + Terminated = 1 << 2, + modelError = 1 << 3 +} ModelState; + +#elif FMI_VERSION == 2 + +typedef enum { + StartAndEnd = 1 << 0, + Instantiated = 1 << 1, + InitializationMode = 1 << 2, + + // ME states + EventMode = 1 << 3, + ContinuousTimeMode = 1 << 4, + + // CS states + StepComplete = 1 << 5, + StepInProgress = 1 << 6, + StepFailed = 1 << 7, + StepCanceled = 1 << 8, + + Terminated = 1 << 9, + modelError = 1 << 10, + modelFatal = 1 << 11, +} ModelState; + +#else + +typedef enum { + StartAndEnd = 1 << 0, + ConfigurationMode = 1 << 1, + Instantiated = 1 << 2, + InitializationMode = 1 << 3, + EventMode = 1 << 4, + ContinuousTimeMode = 1 << 5, + StepMode = 1 << 6, + ClockActivationMode = 1 << 7, + StepDiscarded = 1 << 8, + ReconfigurationMode = 1 << 9, + IntermediateUpdateMode = 1 << 10, + Terminated = 1 << 11, + modelError = 1 << 12, + modelFatal = 1 << 13, +} ModelState; + +#endif + +typedef enum { + ModelExchange, + CoSimulation, + ScheduledExecution, +} InterfaceType; + +typedef enum { + OK, + Warning, + Discard, + Error, + Fatal, + Pending +} Status; + +#if FMI_VERSION < 3 +typedef void (*loggerType)(void *componentEnvironment, const char *instanceName, int status, const char *category, const char *message, ...); +#else +typedef void (*loggerType)(void *componentEnvironment, int status, const char *category, const char *message); +#endif + +typedef void (*lockPreemptionType)(); +typedef void (*unlockPreemptionType)(); + +typedef void (*intermediateUpdateType)(void *instanceEnvironment, + double intermediateUpdateTime, + bool intermediateVariableSetRequested, + bool intermediateVariableGetAllowed, + bool intermediateStepFinished, + bool canReturnEarly, + bool *earlyReturnRequested, + double *earlyReturnTime); + +typedef void (*clockUpdateType)(void *instanceEnvironment); + +typedef struct { + + double startTime; + double time; + double solverStepSize; + const char *instanceName; + InterfaceType type; + const char *resourceLocation; + + Status status; + + // callback functions + loggerType logger; + intermediateUpdateType intermediateUpdate; + clockUpdateType clockUpdate; + + lockPreemptionType lockPreemtion; + unlockPreemptionType unlockPreemtion; + + bool logEvents; + bool logErrors; + + void *componentEnvironment; + ModelState state; + + // event info + bool newDiscreteStatesNeeded; + bool terminateSimulation; + bool nominalsOfContinuousStatesChanged; + bool valuesOfContinuousStatesChanged; + bool nextEventTimeDefined; + double nextEventTime; + bool clocksTicked; + + bool isDirtyValues; + + ModelData modelData; + +#if NZ > 0 + // event indicators + double z[NZ]; +#endif + + // internal solver steps + uint64_t nSteps; + + // Co-Simulation + bool earlyReturnAllowed; + bool eventModeUsed; + +} ModelInstance; + +ModelInstance *createModelInstance( + loggerType logger, + intermediateUpdateType intermediateUpdate, + void *componentEnvironment, + const char *instanceName, + const char *instantiationToken, + const char *resourceLocation, + bool loggingOn, + InterfaceType interfaceType); + +void freeModelInstance(ModelInstance *comp); + +void reset(ModelInstance *comp); + +void setStartValues(ModelInstance *comp); + +Status calculateValues(ModelInstance *comp); + +Status getFloat32(ModelInstance *comp, ValueReference vr, float value[], size_t *index); +Status getFloat64(ModelInstance *comp, ValueReference vr, double value[], size_t *index); +Status getInt8(ModelInstance *comp, ValueReference vr, int8_t value[], size_t *index); +Status getUInt8(ModelInstance *comp, ValueReference vr, uint8_t value[], size_t *index); +Status getInt16(ModelInstance *comp, ValueReference vr, int16_t value[], size_t *index); +Status getUInt16(ModelInstance *comp, ValueReference vr, uint16_t value[], size_t *index); +Status getInt32(ModelInstance *comp, ValueReference vr, int32_t value[], size_t *index); +Status getUInt32(ModelInstance *comp, ValueReference vr, uint32_t value[], size_t *index); +Status getInt64(ModelInstance *comp, ValueReference vr, int64_t value[], size_t *index); +Status getUInt64(ModelInstance *comp, ValueReference vr, uint64_t value[], size_t *index); +Status getBoolean(ModelInstance *comp, ValueReference vr, bool value[], size_t *index); +Status getString(ModelInstance *comp, ValueReference vr, const char *value[], size_t *index); +Status getBinary(ModelInstance *comp, ValueReference vr, size_t size[], const char *value[], size_t *index); + +Status setFloat32(ModelInstance *comp, ValueReference vr, const float value[], size_t *index); +Status setFloat64(ModelInstance *comp, ValueReference vr, const double value[], size_t *index); +Status setInt8(ModelInstance *comp, ValueReference vr, const int8_t value[], size_t *index); +Status setUInt8(ModelInstance *comp, ValueReference vr, const uint8_t value[], size_t *index); +Status setInt16(ModelInstance *comp, ValueReference vr, const int16_t value[], size_t *index); +Status setUInt16(ModelInstance *comp, ValueReference vr, const uint16_t value[], size_t *index); +Status setInt32(ModelInstance *comp, ValueReference vr, const int32_t value[], size_t *index); +Status setUInt32(ModelInstance *comp, ValueReference vr, const uint32_t value[], size_t *index); +Status setInt64(ModelInstance *comp, ValueReference vr, const int64_t value[], size_t *index); +Status setUInt64(ModelInstance *comp, ValueReference vr, const uint64_t value[], size_t *index); +Status setBoolean(ModelInstance *comp, ValueReference vr, const bool value[], size_t *index); +Status setString(ModelInstance *comp, ValueReference vr, const char *const value[], size_t *index); +Status setBinary(ModelInstance *comp, ValueReference vr, const size_t size[], const char *const value[], size_t *index); + +Status activateClock(ModelInstance *comp, ValueReference vr); +Status getClock(ModelInstance *comp, ValueReference vr, bool *value); +Status setClock(ModelInstance *comp, ValueReference vr, const bool *value); + +Status getInterval(ModelInstance *comp, ValueReference vr, double *interval, int *qualifier); + +Status activateModelPartition(ModelInstance *comp, ValueReference vr, double activationTime); + +void getContinuousStates(ModelInstance *comp, double x[], size_t nx); +void setContinuousStates(ModelInstance *comp, const double x[], size_t nx); +void getDerivatives(ModelInstance *comp, double dx[], size_t nx); +Status getOutputDerivative(ModelInstance *comp, ValueReference valueReference, int order, double *value); +Status getPartialDerivative(ModelInstance *comp, ValueReference unknown, ValueReference known, double *partialDerivative); +void getEventIndicators(ModelInstance *comp, double z[], size_t nz); +void eventUpdate(ModelInstance *comp); +// void updateEventTime(ModelInstance *comp); + +bool invalidNumber(ModelInstance *comp, const char *f, const char *arg, size_t actual, size_t expected); +bool invalidState(ModelInstance *comp, const char *f, int statesExpected); +bool nullPointer(ModelInstance *comp, const char *f, const char *arg, const void *p); +void logError(ModelInstance *comp, const char *message, ...); +Status setDebugLogging(ModelInstance *comp, bool loggingOn, size_t nCategories, const char *const categories[]); +void logEvent(ModelInstance *comp, const char *message, ...); +void logError(ModelInstance *comp, const char *message, ...); + +void *getFMUState(ModelInstance *comp); +void setFMUState(ModelInstance *comp, void *FMUState); + +// shorthand to access the variables +#define M(u) (comp->modelData.u) + +// "stringification" macros +#define xstr(s) str(s) +#define str(s) #s diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/set_tool_version.py b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/set_tool_version.py new file mode 100644 index 000000000..9a544bb5e --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/set_tool_version.py @@ -0,0 +1,45 @@ +import os.path +import subprocess +import sys + + +def set_tool_version(filename, git_executable='git'): + """ Set the Git tag or hash in the generationTool attribute if the repo is clean """ + + cwd = os.path.dirname(__file__) + + changed_files = subprocess.check_output( + [git_executable, 'status', '--porcelain', '--untracked=no'], cwd=cwd).decode('ascii').strip() + + if changed_files: + return + + version = subprocess.check_output([git_executable, 'tag', '--contains'], cwd=cwd).decode('ascii').strip() + + if not version: + version = subprocess.check_output([git_executable, 'rev-parse', '--short', + 'HEAD'], cwd=cwd).decode('ascii').strip() + + if not version: + return + + with open(filename, 'r') as f: + lines = f.read() + + lines = lines.replace('"Reference FMUs (development build)"', f'"Reference FMUs ({version})"') + + with open(filename, 'w') as f: + f.write(lines) + + +if __name__ == '__main__': + + try: + if len(sys.argv) > 2: + set_tool_version(sys.argv[1], sys.argv[2]) + elif len(sys.argv) > 1: + set_tool_version(sys.argv[1]) + else: + raise RuntimeError('Not enough arguments') + except Exception as e: + print(e) diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/FMI.c b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/FMI.c new file mode 100644 index 000000000..b3fd16044 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/FMI.c @@ -0,0 +1,329 @@ +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#pragma comment(lib, "shlwapi.lib") +#else +#include +#include +#endif + +#ifdef _MSC_VER +#define strdup _strdup +#endif + +#include "FMI.h" + +#define INITIAL_MESSAGE_BUFFER_SIZE 1024 + +FMIInstance *FMICreateInstance(const char *instanceName, const char *libraryPath, FMILogMessage *logMessage, FMILogFunctionCall *logFunctionCall) +{ + +#ifdef _WIN32 + TCHAR Buffer[1024]; + GetCurrentDirectory(1024, Buffer); + + WCHAR dllDirectory[MAX_PATH]; + + // convert path to unicode + mbstowcs(dllDirectory, libraryPath, MAX_PATH); + + // remove the file name + PathRemoveFileSpecW(dllDirectory); + + // add the binaries directory temporarily to the DLL path to allow discovery of dependencies + DLL_DIRECTORY_COOKIE dllDirectoryCookie = AddDllDirectory(dllDirectory); + + // TODO: log getLastSystemError() + + HMODULE libraryHandle = LoadLibraryExA(libraryPath, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + + // remove the binaries directory from the DLL path + if (dllDirectoryCookie) { + RemoveDllDirectory(dllDirectoryCookie); + } + + // TODO: log error + +#else + void *libraryHandle = dlopen(libraryPath, RTLD_LAZY); +#endif + + if (!libraryHandle) { + return NULL; + } + + FMIInstance *instance = (FMIInstance *) calloc(1, sizeof(FMIInstance)); + + instance->libraryHandle = libraryHandle; + + instance->logMessage = logMessage; + instance->logFunctionCall = logFunctionCall; + + instance->bufsize1 = INITIAL_MESSAGE_BUFFER_SIZE; + instance->bufsize2 = INITIAL_MESSAGE_BUFFER_SIZE; + + instance->buf1 = (char *) calloc(instance->bufsize1, sizeof(char)); + instance->buf2 = (char *) calloc(instance->bufsize1, sizeof(char)); + + instance->name = strdup(instanceName); + + instance->status = FMIOK; + + return instance; +} + +void FMIFreeInstance(FMIInstance *instance) +{ + + if (!instance) { + return; + } + + // unload the shared library + if (instance->libraryHandle) { +#ifdef _WIN32 + FreeLibrary(instance->libraryHandle); +#else + dlclose(instance->libraryHandle); +#endif + instance->libraryHandle = NULL; + } + + free(instance->buf1); + free(instance->buf2); + free((void *) instance->name); + + free(instance->fmi2Functions); + free(instance->fmi3Functions); + + free(instance); +} + +const char *FMIValueReferencesToString(FMIInstance *instance, const FMIValueReference vr[], size_t nvr) +{ + + size_t pos = 0; + + do { + pos += snprintf(&instance->buf1[pos], instance->bufsize1 - pos, "{"); + + for (size_t i = 0; i < nvr; i++) { + + pos += snprintf(&instance->buf1[pos], instance->bufsize1 - pos, i < nvr - 1 ? "%u, " : "%u", vr[i]); + + if (pos > instance->bufsize1 - 2) { + pos = 0; + instance->bufsize1 *= 2; + instance->buf1 = (char *) realloc(instance->buf1, instance->bufsize1); + break; + } + } + } while (pos == 0); + + pos += snprintf(&instance->buf1[pos], instance->bufsize1 - pos, "}"); + + return instance->buf1; +} + +const char *FMIValuesToString(FMIInstance *instance, size_t vValues, const size_t sizes[], const void *values, FMIVariableType variableType) +{ + + size_t pos = 0; + + do { + pos += snprintf(&instance->buf2[pos], instance->bufsize2 - pos, "{"); + + for (size_t i = 0; i < vValues; i++) { + + char *s = &instance->buf2[pos]; + size_t n = instance->bufsize2 - pos; + + switch (variableType) { + case FMIFloat32Type: + case FMIDiscreteFloat32Type: + pos += snprintf(s, n, "%.7g", ((float *) values)[i]); + break; + case FMIFloat64Type: + case FMIDiscreteFloat64Type: + pos += snprintf(s, n, "%.16g", ((double *) values)[i]); + break; + case FMIInt8Type: + pos += snprintf(s, n, "%" PRId8, ((int8_t *) values)[i]); + break; + case FMIUInt8Type: + pos += snprintf(s, n, "%" PRIu8, ((uint8_t *) values)[i]); + break; + case FMIInt16Type: + pos += snprintf(s, n, "%" PRId16, ((int16_t *) values)[i]); + break; + case FMIUInt16Type: + pos += snprintf(s, n, "%" PRIu16, ((uint16_t *) values)[i]); + break; + case FMIInt32Type: + pos += snprintf(s, n, "%" PRId32, ((int32_t *) values)[i]); + break; + case FMIUInt32Type: + pos += snprintf(s, n, "%" PRIu32, ((uint32_t *) values)[i]); + break; + case FMIInt64Type: + pos += snprintf(s, n, "%" PRId64, ((int64_t *) values)[i]); + break; + case FMIUInt64Type: + pos += snprintf(s, n, "%" PRIu64, ((uint64_t *) values)[i]); + break; + case FMIBooleanType: + switch (instance->fmiVersion) { + case FMIVersion1: + pos += snprintf(s, n, "%d", ((char *) values)[i]); + break; + case FMIVersion2: + pos += snprintf(s, n, "%d", ((int *) values)[i]); + break; + case FMIVersion3: + pos += snprintf(s, n, "%d", ((bool *) values)[i]); + break; + } + break; + case FMIStringType: + pos += snprintf(s, n, "\"%s\"", ((const char **) values)[i]); + break; + case FMIBinaryType: { + const size_t size = sizes[i]; + const unsigned char *v = ((const unsigned char **) values)[i]; + for (size_t j = 0; j < size; j++) { + pos += snprintf(&instance->buf2[pos], instance->bufsize2 - pos, "%02hhx", v[j]); + } + break; + } + case FMIClockType: + pos += snprintf(s, n, "%d", ((bool *) values)[i]); + break; + } + + if (i < vValues - 1) { + pos += snprintf(&instance->buf2[pos], instance->bufsize2 - pos, ", "); + } + + // resize the buffer if we ran out of space + if (pos > instance->bufsize2 - 2) { + pos = 0; + instance->bufsize2 *= 2; + instance->buf2 = (char *) realloc(instance->buf2, instance->bufsize2); + break; + } + } + + } while (pos == 0); // run again if the buffer has been resized + + pos += snprintf(&instance->buf2[pos], instance->bufsize2 - pos, "}"); + + return instance->buf2; +} + +FMIStatus FMIURIToPath(const char *uri, char *path, const size_t pathLength) +{ + +#ifdef _WIN32 + DWORD pcchPath = (DWORD) pathLength; + + if (PathCreateFromUrlA(uri, path, &pcchPath, 0) != S_OK) { + return FMIError; + } +#else + const char *scheme1 = "file:///"; + const char *scheme2 = "file:/"; + + strncpy(path, uri, pathLength); + + if (strncmp(uri, scheme1, strlen(scheme1)) == 0) { + strncpy(path, &uri[strlen(scheme1)] - 1, pathLength); + } else if (strncmp(uri, scheme2, strlen(scheme2)) == 0) { + strncpy(path, &uri[strlen(scheme2) - 1], pathLength); + } else { + return FMIError; + } +#endif + +#ifdef _WIN32 + const char *sep = "\\"; +#else + const char *sep = "/"; +#endif + + if (path[strlen(path) - 1] != sep[0]) { + strncat(path, sep, pathLength); + } + + return FMIOK; +} + +FMIStatus FMIPathToURI(const char *path, char *uri, const size_t uriLength) +{ + +#ifdef _WIN32 + DWORD pcchUri = (DWORD) uriLength; + + if (UrlCreateFromPathA(path, uri, &pcchUri, 0) != S_OK) { + return FMIError; + } +#else + snprintf(uri, uriLength, "file://%s", path); + + if (path[strlen(path) - 1] != '/') { + strncat(uri, "/", uriLength); + } +#endif + + return FMIOK; +} + +FMIStatus FMIPlatformBinaryPath(const char *unzipdir, const char *modelIdentifier, FMIVersion fmiVersion, char *platformBinaryPath, size_t size) +{ + +#if defined(_WIN32) + const char *platform = "win"; + const char *system = "windows"; + const char sep = '\\'; + const char *ext = ".dll"; +#elif defined(__APPLE__) + const char *platform = "darwin"; + const char *system = "darwin"; + const char sep = '/'; + const char *ext = ".dylib"; +#else + const char *platform = "linux"; + const char *system = "linux"; + const char sep = '/'; + const char *ext = ".so"; +#endif + +#if defined(_WIN64) || defined(__x86_64__) + const char *bits = "64"; + const char *arch = "x86_64"; +#else + const char *bits = "32"; + const char *arch = "x86"; +#endif + const char *bin = "binaries"; + char optSep[2] = ""; + int rc; + + if (unzipdir[strlen(unzipdir) - 1] != sep) { + optSep[0] = sep; + } + if (fmiVersion == 3) { + rc = snprintf(platformBinaryPath, size, "%s%s%s%c%s-%s%c%s%s", unzipdir, optSep, bin, sep, arch, system, sep, modelIdentifier, ext); + } else { + rc = snprintf(platformBinaryPath, size, "%s%s%s%c%s%s%c%s%s", unzipdir, optSep, bin, sep, platform, bits, sep, modelIdentifier, ext); + } + + if (rc >= size) { + return FMIError; + } + + return FMIOK; +} diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/FMI2.c b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/FMI2.c new file mode 100644 index 000000000..b0321c653 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/FMI2.c @@ -0,0 +1,569 @@ +#ifdef _WIN32 +#include +#include "Shlwapi.h" +#pragma comment(lib, "shlwapi.lib") +#define strdup _strdup +#define INTERNET_MAX_URL_LENGTH 2083 // from wininet.h +#else +#include +#include +#endif + +#include +#include +#include + +#include "FMI2.h" + +static void cb_logMessage2(fmi2ComponentEnvironment componentEnvironment, fmi2String instanceName, fmi2Status status, fmi2String category, fmi2String message, ...) +{ + + if (!componentEnvironment) + return; + + FMIInstance *instance = componentEnvironment; + + char buf[FMI_MAX_MESSAGE_LENGTH]; + + va_list args; + + va_start(args, message); + vsnprintf(buf, FMI_MAX_MESSAGE_LENGTH, message, args); + va_end(args); + + if (!instance->logMessage) + return; + + instance->logMessage(instance, (FMIStatus) status, category, buf); +} + +#if defined(FMI2_FUNCTION_PREFIX) +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi2Functions->fmi2##f = fmi2##f; \ + } while (0) +#elif defined(_WIN32) +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi2Functions->fmi2##f = (fmi2##f##TYPE *) GetProcAddress(instance->libraryHandle, "fmi2" #f); \ + if (!instance->fmi2Functions->fmi2##f) { \ + instance->logMessage(instance, FMIFatal, "fatal", "Symbol fmi2" #f " is missing in shared library."); \ + return fmi2Fatal; \ + } \ + } while (0) +#else +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi2Functions->fmi2##f = (fmi2##f##TYPE *) dlsym(instance->libraryHandle, "fmi2" #f); \ + if (!instance->fmi2Functions->fmi2##f) { \ + instance->logMessage(instance, FMIFatal, "fatal", "Symbol fmi2" #f " is missing in shared library."); \ + return FMIFatal; \ + } \ + } while (0) +#endif + +#define CALL(f) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2##f(instance->component); \ + if (instance->logFunctionCall) { \ + instance->logFunctionCall(instance, status, "fmi2" #f "()"); \ + } \ + return status; \ + } while (0) + +#define CALL_ARGS(f, m, ...) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2##f(instance->component, __VA_ARGS__); \ + if (instance->logFunctionCall) { \ + instance->logFunctionCall(instance, status, "fmi2" #f "(" m ")", __VA_ARGS__); \ + } \ + return status; \ + } while (0) + +#define CALL_ARRAY(s, t) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2##s##t(instance->component, vr, nvr, value); \ + if (instance->logFunctionCall) { \ + FMIValueReferencesToString(instance, vr, nvr); \ + FMIValuesToString(instance, nvr, NULL, value, FMI##t##Type); \ + instance->logFunctionCall(instance, status, "fmi2" #s #t "(vr=%s, nvr=%zu, value=%s)", instance->buf1, nvr, instance->buf2); \ + } \ + return status; \ + } while (0) + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers of header files and setting logging status */ +const char *FMI2GetTypesPlatform(FMIInstance *instance) +{ + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, FMIOK, "fmi2GetTypesPlatform()"); + } + return instance->fmi2Functions->fmi2GetTypesPlatform(); +} + +const char *FMI2GetVersion(FMIInstance *instance) +{ + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, FMIOK, "fmi2GetVersion()"); + } + return instance->fmi2Functions->fmi2GetVersion(); +} + +FMIStatus FMI2SetDebugLogging(FMIInstance *instance, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2SetDebugLogging(instance->component, loggingOn, nCategories, categories); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nCategories, NULL, categories, FMIStringType); + instance->logFunctionCall(instance, status, "fmi2SetDebugLogging(loggingOn=%d, nCategories=%zu, categories=%s)", + loggingOn, nCategories, instance->buf2); + } + return status; +} + +/* Creation and destruction of FMU instances and setting debug status */ +FMIStatus FMI2Instantiate(FMIInstance *instance, const char *fmuResourceLocation, fmi2Type fmuType, fmi2String fmuGUID, + fmi2Boolean visible, fmi2Boolean loggingOn) +{ + + instance->fmiVersion = FMIVersion2; + + instance->fmi2Functions = calloc(1, sizeof(FMI2Functions)); + + if (!instance->fmi2Functions) { + return FMIError; + } + + instance->fmi2Functions->eventInfo.newDiscreteStatesNeeded = fmi2False; + instance->fmi2Functions->eventInfo.terminateSimulation = fmi2False; + instance->fmi2Functions->eventInfo.nominalsOfContinuousStatesChanged = fmi2False; + instance->fmi2Functions->eventInfo.valuesOfContinuousStatesChanged = fmi2False; + instance->fmi2Functions->eventInfo.nextEventTimeDefined = fmi2False; + instance->fmi2Functions->eventInfo.nextEventTime = 0.0; + + instance->state = FMI2StartAndEndState; + +#if !defined(FMI_VERSION) || FMI_VERSION == 2 + + /*************************************************** + Common Functions + ****************************************************/ + + /* required functions */ + LOAD_SYMBOL(GetTypesPlatform); + LOAD_SYMBOL(GetVersion); + LOAD_SYMBOL(SetDebugLogging); + LOAD_SYMBOL(Instantiate); + LOAD_SYMBOL(FreeInstance); + LOAD_SYMBOL(SetupExperiment); + LOAD_SYMBOL(EnterInitializationMode); + LOAD_SYMBOL(ExitInitializationMode); + LOAD_SYMBOL(Terminate); + LOAD_SYMBOL(Reset); + LOAD_SYMBOL(GetReal); + LOAD_SYMBOL(GetInteger); + LOAD_SYMBOL(GetBoolean); + LOAD_SYMBOL(GetString); + LOAD_SYMBOL(SetReal); + LOAD_SYMBOL(SetInteger); + LOAD_SYMBOL(SetBoolean); + LOAD_SYMBOL(SetString); + + /* optional functions */ + LOAD_SYMBOL(GetFMUstate); + LOAD_SYMBOL(SetFMUstate); + LOAD_SYMBOL(FreeFMUstate); + LOAD_SYMBOL(SerializedFMUstateSize); + LOAD_SYMBOL(SerializeFMUstate); + LOAD_SYMBOL(DeSerializeFMUstate); + LOAD_SYMBOL(GetDirectionalDerivative); + + if (fmuType == fmi2ModelExchange) { +#ifndef CO_SIMULATION + /*************************************************** + Model Exchange + ****************************************************/ + + LOAD_SYMBOL(EnterEventMode); + LOAD_SYMBOL(NewDiscreteStates); + LOAD_SYMBOL(EnterContinuousTimeMode); + LOAD_SYMBOL(CompletedIntegratorStep); + LOAD_SYMBOL(SetTime); + LOAD_SYMBOL(SetContinuousStates); + LOAD_SYMBOL(GetDerivatives); + LOAD_SYMBOL(GetEventIndicators); + LOAD_SYMBOL(GetContinuousStates); + LOAD_SYMBOL(GetNominalsOfContinuousStates); +#endif + } else { +#ifndef MODEL_EXCHANGE + /*************************************************** + Co-Simulation + ****************************************************/ + + LOAD_SYMBOL(SetRealInputDerivatives); + LOAD_SYMBOL(GetRealOutputDerivatives); + LOAD_SYMBOL(DoStep); + LOAD_SYMBOL(CancelStep); + LOAD_SYMBOL(GetStatus); + LOAD_SYMBOL(GetRealStatus); + LOAD_SYMBOL(GetIntegerStatus); + LOAD_SYMBOL(GetBooleanStatus); + LOAD_SYMBOL(GetStringStatus); +#endif + } + +#endif + + instance->fmi2Functions->callbacks.logger = cb_logMessage2; + instance->fmi2Functions->callbacks.allocateMemory = calloc; + instance->fmi2Functions->callbacks.freeMemory = free; + instance->fmi2Functions->callbacks.stepFinished = NULL; + instance->fmi2Functions->callbacks.componentEnvironment = instance; + + instance->component = instance->fmi2Functions->fmi2Instantiate(instance->name, fmuType, fmuGUID, fmuResourceLocation, &instance->fmi2Functions->callbacks, visible, loggingOn); + + if (instance->logFunctionCall) { + fmi2CallbackFunctions *f = &instance->fmi2Functions->callbacks; + instance->logFunctionCall(instance, instance->component ? FMIOK : FMIError, + "fmi2Instantiate(instanceName=\"%s\", fmuType=%d, fmuGUID=\"%s\", fmuResourceLocation=\"%s\", functions={logger=0x%p, allocateMemory=0x%p, freeMemory=0x%p, stepFinished=0x%p, componentEnvironment=0x%p}, visible=%d, loggingOn=%d)", + instance->name, fmuType, fmuGUID, fmuResourceLocation, f->logger, f->allocateMemory, f->freeMemory, f->stepFinished, f->componentEnvironment, visible, loggingOn); + } + + if (!instance->component) { + return FMIError; + } + + instance->interfaceType = (FMIInterfaceType) fmuType; + instance->state = FMI2InstantiatedState; + + return FMIOK; +} + +void FMI2FreeInstance(FMIInstance *instance) +{ + + if (!instance) { + return; + } + + instance->fmi2Functions->fmi2FreeInstance(instance->component); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, FMIOK, "fmi2FreeInstance()"); + } +} + +/* Enter and exit initialization mode, terminate and reset */ +FMIStatus FMI2SetupExperiment(FMIInstance *instance, + fmi2Boolean toleranceDefined, + fmi2Real tolerance, + fmi2Real startTime, + fmi2Boolean stopTimeDefined, + fmi2Real stopTime) +{ + + instance->time = startTime; + + CALL_ARGS(SetupExperiment, "toleranceDefined=%d, tolerance=%.16g, startTime=%.16g, stopTimeDefined=%d, stopTime=%.16g", toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); +} + +FMIStatus FMI2EnterInitializationMode(FMIInstance *instance) +{ + instance->state = FMI2InitializationModeState; + CALL(EnterInitializationMode); +} + +FMIStatus FMI2ExitInitializationMode(FMIInstance *instance) +{ + instance->state = instance->interfaceType == FMIModelExchange ? FMI2EventModeState : FMI2StepCompleteState; + CALL(ExitInitializationMode); +} + +FMIStatus FMI2Terminate(FMIInstance *instance) +{ + instance->state = FMI2TerminatedState; + CALL(Terminate); +} + +FMIStatus FMI2Reset(FMIInstance *instance) +{ + instance->state = FMI2InstantiatedState; + CALL(Reset); +} + +/* Getting and setting variable values */ +FMIStatus FMI2GetReal(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) +{ + CALL_ARRAY(Get, Real); +} + +FMIStatus FMI2GetInteger(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) +{ + CALL_ARRAY(Get, Integer); +} + +FMIStatus FMI2GetBoolean(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]) +{ + CALL_ARRAY(Get, Boolean); +} + +FMIStatus FMI2GetString(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) +{ + CALL_ARRAY(Get, String); +} + +FMIStatus FMI2SetReal(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) +{ + CALL_ARRAY(Set, Real); +} + +FMIStatus FMI2SetInteger(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) +{ + CALL_ARRAY(Set, Integer); +} + +FMIStatus FMI2SetBoolean(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) +{ + CALL_ARRAY(Set, Boolean); +} + +FMIStatus FMI2SetString(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) +{ + CALL_ARRAY(Set, String); +} + +/* Getting and setting the internal FMU state */ +FMIStatus FMI2GetFMUstate(FMIInstance *instance, fmi2FMUstate *FMUstate) +{ + CALL_ARGS(GetFMUstate, "FMUstate=0x%p", FMUstate); +} + +FMIStatus FMI2SetFMUstate(FMIInstance *instance, fmi2FMUstate FMUstate) +{ + CALL_ARGS(SetFMUstate, "FMUstate=0x%p", FMUstate); +} + +FMIStatus FMI2FreeFMUstate(FMIInstance *instance, fmi2FMUstate *FMUstate) +{ + CALL_ARGS(FreeFMUstate, "FMUstate=0x%p", FMUstate); +} + +FMIStatus FMI2SerializedFMUstateSize(FMIInstance *instance, fmi2FMUstate FMUstate, size_t *size) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2SerializedFMUstateSize(instance->component, FMUstate, size); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2SerializedFMUstateSize(FMUstate=0x%p, size=%zu)", FMUstate, *size); + } + return status; +} + +FMIStatus FMI2SerializeFMUstate(FMIInstance *instance, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size) +{ + CALL_ARGS(SerializeFMUstate, "FMUstate=0x%p, serializedState=0x%p, size=%zu", FMUstate, serializedState, size); +} + +FMIStatus FMI2DeSerializeFMUstate(FMIInstance *instance, const fmi2Byte serializedState[], size_t size, fmi2FMUstate *FMUstate) +{ + CALL_ARGS(DeSerializeFMUstate, "serializedState=0x%p, size=%zu, FMUstate=0x%p", serializedState, size, FMUstate); +} + +/* Getting partial derivatives */ +FMIStatus FMI2GetDirectionalDerivative(FMIInstance *instance, + const fmi2ValueReference vUnknown_ref[], size_t nUnknown, + const fmi2ValueReference vKnown_ref[], size_t nKnown, + const fmi2Real dvKnown[], + fmi2Real dvUnknown[]) +{ + CALL_ARGS(GetDirectionalDerivative, "vUnknown_ref=0x%p, nUnknown=%zu, vKnown_ref=0x%p, nKnown=%zu, dvKnown=0x%p, dvUnknown=0x%p", + vUnknown_ref, nUnknown, vKnown_ref, nKnown, dvKnown, dvUnknown); +} + +/*************************************************** +Model Exchange +****************************************************/ + +/* Enter and exit the different modes */ +FMIStatus FMI2EnterEventMode(FMIInstance *instance) +{ + instance->state = FMI2EventModeState; + CALL(EnterEventMode); +} + +FMIStatus FMI2NewDiscreteStates(FMIInstance *instance, fmi2EventInfo *eventInfo) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2NewDiscreteStates(instance->component, eventInfo); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, + "fmi2NewDiscreteStates(eventInfo={newDiscreteStatesNeeded=%d, terminateSimulation=%d, nominalsOfContinuousStatesChanged=%d, valuesOfContinuousStatesChanged=%d, nextEventTimeDefined=%d, nextEventTime=%.16g})", + eventInfo->newDiscreteStatesNeeded, eventInfo->terminateSimulation, eventInfo->nominalsOfContinuousStatesChanged, eventInfo->valuesOfContinuousStatesChanged, eventInfo->nextEventTimeDefined, eventInfo->nextEventTime); + } + return status; +} + +FMIStatus FMI2EnterContinuousTimeMode(FMIInstance *instance) +{ + instance->state = FMI2ContinuousTimeModeState; + CALL(EnterContinuousTimeMode); +} + +FMIStatus FMI2CompletedIntegratorStep(FMIInstance *instance, + fmi2Boolean noSetFMUStatePriorToCurrentPoint, + fmi2Boolean *enterEventMode, + fmi2Boolean *terminateSimulation) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2CompletedIntegratorStep(instance->component, noSetFMUStatePriorToCurrentPoint, enterEventMode, terminateSimulation); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2CompletedIntegratorStep(noSetFMUStatePriorToCurrentPoint=%d, enterEventMode=%d, terminateSimulation=%d)", noSetFMUStatePriorToCurrentPoint, *enterEventMode, *terminateSimulation); + } + return status; +} + +/* Providing independent variables and re-initialization of caching */ +FMIStatus FMI2SetTime(FMIInstance *instance, fmi2Real time) +{ + instance->time = time; + CALL_ARGS(SetTime, "time=%.16g", time); +} + +FMIStatus FMI2SetContinuousStates(FMIInstance *instance, const fmi2Real x[], size_t nx) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2SetContinuousStates(instance->component, x, nx); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nx, NULL, x, FMIRealType); + instance->logFunctionCall(instance, status, "fmi2SetContinuousStates(x=%s, nx=%zu)", instance->buf2, nx); + } + return status; +} + +/* Evaluation of the model equations */ +FMIStatus FMI2GetDerivatives(FMIInstance *instance, fmi2Real derivatives[], size_t nx) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetDerivatives(instance->component, derivatives, nx); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nx, NULL, derivatives, FMIRealType); + instance->logFunctionCall(instance, status, "fmi2GetDerivatives(derivatives=%s, nx=%zu)", instance->buf2, nx); + } + return status; +} + +FMIStatus FMI2GetEventIndicators(FMIInstance *instance, fmi2Real eventIndicators[], size_t ni) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetEventIndicators(instance->component, eventIndicators, ni); + if (instance->logFunctionCall) { + FMIValuesToString(instance, ni, NULL, eventIndicators, FMIRealType); + instance->logFunctionCall(instance, status, "fmi2GetEventIndicators(eventIndicators=%s, ni=%zu)", instance->buf2, ni); + } + return status; +} + +FMIStatus FMI2GetContinuousStates(FMIInstance *instance, fmi2Real x[], size_t nx) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetContinuousStates(instance->component, x, nx); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nx, NULL, x, FMIRealType); + instance->logFunctionCall(instance, status, "fmi2GetContinuousStates(x=%s, nx=%zu)", instance->buf2, nx); + } + return status; +} + +FMIStatus FMI2GetNominalsOfContinuousStates(FMIInstance *instance, fmi2Real x_nominal[], size_t nx) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetNominalsOfContinuousStates(instance->component, x_nominal, nx); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nx, NULL, x_nominal, FMIRealType); + instance->logFunctionCall(instance, status, "fmi2GetNominalsOfContinuousStates(x_nominal=%s, nx=%zu)", instance->buf2, nx); + } + return status; +} + +/*************************************************** +Co-Simulation +****************************************************/ + +/* Simulating the slave */ +FMIStatus FMI2SetRealInputDerivatives(FMIInstance *instance, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + const fmi2Real value[]) +{ + CALL_ARGS(SetRealInputDerivatives, "vr=0x%p, nvr=%zu, order=0x%p, value=0x%p", vr, nvr, order, value); +} + +FMIStatus FMI2GetRealOutputDerivatives(FMIInstance *instance, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + fmi2Real value[]) +{ + CALL_ARGS(GetRealOutputDerivatives, "vr=0x%p, nvr=%zu, order=0x%p, value=0x%p", vr, nvr, order, value); +} + +FMIStatus FMI2DoStep(FMIInstance *instance, + fmi2Real currentCommunicationPoint, + fmi2Real communicationStepSize, + fmi2Boolean noSetFMUStatePriorToCurrentPoint) +{ + + instance->time = currentCommunicationPoint + communicationStepSize; + + CALL_ARGS(DoStep, "currentCommunicationPoint=%.16g, communicationStepSize=%.16g, noSetFMUStatePriorToCurrentPoint=%d", + currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint); +} + +FMIStatus FMI2CancelStep(FMIInstance *instance) +{ + CALL(CancelStep); +} + +/* Inquire slave status */ +FMIStatus FMI2GetStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Status *value) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetStatus(instance->component, s, value); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2GetStatus(s=%d, value=%d)", s, *value); + } + return status; +} + +FMIStatus FMI2GetRealStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Real *value) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetRealStatus(instance->component, s, value); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2GetRealStatus(s=%d, value=%.16g)", s, *value); + } + return status; +} + +FMIStatus FMI2GetIntegerStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Integer *value) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetIntegerStatus(instance->component, s, value); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2GetIntegerStatus(s=%d, value=%d)", s, *value); + } + return status; +} + +FMIStatus FMI2GetBooleanStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Boolean *value) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetBooleanStatus(instance->component, s, value); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2GetBooleanStatus(s=%d, value=%d)", s, *value); + } + return status; +} + +FMIStatus FMI2GetStringStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2String *value) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetStringStatus(instance->component, s, value); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2GetStringStatus(s=%d, value=%s)", s, *value); + } + return status; +} + +#undef LOAD_SYMBOL +#undef CALL +#undef CALL_ARGS +#undef CALL_ARRAY diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/FMI3.c b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/FMI3.c new file mode 100644 index 000000000..3b13c02bd --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/FMI3.c @@ -0,0 +1,1186 @@ +#ifdef _WIN32 +#include +#include "Shlwapi.h" +#pragma comment(lib, "shlwapi.lib") +#else +#include +#include +#endif + +#include +#include +#include + +#include "FMI3.h" + +static void cb_logMessage3(fmi3InstanceEnvironment instanceEnvironment, + fmi3Status status, + fmi3String category, + fmi3String message) +{ + + if (!instanceEnvironment) + return; + + FMIInstance *instance = instanceEnvironment; + + if (!instance->logMessage) + return; + + instance->logMessage(instance, (FMIStatus) status, category, message); +} + +#if defined(FMI2_FUNCTION_PREFIX) +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi3Functions->fmi3##f = fmi3##f; \ + } while (0) +#elif defined(_WIN32) +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi3Functions->fmi3##f = (fmi3##f##TYPE *) GetProcAddress(instance->libraryHandle, "fmi3" #f); \ + if (!instance->fmi3Functions->fmi3##f) { \ + instance->logMessage(instance, FMIFatal, "fatal", "Symbol fmi3" #f " is missing in shared library."); \ + return fmi3Fatal; \ + } \ + } while (0) +#else +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi3Functions->fmi3##f = (fmi3##f##TYPE *) dlsym(instance->libraryHandle, "fmi3" #f); \ + if (!instance->fmi3Functions->fmi3##f) { \ + instance->logMessage(instance, FMIFatal, "fatal", "Symbol fmi3" #f " is missing in shared library."); \ + return FMIFatal; \ + } \ + } while (0) +#endif + +#define CALL(f) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3##f(instance->component); \ + if (instance->logFunctionCall) { \ + instance->logFunctionCall(instance, status, "fmi3" #f "()"); \ + } \ + instance->status = status > instance->status ? status : instance->status; \ + return status; \ + } while (0) + +#define CALL_ARGS(f, m, ...) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3##f(instance->component, __VA_ARGS__); \ + if (instance->logFunctionCall) { \ + instance->logFunctionCall(instance, status, "fmi3" #f "(" m ")", __VA_ARGS__); \ + } \ + instance->status = status > instance->status ? status : instance->status; \ + return status; \ + } while (0) + +#define CALL_ARRAY(s, t) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3##s##t(instance->component, valueReferences, nValueReferences, values, nValues); \ + if (instance->logFunctionCall) { \ + FMIValueReferencesToString(instance, valueReferences, nValueReferences); \ + FMIValuesToString(instance, nValues, NULL, values, FMI##t##Type); \ + instance->logFunctionCall(instance, status, "fmi3" #s #t "(valueReferences=%s, nValueReferences=%zu, values=%s, nValues=%zu)", instance->buf1, nValueReferences, instance->buf2, nValues); \ + } \ + instance->status = status > instance->status ? status : instance->status; \ + return status; \ + } while (0) + +/*************************************************** +Types for Common Functions +****************************************************/ + +/* Inquire version numbers and setting logging status */ +const char *FMI3GetVersion(FMIInstance *instance) +{ + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, FMIOK, "fmi3GetVersion()"); + } + return instance->fmi3Functions->fmi3GetVersion(); +} + +FMIStatus FMI3SetDebugLogging(FMIInstance *instance, + fmi3Boolean loggingOn, + size_t nCategories, + const fmi3String categories[]) +{ + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3SetDebugLogging(instance->component, loggingOn, nCategories, categories); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nCategories, NULL, categories, FMIStringType); + instance->logFunctionCall(instance, status, "fmi3SetDebugLogging(loggingOn=%d, nCategories=%zu, categories=%s)", + loggingOn, nCategories, instance->buf2); + } + return status; +} + +static FMIStatus loadSymbols3(FMIInstance *instance) +{ + +#if !defined(FMI_VERSION) || FMI_VERSION == 3 + + instance->fmi3Functions = calloc(1, sizeof(FMI3Functions)); + + if (!instance->fmi3Functions) { + return FMIError; + } + + instance->fmiVersion = FMIVersion3; + + /*************************************************** + Common Functions + ****************************************************/ + + /* Inquire version numbers and set debug logging */ + LOAD_SYMBOL(GetVersion); + LOAD_SYMBOL(SetDebugLogging); + + /* Creation and destruction of FMU instances */ + LOAD_SYMBOL(InstantiateModelExchange); + LOAD_SYMBOL(InstantiateCoSimulation); + LOAD_SYMBOL(InstantiateScheduledExecution); + LOAD_SYMBOL(FreeInstance); + + /* Enter and exit initialization mode, terminate and reset */ + LOAD_SYMBOL(EnterInitializationMode); + LOAD_SYMBOL(ExitInitializationMode); + LOAD_SYMBOL(EnterEventMode); + LOAD_SYMBOL(Terminate); + LOAD_SYMBOL(Reset); + + /* Getting and setting variable values */ + LOAD_SYMBOL(GetFloat32); + LOAD_SYMBOL(GetFloat64); + LOAD_SYMBOL(GetInt8); + LOAD_SYMBOL(GetUInt8); + LOAD_SYMBOL(GetInt16); + LOAD_SYMBOL(GetUInt16); + LOAD_SYMBOL(GetInt32); + LOAD_SYMBOL(GetUInt32); + LOAD_SYMBOL(GetInt64); + LOAD_SYMBOL(GetUInt64); + LOAD_SYMBOL(GetBoolean); + LOAD_SYMBOL(GetString); + LOAD_SYMBOL(GetBinary); + LOAD_SYMBOL(GetClock); + LOAD_SYMBOL(SetFloat32); + LOAD_SYMBOL(SetFloat64); + LOAD_SYMBOL(SetInt8); + LOAD_SYMBOL(SetUInt8); + LOAD_SYMBOL(SetInt16); + LOAD_SYMBOL(SetUInt16); + LOAD_SYMBOL(SetInt32); + LOAD_SYMBOL(SetUInt32); + LOAD_SYMBOL(SetInt64); + LOAD_SYMBOL(SetUInt64); + LOAD_SYMBOL(SetBoolean); + LOAD_SYMBOL(SetString); + LOAD_SYMBOL(SetBinary); + LOAD_SYMBOL(SetClock); + + /* Getting Variable Dependency Information */ + LOAD_SYMBOL(GetNumberOfVariableDependencies); + LOAD_SYMBOL(GetVariableDependencies); + + /* Getting and setting the internal FMU state */ + LOAD_SYMBOL(GetFMUState); + LOAD_SYMBOL(SetFMUState); + LOAD_SYMBOL(FreeFMUState); + LOAD_SYMBOL(SerializedFMUStateSize); + LOAD_SYMBOL(SerializeFMUState); + LOAD_SYMBOL(DeserializeFMUState); + + /* Getting partial derivatives */ + LOAD_SYMBOL(GetDirectionalDerivative); + LOAD_SYMBOL(GetAdjointDerivative); + + /* Entering and exiting the Configuration or Reconfiguration Mode */ + LOAD_SYMBOL(EnterConfigurationMode); + LOAD_SYMBOL(ExitConfigurationMode); + + /* Clock related functions */ + LOAD_SYMBOL(GetIntervalDecimal); + LOAD_SYMBOL(GetIntervalFraction); + LOAD_SYMBOL(GetShiftDecimal); + LOAD_SYMBOL(GetShiftFraction); + LOAD_SYMBOL(SetIntervalDecimal); + LOAD_SYMBOL(SetIntervalFraction); + LOAD_SYMBOL(EvaluateDiscreteStates); + LOAD_SYMBOL(UpdateDiscreteStates); + + /*************************************************** + Functions for Model Exchange + ****************************************************/ + + LOAD_SYMBOL(EnterContinuousTimeMode); + LOAD_SYMBOL(CompletedIntegratorStep); + + /* Providing independent variables and re-initialization of caching */ + LOAD_SYMBOL(SetTime); + LOAD_SYMBOL(SetContinuousStates); + + /* Evaluation of the model equations */ + LOAD_SYMBOL(GetContinuousStateDerivatives); + LOAD_SYMBOL(GetEventIndicators); + LOAD_SYMBOL(GetContinuousStates); + LOAD_SYMBOL(GetNominalsOfContinuousStates); + LOAD_SYMBOL(GetNumberOfEventIndicators); + LOAD_SYMBOL(GetNumberOfContinuousStates); + + /*************************************************** + Functions for Co-Simulation + ****************************************************/ + + /* Simulating the FMU */ + LOAD_SYMBOL(EnterStepMode); + LOAD_SYMBOL(GetOutputDerivatives); + LOAD_SYMBOL(DoStep); + LOAD_SYMBOL(ActivateModelPartition); + + instance->state = FMI2StartAndEndState; + + return FMIOK; + +#else + + return FMIError; + +#endif +} + +/* Creation and destruction of FMU instances and setting debug status */ +FMIStatus FMI3InstantiateModelExchange( + FMIInstance *instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn) +{ + + FMIStatus status = loadSymbols3(instance); + + fmi3LogMessageCallback logMessage = instance->logMessage ? cb_logMessage3 : NULL; + + instance->component = instance->fmi3Functions->fmi3InstantiateModelExchange(instance->name, instantiationToken, resourcePath, visible, loggingOn, instance, logMessage); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, instance->component ? FMIOK : FMIError, + "fmi3InstantiateModelExchange(" + "instanceName=\"%s\", " + "instantiationToken=\"%s\", " + "resourcePath=\"%s\", " + "visible=%d, " + "loggingOn=%d, " + "instanceEnvironment=0x%p, " + "logMessage=0x%p)", + instance->name, + instantiationToken, + resourcePath, + visible, + loggingOn, + instance, + logMessage); + } + + if (!instance->component) { + return FMIError; + } + + instance->interfaceType = FMIModelExchange; + instance->state = FMI2InstantiatedState; + + return status; +} + +FMIStatus FMI3InstantiateCoSimulation( + FMIInstance *instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3Boolean eventModeUsed, + fmi3Boolean earlyReturnAllowed, + const fmi3ValueReference requiredIntermediateVariables[], + size_t nRequiredIntermediateVariables, + fmi3IntermediateUpdateCallback intermediateUpdate) +{ + + if (loadSymbols3(instance) != FMIOK) { + return FMIFatal; + } + + fmi3LogMessageCallback logMessage = instance->logMessage ? cb_logMessage3 : NULL; + + instance->component = instance->fmi3Functions->fmi3InstantiateCoSimulation( + instance->name, + instantiationToken, + resourcePath, + visible, + loggingOn, + eventModeUsed, + earlyReturnAllowed, + requiredIntermediateVariables, + nRequiredIntermediateVariables, + instance, + logMessage, + intermediateUpdate); + + instance->fmi3Functions->eventModeUsed = eventModeUsed; + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, instance->component ? FMIOK : FMIError, + "fmi3InstantiateCoSimulation(" + "instanceName=\"%s\", " + "instantiationToken=\"%s\", " + "resourcePath=\"%s\", " + "visible=%d, " + "loggingOn=%d, " + "eventModeUsed=%d, " + "earlyReturnAllowed=%d, " + "requiredIntermediateVariables=0x%p, " + "nRequiredIntermediateVariables=%zu, " + "instanceEnvironment=0x%p, " + "logMessage=0x%p, " + "intermediateUpdate=0x%p)", + instance->name, + instantiationToken, + resourcePath, + visible, + loggingOn, + eventModeUsed, + earlyReturnAllowed, + requiredIntermediateVariables, + nRequiredIntermediateVariables, + instance, + logMessage, + intermediateUpdate); + } + + if (!instance->component) { + return FMIError; + } + + instance->interfaceType = FMICoSimulation; + instance->state = FMI2InstantiatedState; + + return FMIOK; +} + +FMIStatus FMI3InstantiateScheduledExecution( + FMIInstance *instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3ClockUpdateCallback clockUpdate, + fmi3LockPreemptionCallback lockPreemption, + fmi3UnlockPreemptionCallback unlockPreemption) +{ + + if (loadSymbols3(instance) != FMIOK) { + return FMIError; + } + + fmi3LogMessageCallback _logMessage = instance->logMessage ? cb_logMessage3 : NULL; + + instance->component = instance->fmi3Functions->fmi3InstantiateScheduledExecution( + instance->name, + instantiationToken, + resourcePath, + visible, + loggingOn, + instance, + _logMessage, + clockUpdate, + lockPreemption, + unlockPreemption); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, instance->component ? FMIOK : FMIError, + "fmi3InstantiateScheduledExecution(" + "instanceName=\"%s\", " + "instantiationToken=\"%s\", " + "resourcePath=\"%s\", " + "visible=%d, " + "loggingOn=%d, " + "instanceEnvironment=0x%p, " + "logMessage=0x%p, " + "clockUpdate=0x%p, " + "lockPreemption=0x%p, " + "unlockPreemption=0x%p)", + instance->name, + instantiationToken, + resourcePath, + visible, + loggingOn, + instance, + _logMessage, + clockUpdate, + lockPreemption, + unlockPreemption); + } + + if (!instance->component) { + return FMIError; + } + + instance->interfaceType = FMIScheduledExecution; + instance->state = FMI2InstantiatedState; + + return FMIOK; +} + +FMIStatus FMI3FreeInstance(FMIInstance *instance) +{ + + if (!instance) { + return FMIError; + } + + instance->fmi3Functions->fmi3FreeInstance(instance->component); + + instance->component = NULL; + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, FMIOK, "fmi3FreeInstance()"); + } + + return FMIOK; +} + +/* Enter and exit initialization mode, enter event mode, terminate and reset */ +FMIStatus FMI3EnterInitializationMode(FMIInstance *instance, + fmi3Boolean toleranceDefined, + fmi3Float64 tolerance, + fmi3Float64 startTime, + fmi3Boolean stopTimeDefined, + fmi3Float64 stopTime) +{ + + instance->state = FMI2InitializationModeState; + + CALL_ARGS(EnterInitializationMode, + "fmi3EnterInitializationMode(toleranceDefined=%d, tolerance=%.16g, startTime=%.16g, stopTimeDefined=%d, stopTime=%.16g)", + toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); +} + +FMIStatus FMI3ExitInitializationMode(FMIInstance *instance) +{ + + if (instance->interfaceType == FMIModelExchange || (instance->fmiVersion == FMIVersion3 && instance->interfaceType == FMICoSimulation && instance->fmi3Functions->eventModeUsed)) { + instance->state = FMI2EventModeState; + } else { + instance->state = FMI2StepCompleteState; + } + + CALL(ExitInitializationMode); +} + +FMIStatus FMI3EnterEventMode(FMIInstance *instance) +{ + instance->state = FMI2EventModeState; + CALL(EnterEventMode); +} + +FMIStatus FMI3Terminate(FMIInstance *instance) +{ + instance->state = FMI2TerminatedState; + CALL(Terminate); +} + +FMIStatus FMI3Reset(FMIInstance *instance) +{ + instance->state = FMI2InstantiatedState; + CALL(Reset); +} + +/* Getting and setting variable values */ +FMIStatus FMI3GetFloat32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float32 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Float32); +} + +FMIStatus FMI3GetFloat64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Float64); +} + +FMIStatus FMI3GetInt8(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int8 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Int8); +} + +FMIStatus FMI3GetUInt8(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt8 values[], + size_t nValues) +{ + CALL_ARRAY(Get, UInt8); +} + +FMIStatus FMI3GetInt16(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int16 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Int16); +} + +FMIStatus FMI3GetUInt16(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt16 values[], + size_t nValues) +{ + CALL_ARRAY(Get, UInt16); +} + +FMIStatus FMI3GetInt32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int32 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Int32); +} + +FMIStatus FMI3GetUInt32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt32 values[], + size_t nValues) +{ + CALL_ARRAY(Get, UInt32); +} + +FMIStatus FMI3GetInt64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int64 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Int64); +} + +FMIStatus FMI3GetUInt64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 values[], + size_t nValues) +{ + CALL_ARRAY(Get, UInt64); +} + +FMIStatus FMI3GetBoolean(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Boolean values[], + size_t nValues) +{ + CALL_ARRAY(Get, Boolean); +} + +FMIStatus FMI3GetString(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3String values[], + size_t nValues) +{ + CALL_ARRAY(Get, String); +} + +FMIStatus FMI3GetBinary(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + size_t sizes[], + fmi3Binary values[], + size_t nValues) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3GetBinary(instance->component, valueReferences, nValueReferences, sizes, values, nValues); + + if (instance->logFunctionCall) { + FMIValueReferencesToString(instance, valueReferences, nValueReferences); + FMIValuesToString(instance, nValues, sizes, values, FMIBinaryType); + instance->logFunctionCall(instance, status, "fmi3GetBinary(valueReferences=%s, nValueReferences=%zu, sizes=%p, values=%s, nValues=%zu)", instance->buf1, nValueReferences, sizes, instance->buf2, nValues); + } + + return status; +} + +FMIStatus FMI3GetClock(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Clock values[]) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3GetClock(instance->component, valueReferences, nValueReferences, values); + + if (instance->logFunctionCall) { + FMIValueReferencesToString(instance, valueReferences, nValueReferences); + FMIValuesToString(instance, nValueReferences, NULL, values, FMIClockType); + instance->logFunctionCall(instance, status, "fmi3GetClock(valueReferences=%s, nValueReferences=%zu, values=%s)", instance->buf1, nValueReferences, instance->buf2); + } + + return status; +} + +FMIStatus FMI3SetFloat32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float32 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Float32); +} + +FMIStatus FMI3SetFloat64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Float64); +} + +FMIStatus FMI3SetInt8(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int8 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Int8); +} + +FMIStatus FMI3SetUInt8(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt8 values[], + size_t nValues) +{ + CALL_ARRAY(Set, UInt8); +} + +FMIStatus FMI3SetInt16(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int16 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Int16); +} + +FMIStatus FMI3SetUInt16(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt16 values[], + size_t nValues) +{ + CALL_ARRAY(Set, UInt16); +} + +FMIStatus FMI3SetInt32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Int32); +} + +FMIStatus FMI3SetUInt32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt32 values[], + size_t nValues) +{ + CALL_ARRAY(Set, UInt32); +} + +FMIStatus FMI3SetInt64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int64 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Int64); +} + +FMIStatus FMI3SetUInt64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 values[], + size_t nValues) +{ + CALL_ARRAY(Set, UInt64); +} + +FMIStatus FMI3SetBoolean(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Boolean values[], + size_t nValues) +{ + CALL_ARRAY(Set, Boolean); +} + +FMIStatus FMI3SetString(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3String values[], + size_t nValues) +{ + CALL_ARRAY(Set, String); +} + +FMIStatus FMI3SetBinary(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const size_t sizes[], + const fmi3Binary values[], + size_t nValues) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3SetBinary(instance->component, valueReferences, nValueReferences, sizes, values, nValues); + + if (instance->logFunctionCall) { + FMIValueReferencesToString(instance, valueReferences, nValueReferences); + FMIValuesToString(instance, nValues, sizes, values, FMIBinaryType); + instance->logFunctionCall(instance, status, "fmi3SetBinary(valueReferences=%s, nValueReferences=%zu, sizes=0x%p, values=%s, nValues=%zu", instance->buf1, nValueReferences, sizes, instance->buf2, nValues); + } + + return status; +} + +FMIStatus FMI3SetClock(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Clock values[]) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3SetClock(instance->component, valueReferences, nValueReferences, values); + + if (instance->logFunctionCall) { + FMIValueReferencesToString(instance, valueReferences, nValueReferences); + FMIValuesToString(instance, nValueReferences, NULL, values, FMIClockType); + instance->logFunctionCall(instance, status, "fmi3SetClock(valueReferences=%s, nValueReferences=%zu, values=%s)", instance->buf1, nValueReferences, instance->buf2); + } + + return status; +} + +/* Getting Variable Dependency Information */ +FMIStatus FMI3GetNumberOfVariableDependencies(FMIInstance *instance, + fmi3ValueReference valueReference, + size_t *nDependencies) +{ + CALL_ARGS(GetNumberOfVariableDependencies, "valueReference=%u, nDependencies=0x%p", valueReference, nDependencies); +} + +FMIStatus FMI3GetVariableDependencies(FMIInstance *instance, + fmi3ValueReference dependent, + size_t elementIndicesOfDependent[], + fmi3ValueReference independents[], + size_t elementIndicesOfIndependents[], + fmi3DependencyKind dependencyKinds[], + size_t nDependencies) +{ + CALL_ARGS(GetVariableDependencies, "dependent=%u, elementIndicesOfDependent=0x%p, independents=0x%p, elementIndicesOfIndependents=0x%p, dependencyKinds=0x%p, nDependencies=%zu", + dependent, elementIndicesOfDependent, independents, elementIndicesOfIndependents, dependencyKinds, nDependencies); +} + +/* Getting and setting the internal FMU state */ +FMIStatus FMI3GetFMUState(FMIInstance *instance, fmi3FMUState *FMUState) +{ + CALL_ARGS(GetFMUState, "FMUState=0x%p", FMUState); +} + +FMIStatus FMI3SetFMUState(FMIInstance *instance, fmi3FMUState FMUState) +{ + CALL_ARGS(SetFMUState, "FMUState=0x%p", FMUState); +} + +FMIStatus FMI3FreeFMUState(FMIInstance *instance, fmi3FMUState *FMUState) +{ + CALL_ARGS(FreeFMUState, "FMUState=0x%p", FMUState); +} + +FMIStatus FMI3SerializedFMUStateSize(FMIInstance *instance, + fmi3FMUState FMUState, + size_t *size) +{ + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3SerializedFMUStateSize(instance->component, FMUState, size); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi3SerializedFMUStateSize(FMUState=0x%p, size=%zu)", FMUState, *size); + } + return status; +} + +FMIStatus FMI3SerializeFMUState(FMIInstance *instance, + fmi3FMUState FMUState, + fmi3Byte serializedState[], + size_t size) +{ + CALL_ARGS(SerializeFMUState, "FMUstate=0x%p, serializedState=0x%p, size=%zu", FMUState, serializedState, size); +} + +FMIStatus FMI3DeserializeFMUState(FMIInstance *instance, + const fmi3Byte serializedState[], + size_t size, + fmi3FMUState *FMUState) +{ + CALL_ARGS(DeserializeFMUState, "serializedState=0x%p, size=%zu, FMUState=0x%p", serializedState, size, FMUState); +} + +/* Getting partial derivatives */ +FMIStatus FMI3GetDirectionalDerivative(FMIInstance *instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity) +{ + CALL_ARGS(GetDirectionalDerivative, + "unknowns=0x%p, nUnknowns=%zu, knowns=0x%p, nKnowns=%zu, seed=0x%p, nSeed=%zu, sensitivity=0x%p, nSensitivity=%zu", + unknowns, nUnknowns, knowns, nKnowns, seed, nSeed, sensitivity, nSensitivity); +} + +FMIStatus FMI3GetAdjointDerivative(FMIInstance *instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity) +{ + CALL_ARGS(GetAdjointDerivative, + "unknowns=0x%p, nUnknowns=%zu, knowns=0x%p, nKnowns=%zu, seed=0x%p, nSeed=%zu, sensitivity=0x%p, nSensitivity=%zu", + unknowns, nUnknowns, knowns, nKnowns, seed, nSeed, sensitivity, nSensitivity); +} + +/* Entering and exiting the Configuration or Reconfiguration Mode */ +FMIStatus FMI3EnterConfigurationMode(FMIInstance *instance) +{ + CALL(EnterConfigurationMode); +} + +FMIStatus FMI3ExitConfigurationMode(FMIInstance *instance) +{ + CALL(ExitConfigurationMode); +} + +/* Clock related functions */ + +FMI_STATIC FMIStatus FMI3GetIntervalDecimal(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 intervals[], + fmi3IntervalQualifier qualifiers[]) +{ + CALL_ARGS(GetIntervalDecimal, + "valueReferences=0x%p, nValueReferences=%zu, intervals=0x%p, qualifiers=0x%p", + valueReferences, nValueReferences, intervals, qualifiers); +} + +FMIStatus FMI3GetIntervalFraction(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 intervalCounters[], + fmi3UInt64 resolutions[], + fmi3IntervalQualifier qualifiers[]) +{ + CALL_ARGS(GetIntervalFraction, + "valueReferences=0x%p, nValueReferences=%zu, intervalCounters=0x%p, resolutions=0x%p, qualifiers=%d", + valueReferences, nValueReferences, intervalCounters, resolutions, qualifiers); +} + +FMIStatus FMI3GetShiftDecimal(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 shifts[]) +{ + CALL_ARGS(GetShiftDecimal, + "valueReferences=0x%p, nValueReferences=%zu, shifts=0x%p", + valueReferences, nValueReferences, shifts); +} + +FMIStatus FMI3GetShiftFraction(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 shiftCounters[], + fmi3UInt64 resolutions[]) +{ + CALL_ARGS(GetShiftFraction, + "valueReferences=0x%p, nValueReferences=%zu, shiftCounters=0x%p, resolutions=0x%p", + valueReferences, nValueReferences, shiftCounters, resolutions); +} + +FMIStatus FMI3SetIntervalDecimal(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 intervals[]) +{ + CALL_ARGS(SetIntervalDecimal, + "valueReferences=0x%p, nValueReferences=%zu, intervals=0x%p", + valueReferences, nValueReferences, intervals); +} + +FMIStatus FMI3SetIntervalFraction(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 intervalCounters[], + const fmi3UInt64 resolutions[]) +{ + CALL_ARGS(SetIntervalFraction, + "valueReferences=0x%p, nValueReferences=%zu, intervalCounters=0x%p, resolutions=0x%p", + valueReferences, nValueReferences, intervalCounters, resolutions); +} + +FMIStatus FMI3SetShiftDecimal(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 shifts[]) +{ + CALL_ARGS(SetShiftDecimal, + "valueReferences=0x%p, nValueReferences=%zu, shifts=0x%p", + valueReferences, nValueReferences, shifts); +} + +FMIStatus FMI3SetShiftFraction(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 shiftCounters[], + const fmi3UInt64 resolutions[]) +{ + CALL_ARGS(SetShiftFraction, + "valueReferences=0x%p, nValueReferences=%zu, shiftCounters=0x%p, resolutions=0x%p", + valueReferences, nValueReferences, shiftCounters, resolutions); +} + +FMIStatus FMI3EvaluateDiscreteStates(FMIInstance *instance) +{ + CALL(EvaluateDiscreteStates); +} + +FMIStatus FMI3UpdateDiscreteStates(FMIInstance *instance, + fmi3Boolean *discreteStatesNeedUpdate, + fmi3Boolean *terminateSimulation, + fmi3Boolean *nominalsOfContinuousStatesChanged, + fmi3Boolean *valuesOfContinuousStatesChanged, + fmi3Boolean *nextEventTimeDefined, + fmi3Float64 *nextEventTime) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3UpdateDiscreteStates(instance->component, discreteStatesNeedUpdate, terminateSimulation, nominalsOfContinuousStatesChanged, valuesOfContinuousStatesChanged, nextEventTimeDefined, nextEventTime); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, + "fmi3UpdateDiscreteStates(discreteStatesNeedUpdate=%d, terminateSimulation=%d, nominalsOfContinuousStatesChanged=%d, valuesOfContinuousStatesChanged=%d, nextEventTimeDefined=%d, nextEventTime=%.16g)", + *discreteStatesNeedUpdate, *terminateSimulation, *nominalsOfContinuousStatesChanged, *valuesOfContinuousStatesChanged, *nextEventTimeDefined, *nextEventTime); + } + + return status; +} + +/*************************************************** +Types for Functions for Model Exchange +****************************************************/ + +FMIStatus FMI3EnterContinuousTimeMode(FMIInstance *instance) +{ + instance->state = FMI2ContinuousTimeModeState; + CALL(EnterContinuousTimeMode); +} + +FMIStatus FMI3CompletedIntegratorStep(FMIInstance *instance, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *enterEventMode, + fmi3Boolean *terminateSimulation) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3CompletedIntegratorStep(instance->component, noSetFMUStatePriorToCurrentPoint, enterEventMode, terminateSimulation); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, + "fmi3CompletedIntegratorStep(noSetFMUStatePriorToCurrentPoint=%d, enterEventMode=%d, terminateSimulation=%d)", + noSetFMUStatePriorToCurrentPoint, *enterEventMode, *terminateSimulation); + } + + return status; +} + +/* Providing independent variables and re-initialization of caching */ +FMIStatus FMI3SetTime(FMIInstance *instance, fmi3Float64 time) +{ + instance->time = time; + CALL_ARGS(SetTime, "time=%.16g", time); +} + +FMIStatus FMI3SetContinuousStates(FMIInstance *instance, + const fmi3Float64 continuousStates[], + size_t nContinuousStates) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3SetContinuousStates(instance->component, continuousStates, nContinuousStates); + + if (instance->logFunctionCall) { + FMIValuesToString(instance, nContinuousStates, NULL, continuousStates, FMIFloat64Type); + instance->logFunctionCall(instance, status, + "fmi3SetContinuousStates(continuousStates=%s, nContinuousStates=%zu)", + instance->buf2, nContinuousStates); + } + + return status; +} + +/* Evaluation of the model equations */ +FMIStatus FMI3GetContinuousStateDerivatives(FMIInstance *instance, + fmi3Float64 derivatives[], + size_t nContinuousStates) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3GetContinuousStateDerivatives(instance->component, derivatives, nContinuousStates); + + if (instance->logFunctionCall) { + FMIValuesToString(instance, nContinuousStates, NULL, derivatives, FMIFloat64Type); + instance->logFunctionCall(instance, status, + "fmi3GetDerivatives(derivatives=%s, nContinuousStates=%zu)", + instance->buf2, nContinuousStates); + } + + return status; +} + +FMIStatus FMI3GetEventIndicators(FMIInstance *instance, + fmi3Float64 eventIndicators[], + size_t nEventIndicators) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3GetEventIndicators(instance->component, eventIndicators, nEventIndicators); + + if (instance->logFunctionCall) { + FMIValuesToString(instance, nEventIndicators, NULL, eventIndicators, FMIFloat64Type); + instance->logFunctionCall(instance, status, + "fmi3GetEventIndicators(eventIndicators=%s, nEventIndicators=%zu)", + instance->buf2, nEventIndicators); + } + + return status; +} + +FMIStatus FMI3GetContinuousStates(FMIInstance *instance, + fmi3Float64 continuousStates[], + size_t nContinuousStates) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3GetContinuousStates(instance->component, continuousStates, nContinuousStates); + + if (instance->logFunctionCall) { + FMIValuesToString(instance, nContinuousStates, NULL, continuousStates, FMIFloat64Type); + instance->logFunctionCall(instance, status, + "fmi3GetContinuousStates(continuousStates=%s, nContinuousStates=%zu)", + instance->buf2, nContinuousStates); + } + + return status; +} + +FMIStatus FMI3GetNominalsOfContinuousStates(FMIInstance *instance, + fmi3Float64 nominals[], + size_t nContinuousStates) +{ + CALL_ARGS(GetNominalsOfContinuousStates, "nominals=0x%p, nContinuousStates=%zu", nominals, nContinuousStates); +} + +FMIStatus FMI3GetNumberOfEventIndicators(FMIInstance *instance, + size_t *nEventIndicators) +{ + CALL_ARGS(GetNumberOfEventIndicators, "nEventIndicators=0x%p", nEventIndicators); +} + +FMIStatus FMI3GetNumberOfContinuousStates(FMIInstance *instance, + size_t *nContinuousStates) +{ + CALL_ARGS(GetNumberOfContinuousStates, "nContinuousStates=0x%p", nContinuousStates); +} + +/*************************************************** +Types for Functions for Co-Simulation +****************************************************/ + +/* Simulating the FMU */ + +FMIStatus FMI3EnterStepMode(FMIInstance *instance) +{ + CALL(EnterStepMode); +} + +FMIStatus FMI3GetOutputDerivatives(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 orders[], + fmi3Float64 values[], + size_t nValues) +{ + CALL_ARGS(GetOutputDerivatives, + "valueReferences=0x%p, nValueReferences=%zu, orders=0x%p, values=0x%p, nValues=%zu", + valueReferences, nValueReferences, orders, values, nValues); +} + +FMIStatus FMI3DoStep(FMIInstance *instance, + fmi3Float64 currentCommunicationPoint, + fmi3Float64 communicationStepSize, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *eventEncountered, + fmi3Boolean *terminate, + fmi3Boolean *earlyReturn, + fmi3Float64 *lastSuccessfulTime) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3DoStep(instance->component, currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint, eventEncountered, terminate, earlyReturn, lastSuccessfulTime); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, + "fmi3DoStep(currentCommunicationPoint=%.16g, communicationStepSize=%.16g, noSetFMUStatePriorToCurrentPoint=%d, eventEncountered=%d, terminate=%d, earlyReturn=%d, lastSuccessfulTime=%.16g)", + currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint, *eventEncountered, *terminate, *earlyReturn, *lastSuccessfulTime); + } + + instance->time = *lastSuccessfulTime; + + return status; +} + +FMIStatus FMI3ActivateModelPartition(FMIInstance *instance, + fmi3ValueReference clockReference, + fmi3Float64 activationTime) +{ + CALL_ARGS(ActivateModelPartition, + "clockReference=%u, activationTime=%.16g", + clockReference, activationTime); +} + +#undef LOAD_SYMBOL +#undef CALL +#undef CALL_ARGS +#undef CALL_ARRAY diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/cosimulation.c b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/cosimulation.c new file mode 100644 index 000000000..86d60baf0 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/cosimulation.c @@ -0,0 +1,656 @@ +#include "cosimulation.h" +#include // for DBL_EPSILON +#include // for fabs() +#include +#include +#include // for calloc(), free() +#include +#include "config.h" + +#if FMI_VERSION == 3 +#include "fmi3Functions.h" +#endif + +#ifdef _MSC_VER +#define strdup _strdup +#endif + +ModelInstance *createModelInstance( + loggerType cbLogger, + intermediateUpdateType intermediateUpdate, + void *componentEnvironment, + const char *instanceName, + const char *instantiationToken, + const char *resourceLocation, + bool loggingOn, + InterfaceType interfaceType) +{ + + ModelInstance *comp = NULL; + + if (!instanceName || strlen(instanceName) == 0) { + if (cbLogger) { +#if FMI_VERSION < 3 + cbLogger(componentEnvironment, "?", Error, "error", "Missing instance name."); +#else + cbLogger(componentEnvironment, Error, "error", "Missing instance name."); +#endif + } + return NULL; + } + + if (!instantiationToken || strlen(instantiationToken) == 0) { + if (cbLogger) { +#if FMI_VERSION < 3 + cbLogger(componentEnvironment, instanceName, Error, "error", "Missing GUID."); +#else + cbLogger(componentEnvironment, Error, "error", "Missing instantiationToken."); +#endif + } + return NULL; + } + + if (strcmp(instantiationToken, INSTANTIATION_TOKEN)) { + if (cbLogger) { +#if FMI_VERSION < 3 + cbLogger(componentEnvironment, instanceName, Error, "error", "Wrong GUID."); +#else + cbLogger(componentEnvironment, Error, "error", "Wrong instantiationToken."); +#endif + } + return NULL; + } + + comp = (ModelInstance *) calloc(1, sizeof(ModelInstance)); + + if (comp) { + comp->componentEnvironment = componentEnvironment; + comp->logger = cbLogger; + comp->intermediateUpdate = intermediateUpdate; + comp->lockPreemtion = NULL; + comp->unlockPreemtion = NULL; + comp->instanceName = strdup(instanceName); + comp->resourceLocation = resourceLocation ? strdup(resourceLocation) : NULL; + comp->status = OK; + comp->logEvents = loggingOn; + comp->logErrors = true; // always log errors + comp->nSteps = 0; + comp->solverStepSize = 1e-3; + comp->earlyReturnAllowed = false; + comp->eventModeUsed = false; + } + + if (!comp || !comp->instanceName) { + logError(comp, "Out of memory."); + return NULL; + } + + comp->time = 0.0; // overwrite in fmi*SetupExperiment, fmi*SetTime + comp->type = interfaceType; + + comp->state = Instantiated; + + comp->newDiscreteStatesNeeded = false; + comp->terminateSimulation = false; + comp->nominalsOfContinuousStatesChanged = false; + comp->valuesOfContinuousStatesChanged = false; + comp->nextEventTimeDefined = false; + comp->nextEventTime = 0; + + setStartValues(comp); + + comp->isDirtyValues = true; + + return comp; +} + +void freeModelInstance(ModelInstance *comp) +{ + free((void *) comp->instanceName); + free(comp); +} + +void reset(ModelInstance *comp) +{ + comp->state = Instantiated; + comp->startTime = 0.0; + comp->time = 0.0; + comp->nSteps = 0; + comp->solverStepSize = 1e-3; + comp->status = OK; + setStartValues(comp); + comp->isDirtyValues = true; +} + +bool invalidNumber(ModelInstance *comp, const char *f, const char *arg, size_t actual, size_t expected) +{ + + if (actual != expected) { + comp->state = modelError; + logError(comp, "%s: Invalid argument %s = %d. Expected %d.", f, arg, actual, expected); + return true; + } + + return false; +} + +bool invalidState(ModelInstance *comp, const char *f, int statesExpected) +{ + + UNUSED(f); + UNUSED(statesExpected); + + if (!comp) { + return true; + } + + // TODO: add missing states and check state + return false; + + // if (!(comp->state & statesExpected)) { + // comp->state = modelError; + // logError(comp, "%s: Illegal call sequence.", f); + // return true; + // } + // + // return false; +} + +bool nullPointer(ModelInstance *comp, const char *f, const char *arg, const void *p) +{ + + if (!p) { + comp->state = modelError; + logError(comp, "%s: Invalid argument %s = NULL.", f, arg); + return true; + } + + return false; +} + +Status setDebugLogging(ModelInstance *comp, bool loggingOn, size_t nCategories, const char *const categories[]) +{ + + if (loggingOn) { + for (size_t i = 0; i < nCategories; i++) { + if (categories[i] == NULL) { + logError(comp, "Log category[%d] must not be NULL", i); + return Error; + } else if (strcmp(categories[i], "logEvents") == 0) { + comp->logEvents = true; + } else if (strcmp(categories[i], "logStatusError") == 0) { + comp->logErrors = true; + } else { + logError(comp, "Log category[%d] must be one of logEvents or logStatusError but was %s", i, categories[i]); + return Error; + } + } + } else { + // disable logging + comp->logEvents = false; + comp->logErrors = false; + } + + return OK; +} + +static void logMessage(ModelInstance *comp, int status, const char *category, const char *message, va_list args) +{ + + if (!comp->logger) { + return; + } + + va_list args1; + size_t len = 0; + char *buf = ""; + + va_copy(args1, args); + len = vsnprintf(buf, len, message, args1); + va_end(args1); + + va_copy(args1, args); + buf = (char *) calloc(len + 1, sizeof(char)); + vsnprintf(buf, len + 1, message, args); + va_end(args1); + + // no need to distinguish between FMI versions since we're not using variadic arguments +#if FMI_VERSION < 3 + comp->logger(comp->componentEnvironment, comp->instanceName, status, category, buf); +#else + comp->logger(comp->componentEnvironment, status, category, buf); +#endif + + free(buf); +} + +void logEvent(ModelInstance *comp, const char *message, ...) +{ + + if (!comp || !comp->logEvents) + return; + + va_list args; + va_start(args, message); + logMessage(comp, OK, "logEvents", message, args); + va_end(args); +} + +void logError(ModelInstance *comp, const char *message, ...) +{ + + if (!comp || !comp->logErrors) + return; + + va_list args; + va_start(args, message); + logMessage(comp, Error, "logStatusError", message, args); + va_end(args); +} + +// default implementations +#if NZ < 1 +void getEventIndicators(ModelInstance *comp, double z[], size_t nz) +{ + UNUSED(comp); + UNUSED(z); + UNUSED(nz); + // do nothing +} +#endif + +#define GET_NOT_ALLOWED(t) \ + do { \ + UNUSED(vr); \ + UNUSED(value); \ + UNUSED(index); \ + logError(comp, "Getting " t " is not allowed."); \ + return Error; \ + } while (false) + +#ifndef GET_FLOAT32 +Status getFloat32(ModelInstance *comp, ValueReference vr, float value[], size_t *index) +{ + GET_NOT_ALLOWED("Float32"); +} +#endif + +#ifndef GET_INT8 +Status getInt8(ModelInstance *comp, ValueReference vr, int8_t value[], size_t *index) +{ + GET_NOT_ALLOWED("Int8"); +} +#endif + +#ifndef GET_UINT8 +Status getUInt8(ModelInstance *comp, ValueReference vr, uint8_t value[], size_t *index) +{ + GET_NOT_ALLOWED("UInt8"); +} +#endif + +#ifndef GET_INT16 +Status getInt16(ModelInstance *comp, ValueReference vr, int16_t value[], size_t *index) +{ + GET_NOT_ALLOWED("Int16"); +} +#endif + +#ifndef GET_UINT16 +Status getUInt16(ModelInstance *comp, ValueReference vr, uint16_t value[], size_t *index) +{ + GET_NOT_ALLOWED("UInt16"); +} +#endif + +#ifndef GET_INT32 +Status getInt32(ModelInstance *comp, ValueReference vr, int32_t value[], size_t *index) +{ + GET_NOT_ALLOWED("Int32"); +} +#endif + +#ifndef GET_UINT32 +Status getUInt32(ModelInstance *comp, ValueReference vr, uint32_t value[], size_t *index) +{ + GET_NOT_ALLOWED("UInt32"); +} +#endif + +#ifndef GET_INT64 +Status getInt64(ModelInstance *comp, ValueReference vr, int64_t value[], size_t *index) +{ + GET_NOT_ALLOWED("Int64"); +} +#endif + +#ifndef GET_UINT64 +Status getUInt64(ModelInstance *comp, ValueReference vr, uint64_t value[], size_t *index) +{ + GET_NOT_ALLOWED("UInt64"); +} +#endif + +#ifndef GET_BOOLEAN +Status getBoolean(ModelInstance *comp, ValueReference vr, bool value[], size_t *index) +{ + GET_NOT_ALLOWED("Boolean"); +} +#endif + +#ifndef GET_STRING +Status getString(ModelInstance *comp, ValueReference vr, const char *value[], size_t *index) +{ + GET_NOT_ALLOWED("String"); +} +#endif + +#ifndef GET_BINARY +Status getBinary(ModelInstance *comp, ValueReference vr, size_t size[], const char *value[], size_t *index) +{ + UNUSED(size); + GET_NOT_ALLOWED("Binary"); +} +#endif + +#define SET_NOT_ALLOWED(t) \ + do { \ + UNUSED(vr); \ + UNUSED(value); \ + UNUSED(index); \ + logError(comp, "Setting " t " is not allowed."); \ + return Error; \ + } while (false) + +#ifndef SET_FLOAT32 +Status setFloat32(ModelInstance *comp, ValueReference vr, const float value[], size_t *index) +{ + SET_NOT_ALLOWED("Float32"); +} +#endif + +#ifndef SET_FLOAT64 +Status setFloat64(ModelInstance *comp, ValueReference vr, const double value[], size_t *index) +{ + SET_NOT_ALLOWED("Float64"); +} +#endif + +#ifndef SET_INT8 +Status setInt8(ModelInstance *comp, ValueReference vr, const int8_t value[], size_t *index) +{ + SET_NOT_ALLOWED("Int8"); +} +#endif + +#ifndef SET_UINT8 +Status setUInt8(ModelInstance *comp, ValueReference vr, const uint8_t value[], size_t *index) +{ + SET_NOT_ALLOWED("UInt8"); +} +#endif + +#ifndef SET_INT16 +Status setInt16(ModelInstance *comp, ValueReference vr, const int16_t value[], size_t *index) +{ + SET_NOT_ALLOWED("Int16"); +} +#endif + +#ifndef SET_UINT16 +Status setUInt16(ModelInstance *comp, ValueReference vr, const uint16_t value[], size_t *index) +{ + SET_NOT_ALLOWED("UInt16"); +} +#endif + +#ifndef SET_INT32 +Status setInt32(ModelInstance *comp, ValueReference vr, const int32_t value[], size_t *index) +{ + SET_NOT_ALLOWED("Int32"); +} +#endif + +#ifndef SET_UINT32 +Status setUInt32(ModelInstance *comp, ValueReference vr, const uint32_t value[], size_t *index) +{ + SET_NOT_ALLOWED("UInt32"); +} +#endif + +#ifndef SET_INT64 +Status setInt64(ModelInstance *comp, ValueReference vr, const int64_t value[], size_t *index) +{ + SET_NOT_ALLOWED("Int64"); +} +#endif + +#ifndef SET_UINT64 +Status setUInt64(ModelInstance *comp, ValueReference vr, const uint64_t value[], size_t *index) +{ + SET_NOT_ALLOWED("UInt64"); +} +#endif + +#ifndef SET_BOOLEAN +Status setBoolean(ModelInstance *comp, ValueReference vr, const bool value[], size_t *index) +{ + SET_NOT_ALLOWED("Boolean"); +} +#endif + +#ifndef SET_STRING +Status setString(ModelInstance *comp, ValueReference vr, const char *const value[], size_t *index) +{ + SET_NOT_ALLOWED("String"); +} +#endif + +#ifndef SET_BINARY +Status setBinary(ModelInstance *comp, ValueReference vr, const size_t size[], const char *const value[], size_t *index) +{ + UNUSED(size); + SET_NOT_ALLOWED("Binary"); +} +#endif + +#ifndef ACTIVATE_CLOCK +Status activateClock(ModelInstance *comp, ValueReference vr) +{ + UNUSED(comp); + UNUSED(vr); + return Error; +} +#endif + +#ifndef GET_CLOCK +Status getClock(ModelInstance *comp, ValueReference vr, bool *value) +{ + UNUSED(comp); + UNUSED(vr); + UNUSED(value); + return Error; +} +#endif + +#ifndef GET_INTERVAL +Status getInterval(ModelInstance *comp, ValueReference vr, double *interval, int *qualifier) +{ + UNUSED(comp); + UNUSED(vr); + UNUSED(interval); + UNUSED(qualifier); + return Error; +} +#endif + +#ifndef ACTIVATE_MODEL_PARTITION +Status activateModelPartition(ModelInstance *comp, ValueReference vr, double activationTime) +{ + UNUSED(comp); + UNUSED(vr); + UNUSED(activationTime); + return Error; +} +#endif + +#if NX < 1 +void getContinuousStates(ModelInstance *comp, double x[], size_t nx) +{ + UNUSED(comp); + UNUSED(x); + UNUSED(nx); +} + +void setContinuousStates(ModelInstance *comp, const double x[], size_t nx) +{ + UNUSED(comp); + UNUSED(x); + UNUSED(nx); +} + +void getDerivatives(ModelInstance *comp, double dx[], size_t nx) +{ + UNUSED(comp); + UNUSED(dx); + UNUSED(nx); +} +#endif + +#ifndef GET_PARTIAL_DERIVATIVE +Status getPartialDerivative(ModelInstance *comp, ValueReference unknown, ValueReference known, double *partialDerivative) +{ + UNUSED(comp); + UNUSED(unknown); + UNUSED(known); + UNUSED(partialDerivative); + return Error; +} +#endif + +void *getFMUState(ModelInstance *comp) +{ + + ModelInstance *fmuState = (ModelInstance *) calloc(1, sizeof(ModelInstance)); + + memcpy(fmuState, comp, sizeof(ModelInstance)); + + return fmuState; +} + +void setFMUState(ModelInstance *comp, void *FMUState) +{ + + ModelInstance *s = (ModelInstance *) FMUState; + + comp->startTime = s->startTime; + comp->time = s->time; + comp->solverStepSize = s->solverStepSize; + comp->status = s->status; + comp->state = s->state; + comp->newDiscreteStatesNeeded = s->newDiscreteStatesNeeded; + comp->terminateSimulation = s->terminateSimulation; + comp->nominalsOfContinuousStatesChanged = s->nominalsOfContinuousStatesChanged; + comp->valuesOfContinuousStatesChanged = s->valuesOfContinuousStatesChanged; + comp->nextEventTimeDefined = s->nextEventTimeDefined; + comp->nextEventTime = s->nextEventTime; + comp->clocksTicked = s->clocksTicked; + comp->isDirtyValues = s->isDirtyValues; + comp->modelData = s->modelData; +#if NZ > 0 + memcpy(comp->z, s->z, NZ * sizeof(double)); +#endif + comp->nSteps = s->nSteps; +} + +void doFixedStep(ModelInstance *comp, bool *stateEvent, bool *timeEvent) +{ + + // not implemented + UNUSED(comp); + UNUSED(stateEvent); + UNUSED(timeEvent); +} + +void doAdaptiveStep(ModelInstance *comp, bool *stateEvent, bool *timeEvent) +{ + + // create local variables + double t = comp->time; + double dt = comp->solverStepSize; + + // compute control output according to flags "compute_u_1" and "use_implicit_method" + + if (M(compute_u_1)) { + + // compute error + M(e) = M(r) - M(y_1); + + // calculate u_1 + if (M(use_implicit_method)) { + // implicit trapezoid + M(P) = M(kp) * M(e); + M(I) = M(ki) * (M(I) + (M(e) + M(e_ls)) * dt / 2); + M(D) = M(kd) * (M(e) - M(e_ls)) / dt; + + } else { + // explicit euler + M(P) = M(kp) * M(e); + M(I) = M(ki) * (M(I) + M(e) * dt); + M(D) = M(kd) * (M(e) - M(e_ls)) / dt; + } + + // limit I to avoid integrator windup + if (M(I) > M(I_max)) { + M(I) = M(I_max); + } + + // compute u_1 + M(u_1) = M(P) + M(I) + M(D); + + // set u_2 to default value + M(u_2) = 0; + } + + else { + + // compute error + M(e) = M(r) - M(y_2); + + // calculate u_2 + if (M(use_implicit_method)) { + // implicit trapezoid + M(P) = M(kp) * M(e); + M(I) = M(ki) * (M(I) + (M(e) + M(e_ls)) * dt / 2); + M(D) = M(kd) * (M(e) - M(e_ls)) / dt; + + } else { + // explicit euler + M(P) = M(kp) * M(e); + M(I) = M(ki) * (M(I) + M(e) * dt); + M(D) = M(kd) * (M(e) - M(e_ls)) / dt; + } + + // limit I to avoid integrator windup + if (M(I) > M(I_max)) { + M(I) = M(I_max); + } + + // compute u_2 + M(u_2) = M(P) + M(I) + M(D); + + // set u_1 to default value + M(u_1) = 0; + } + + // save error for next timestep + M(e_ls) = M(e); + + // advance nSteps and time + comp->nSteps++; + comp->time = t + dt; + + // state event + *stateEvent = false; + UNUSED(timeEvent); +} diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/fmi2Functions.c b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/fmi2Functions.c new file mode 100644 index 000000000..3e8a5fb5a --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/fmi2Functions.c @@ -0,0 +1,923 @@ +#if FMI_VERSION != 2 +#error FMI_VERSION must be 2 +#endif + +#include +#include +#include +#include + +#include "config.h" +#include "cosimulation.h" +#include "model.h" + +// C-code FMUs have functions names prefixed with MODEL_IDENTIFIER_. +// Define DISABLE_PREFIX to build a binary FMU. +#ifndef DISABLE_PREFIX +#define pasteA(a, b) a##b +#define pasteB(a, b) pasteA(a, b) +#define FMI2_FUNCTION_PREFIX pasteB(MODEL_IDENTIFIER, _) +#endif +#include "fmi2Functions.h" + +#define ASSERT_NOT_NULL(p) \ + do { \ + if (!p) { \ + logError(S, "Argument %s must not be NULL.", xstr(p)); \ + S->state = modelError; \ + return (fmi2Status) Error; \ + } \ + } while (0) + +#define GET_VARIABLES(T) \ + do { \ + Status status = OK; \ + if (nvr == 0) \ + return (fmi2Status) status; \ + ASSERT_NOT_NULL(vr); \ + ASSERT_NOT_NULL(value); \ + size_t index = 0; \ + if (S->isDirtyValues) { \ + Status s = calculateValues(S); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi2Status) status; \ + S->isDirtyValues = false; \ + } \ + for (size_t i = 0; i < nvr; i++) { \ + Status s = get##T(S, vr[i], value, &index); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi2Status) status; \ + } \ + return (fmi2Status) status; \ + } while (0) + +#define SET_VARIABLES(T) \ + do { \ + Status status = OK; \ + if (nvr == 0) \ + return (fmi2Status) status; \ + ASSERT_NOT_NULL(vr); \ + ASSERT_NOT_NULL(value); \ + size_t index = 0; \ + for (size_t i = 0; i < nvr; i++) { \ + Status s = set##T(S, vr[i], value, &index); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi2Status) status; \ + } \ + if (nvr > 0) \ + S->isDirtyValues = true; \ + return (fmi2Status) status; \ + } while (0) + +#define GET_BOOLEAN_VARIABLES \ + do { \ + Status status = OK; \ + for (size_t i = 0; i < nvr; i++) { \ + bool v = false; \ + size_t index = 0; \ + Status s = getBoolean(S, vr[i], &v, &index); \ + value[i] = v; \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi2Status) status; \ + } \ + return (fmi2Status) status; \ + } while (0) + +#define SET_BOOLEAN_VARIABLES \ + do { \ + Status status = OK; \ + for (size_t i = 0; i < nvr; i++) { \ + bool v = value[i]; \ + size_t index = 0; \ + Status s = setBoolean(S, vr[i], &v, &index); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi2Status) status; \ + } \ + return (fmi2Status) status; \ + } while (0) + +#ifndef max +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef DT_EVENT_DETECT +#define DT_EVENT_DETECT 1e-10 +#endif + +// --------------------------------------------------------------------------- +// Function calls allowed state masks for both Model-exchange and Co-simulation +// --------------------------------------------------------------------------- +#define MASK_fmi2GetTypesPlatform (StartAndEnd | Instantiated | InitializationMode | EventMode | ContinuousTimeMode | StepComplete | StepInProgress | StepFailed | StepCanceled | Terminated | Error) +#define MASK_fmi2GetVersion MASK_fmi2GetTypesPlatform +#define MASK_fmi2SetDebugLogging (Instantiated | InitializationMode | EventMode | ContinuousTimeMode | StepComplete | StepInProgress | StepFailed | StepCanceled | Terminated | Error) +#define MASK_fmi2Instantiate (StartAndEnd) +#define MASK_fmi2FreeInstance (Instantiated | InitializationMode | EventMode | ContinuousTimeMode | StepComplete | StepFailed | StepCanceled | Terminated | Error) +#define MASK_fmi2SetupExperiment Instantiated +#define MASK_fmi2EnterInitializationMode Instantiated +#define MASK_fmi2ExitInitializationMode InitializationMode +#define MASK_fmi2Terminate (EventMode | ContinuousTimeMode | StepComplete | StepFailed) +#define MASK_fmi2Reset MASK_fmi2FreeInstance +#define MASK_fmi2GetReal (InitializationMode | EventMode | ContinuousTimeMode | StepComplete | StepFailed | StepCanceled | Terminated | Error) +#define MASK_fmi2GetInteger MASK_fmi2GetReal +#define MASK_fmi2GetBoolean MASK_fmi2GetReal +#define MASK_fmi2GetString MASK_fmi2GetReal +#define MASK_fmi2SetReal (Instantiated | InitializationMode | EventMode | ContinuousTimeMode | StepComplete) +#define MASK_fmi2SetInteger (Instantiated | InitializationMode | EventMode | StepComplete) +#define MASK_fmi2SetBoolean MASK_fmi2SetInteger +#define MASK_fmi2SetString MASK_fmi2SetInteger +#define MASK_fmi2GetFMUstate MASK_fmi2FreeInstance +#define MASK_fmi2SetFMUstate MASK_fmi2FreeInstance +#define MASK_fmi2FreeFMUstate MASK_fmi2FreeInstance +#define MASK_fmi2SerializedFMUstateSize MASK_fmi2FreeInstance +#define MASK_fmi2SerializeFMUstate MASK_fmi2FreeInstance +#define MASK_fmi2DeSerializeFMUstate MASK_fmi2FreeInstance +#define MASK_fmi2GetDirectionalDerivative (InitializationMode | EventMode | ContinuousTimeMode | StepComplete | StepFailed | StepCanceled | Terminated | Error) + +// --------------------------------------------------------------------------- +// Function calls allowed state masks for Model-exchange +// --------------------------------------------------------------------------- +#define MASK_fmi2EnterEventMode (EventMode | ContinuousTimeMode) +#define MASK_fmi2NewDiscreteStates EventMode +#define MASK_fmi2EnterContinuousTimeMode EventMode +#define MASK_fmi2CompletedIntegratorStep ContinuousTimeMode +#define MASK_fmi2SetTime (EventMode | ContinuousTimeMode) +#define MASK_fmi2SetContinuousStates ContinuousTimeMode +#define MASK_fmi2GetEventIndicators (InitializationMode | EventMode | ContinuousTimeMode | Terminated | Error) +#define MASK_fmi2GetContinuousStates MASK_fmi2GetEventIndicators +#define MASK_fmi2GetDerivatives (EventMode | ContinuousTimeMode | Terminated | Error) +#define MASK_fmi2GetNominalsOfContinuousStates (Instantiated | EventMode | ContinuousTimeMode | Terminated | Error) + +// --------------------------------------------------------------------------- +// Function calls allowed state masks for Co-simulation +// --------------------------------------------------------------------------- +#define MASK_fmi2SetRealInputDerivatives (Instantiated | InitializationMode | StepComplete) +#define MASK_fmi2GetRealOutputDerivatives (StepComplete | StepFailed | StepCanceled | Terminated | Error) +#define MASK_fmi2DoStep StepComplete +#define MASK_fmi2CancelStep StepInProgress +#define MASK_fmi2GetStatus (StepComplete | StepInProgress | StepFailed | Terminated) +#define MASK_fmi2GetRealStatus MASK_fmi2GetStatus +#define MASK_fmi2GetIntegerStatus MASK_fmi2GetStatus +#define MASK_fmi2GetBooleanStatus MASK_fmi2GetStatus +#define MASK_fmi2GetStringStatus MASK_fmi2GetStatus + +// shorthand to access the instance +#define S ((ModelInstance *) c) + +#define ASSERT_STATE(S) \ + if (!allowedState(c, MASK_fmi2##S, #S)) \ + return fmi2Error; + +static bool allowedState(ModelInstance *instance, int statesExpected, char *name) +{ + + if (!instance) { + return false; + } + + if (!(instance->state & statesExpected)) { + logError(instance, "fmi2%s: Illegal call sequence.", name); + return false; + } + + return true; +} + +// --------------------------------------------------------------------------- +// FMI functions +// --------------------------------------------------------------------------- + +fmi2Component fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID, + fmi2String fmuResourceLocation, const fmi2CallbackFunctions *functions, + fmi2Boolean visible, fmi2Boolean loggingOn) +{ + + UNUSED(visible); + + if (!functions || !functions->logger) { + return NULL; + } + + return createModelInstance( + (loggerType) functions->logger, + NULL, + functions->componentEnvironment, + instanceName, + fmuGUID, + fmuResourceLocation, + loggingOn, + (InterfaceType) fmuType); +} + +fmi2Status fmi2SetupExperiment(fmi2Component c, fmi2Boolean toleranceDefined, fmi2Real tolerance, + fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime) +{ + + UNUSED(toleranceDefined); + UNUSED(tolerance); + UNUSED(stopTimeDefined); + UNUSED(stopTime); + + ASSERT_STATE(SetupExperiment) + + S->startTime = startTime; + S->time = startTime; + + return fmi2OK; +} + +fmi2Status fmi2EnterInitializationMode(fmi2Component c) +{ + + ASSERT_STATE(EnterInitializationMode) + + S->state = InitializationMode; + + return fmi2OK; +} + +fmi2Status fmi2ExitInitializationMode(fmi2Component c) +{ + + ASSERT_STATE(ExitInitializationMode); + + fmi2Status status = fmi2OK; + + // if values were set and no fmi2GetXXX triggered update before, + // ensure calculated values are updated now + if (S->isDirtyValues) { + status = (fmi2Status) calculateValues(S); + S->isDirtyValues = false; + } + + if (S->type == ModelExchange) { + S->state = EventMode; + } else { + S->state = StepComplete; + } + + return status; +} + +fmi2Status fmi2Terminate(fmi2Component c) +{ + + ASSERT_STATE(Terminate) + + S->state = Terminated; + + return fmi2OK; +} + +fmi2Status fmi2Reset(fmi2Component c) +{ + + ASSERT_STATE(Reset); + + reset(S); + + return fmi2OK; +} + +void fmi2FreeInstance(fmi2Component c) +{ + + if (S) { + freeModelInstance(S); + } +} + +// --------------------------------------------------------------------------- +// FMI functions: class methods not depending of a specific model instance +// --------------------------------------------------------------------------- + +const char *fmi2GetVersion() +{ + return fmi2Version; +} + +const char *fmi2GetTypesPlatform() +{ + return fmi2TypesPlatform; +} + +// --------------------------------------------------------------------------- +// FMI functions: logging control, setters and getters for Real, Integer, +// Boolean, String +// --------------------------------------------------------------------------- + +fmi2Status fmi2SetDebugLogging(fmi2Component c, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]) +{ + + ASSERT_STATE(SetDebugLogging) + + return (fmi2Status) setDebugLogging(S, loggingOn, nCategories, categories); +} + +fmi2Status fmi2GetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) +{ + + ASSERT_STATE(GetReal) + + if (nvr > 0 && nullPointer(S, "fmi2GetReal", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2GetReal", "value[]", value)) + return fmi2Error; + + if (nvr > 0 && S->isDirtyValues) { + calculateValues(S); + S->isDirtyValues = false; + } + + GET_VARIABLES(Float64); +} + +fmi2Status fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) +{ + + ASSERT_STATE(GetInteger) + + if (nvr > 0 && nullPointer(S, "fmi2GetInteger", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2GetInteger", "value[]", value)) + return fmi2Error; + + if (nvr > 0 && S->isDirtyValues) { + calculateValues(S); + S->isDirtyValues = false; + } + + GET_VARIABLES(Int32); +} + +fmi2Status fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]) +{ + + ASSERT_STATE(GetBoolean) + + if (nvr > 0 && nullPointer(S, "fmi2GetBoolean", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2GetBoolean", "value[]", value)) + return fmi2Error; + + if (nvr > 0 && S->isDirtyValues) { + calculateValues(S); + S->isDirtyValues = false; + } + + GET_BOOLEAN_VARIABLES; +} + +fmi2Status fmi2GetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) +{ + + ASSERT_STATE(GetString) + + if (nvr > 0 && nullPointer(S, "fmi2GetString", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2GetString", "value[]", value)) + return fmi2Error; + + if (nvr > 0 && S->isDirtyValues) { + calculateValues(S); + S->isDirtyValues = false; + } + + GET_VARIABLES(String); +} + +fmi2Status fmi2SetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) +{ + + ASSERT_STATE(SetReal) + + if (invalidState(S, "fmi2SetReal", MASK_fmi2SetReal)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2SetReal", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2SetReal", "value[]", value)) + return fmi2Error; + + SET_VARIABLES(Float64); +} + +fmi2Status fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) +{ + + ASSERT_STATE(SetInteger) + + if (nvr > 0 && nullPointer(S, "fmi2SetInteger", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2SetInteger", "value[]", value)) + return fmi2Error; + + SET_VARIABLES(Int32); +} + +fmi2Status fmi2SetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) +{ + + ASSERT_STATE(SetBoolean) + + if (nvr > 0 && nullPointer(S, "fmi2SetBoolean", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2SetBoolean", "value[]", value)) + return fmi2Error; + + SET_BOOLEAN_VARIABLES; +} + +fmi2Status fmi2SetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) +{ + + ASSERT_STATE(SetString); + + if (nvr > 0 && nullPointer(S, "fmi2SetString", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2SetString", "value[]", value)) + return fmi2Error; + + SET_VARIABLES(String); +} + +fmi2Status fmi2GetFMUstate(fmi2Component c, fmi2FMUstate *FMUstate) +{ + + ASSERT_STATE(GetFMUstate); + + *FMUstate = getFMUState(S); + + return fmi2OK; +} + +fmi2Status fmi2SetFMUstate(fmi2Component c, fmi2FMUstate FMUstate) +{ + + ASSERT_STATE(SetFMUstate); + + if (nullPointer(S, "fmi2SetFMUstate", "FMUstate", FMUstate)) { + return fmi2Error; + } + + setFMUState(S, FMUstate); + + return fmi2OK; +} + +fmi2Status fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate *FMUstate) +{ + + ASSERT_STATE(FreeFMUstate); + + free(*FMUstate); + + *FMUstate = NULL; + + return fmi2OK; +} + +fmi2Status fmi2SerializedFMUstateSize(fmi2Component c, fmi2FMUstate FMUstate, size_t *size) +{ + + UNUSED(c); + UNUSED(FMUstate); + + ASSERT_STATE(SerializedFMUstateSize); + + *size = sizeof(ModelInstance); + + return fmi2OK; +} + +fmi2Status fmi2SerializeFMUstate(fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size) +{ + + ASSERT_STATE(SerializeFMUstate); + + if (nullPointer(S, "fmi2SerializeFMUstate", "FMUstate", FMUstate)) { + return fmi2Error; + } + + if (invalidNumber(S, "fmi2SerializeFMUstate", "size", size, sizeof(ModelInstance))) { + return fmi2Error; + } + + memcpy(serializedState, FMUstate, sizeof(ModelInstance)); + + return fmi2OK; +} + +fmi2Status fmi2DeSerializeFMUstate(fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate *FMUstate) +{ + + ASSERT_STATE(DeSerializeFMUstate); + + if (invalidNumber(S, "fmi2DeSerializeFMUstate", "size", size, sizeof(ModelInstance))) { + return fmi2Error; + } + + if (*FMUstate == NULL) { + *FMUstate = calloc(1, sizeof(ModelInstance)); + } + + memcpy(*FMUstate, serializedState, sizeof(ModelInstance)); + + return fmi2OK; +} + +fmi2Status fmi2GetDirectionalDerivative(fmi2Component c, const fmi2ValueReference vUnknown_ref[], size_t nUnknown, + const fmi2ValueReference vKnown_ref[], size_t nKnown, + const fmi2Real dvKnown[], fmi2Real dvUnknown[]) +{ + + ASSERT_STATE(GetDirectionalDerivative); + + // TODO: check value references + // TODO: assert nUnknowns == nDeltaOfUnknowns + // TODO: assert nKnowns == nDeltaKnowns + + Status status = OK; + + for (size_t i = 0; i < nUnknown; i++) { + dvUnknown[i] = 0; + for (size_t j = 0; j < nKnown; j++) { + double partialDerivative = 0; + Status s = getPartialDerivative(S, vUnknown_ref[i], vKnown_ref[j], &partialDerivative); + status = max(status, s); + if (status > Warning) { + return (fmi2Status) status; + } + dvUnknown[i] += partialDerivative * dvKnown[j]; + } + } + + return fmi2OK; +} + +// --------------------------------------------------------------------------- +// Functions for FMI for Co-Simulation +// --------------------------------------------------------------------------- +/* Simulating the slave */ +fmi2Status fmi2SetRealInputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], const fmi2Real value[]) +{ + + UNUSED(vr); + UNUSED(nvr); + UNUSED(order); + UNUSED(value); + + ASSERT_STATE(SetRealInputDerivatives); + + logError(S, "fmi2SetRealInputDerivatives: ignoring function call." + " This model cannot interpolate inputs: canInterpolateInputs=\"fmi2False\""); + + return fmi2Error; +} + +fmi2Status fmi2GetRealOutputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], fmi2Real value[]) +{ + + ASSERT_STATE(GetRealOutputDerivatives); + +#ifdef GET_OUTPUT_DERIVATIVE + Status status = OK; + + for (size_t i = 0; i < nvr; i++) { + const Status s = getOutputDerivative(S, vr[i], order[i], &value[i]); + status = max(status, s); + if (status > Warning) { + return (fmi2Status) status; + } + } + + return (fmi2Status) status; +#else + UNUSED(vr); + UNUSED(nvr); + UNUSED(order); + UNUSED(value); + + logError(S, "fmi2GetRealOutputDerivatives: ignoring function call." + " This model cannot compute derivatives of outputs: MaxOutputDerivativeOrder=\"0\""); + + return fmi2Error; +#endif +} + +fmi2Status fmi2CancelStep(fmi2Component c) +{ + + ASSERT_STATE(CancelStep); + + logError(S, "fmi2CancelStep: Can be called when fmi2DoStep returned fmi2Pending." + " This is not the case."); + + return fmi2Error; +} + +fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, + fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPoint) +{ + + UNUSED(noSetFMUStatePriorToCurrentPoint); + + ASSERT_STATE(DoStep); + + if (communicationStepSize <= 0) { + logError(S, "fmi2DoStep: communication step size must be > 0 but was %g.", communicationStepSize); + S->state = modelError; + return fmi2Error; + } + + const fmi2Real nextCommunicationPoint = currentCommunicationPoint + communicationStepSize + EPSILON; + + fmi2Boolean nextCommunicationPointReached; + + S->solverStepSize = communicationStepSize; + + while (true) { + + nextCommunicationPointReached = S->time + S->solverStepSize > nextCommunicationPoint; + + if (nextCommunicationPointReached) { + break; // next communcation point reached + } + + bool stateEvent, timeEvent; + + doAdaptiveStep(S, &stateEvent, &timeEvent); + +#ifdef EVENT_UPDATE + if (stateEvent || timeEvent) { + eventUpdate(S); + } +#endif + } + + return S->terminateSimulation ? fmi2Discard : fmi2OK; +} + +/* Inquire slave status */ +static fmi2Status getStatus(char *fname, fmi2Component c, const fmi2StatusKind s) +{ + + if (invalidState(S, fname, MASK_fmi2GetStatus)) // all get status have the same MASK_fmi2GetStatus + return fmi2Error; + + switch (s) { + case fmi2DoStepStatus: + logError(S, + "%s: Can be called with fmi2DoStepStatus when fmi2DoStep returned fmi2Pending." + " This is not the case.", + fname); + break; + case fmi2PendingStatus: + logError(S, + "%s: Can be called with fmi2PendingStatus when fmi2DoStep returned fmi2Pending." + " This is not the case.", + fname); + break; + case fmi2LastSuccessfulTime: + logError(S, + "%s: Can be called with fmi2LastSuccessfulTime when fmi2DoStep returned fmi2Discard." + " This is not the case.", + fname); + break; + case fmi2Terminated: + logError(S, + "%s: Can be called with fmi2Terminated when fmi2DoStep returned fmi2Discard." + " This is not the case.", + fname); + break; + } + + return fmi2Discard; +} + +fmi2Status fmi2GetStatus(fmi2Component c, const fmi2StatusKind s, fmi2Status *value) +{ + + UNUSED(value); + + ASSERT_STATE(GetStatus); + + return getStatus("fmi2GetStatus", c, s); +} + +fmi2Status fmi2GetRealStatus(fmi2Component c, const fmi2StatusKind s, fmi2Real *value) +{ + + ASSERT_STATE(GetRealStatus); + + if (s == fmi2LastSuccessfulTime) { + *value = S->time; + return fmi2OK; + } + + return getStatus("fmi2GetRealStatus", c, s); +} + +fmi2Status fmi2GetIntegerStatus(fmi2Component c, const fmi2StatusKind s, fmi2Integer *value) +{ + + UNUSED(value); + + ASSERT_STATE(GetIntegerStatus); + + return getStatus("fmi2GetIntegerStatus", c, s); +} + +fmi2Status fmi2GetBooleanStatus(fmi2Component c, const fmi2StatusKind s, fmi2Boolean *value) +{ + + ASSERT_STATE(GetBooleanStatus); + + if (s == fmi2Terminated) { + *value = S->terminateSimulation; + return fmi2OK; + } + + return getStatus("fmi2GetBooleanStatus", c, s); +} + +fmi2Status fmi2GetStringStatus(fmi2Component c, const fmi2StatusKind s, fmi2String *value) +{ + UNUSED(value); + ASSERT_STATE(GetStringStatus); + return getStatus("fmi2GetStringStatus", c, s); +} + +// --------------------------------------------------------------------------- +// Functions for FMI2 for Model Exchange +// --------------------------------------------------------------------------- +/* Enter and exit the different modes */ +fmi2Status fmi2EnterEventMode(fmi2Component c) +{ + + ASSERT_STATE(EnterEventMode); + + S->state = EventMode; + + return fmi2OK; +} + +fmi2Status fmi2NewDiscreteStates(fmi2Component c, fmi2EventInfo *eventInfo) +{ + + ASSERT_STATE(NewDiscreteStates); + +#ifdef EVENT_UPDATE + eventUpdate(S); +#endif + + eventInfo->newDiscreteStatesNeeded = S->newDiscreteStatesNeeded; + eventInfo->terminateSimulation = S->terminateSimulation; + eventInfo->nominalsOfContinuousStatesChanged = S->nominalsOfContinuousStatesChanged; + eventInfo->valuesOfContinuousStatesChanged = S->valuesOfContinuousStatesChanged; + eventInfo->nextEventTimeDefined = S->nextEventTimeDefined; + eventInfo->nextEventTime = S->nextEventTime; + + return fmi2OK; +} + +fmi2Status fmi2EnterContinuousTimeMode(fmi2Component c) +{ + + ASSERT_STATE(EnterContinuousTimeMode); + + S->state = ContinuousTimeMode; + + return fmi2OK; +} + +fmi2Status fmi2CompletedIntegratorStep(fmi2Component c, fmi2Boolean noSetFMUStatePriorToCurrentPoint, + fmi2Boolean *enterEventMode, fmi2Boolean *terminateSimulation) +{ + + UNUSED(noSetFMUStatePriorToCurrentPoint); + + ASSERT_STATE(CompletedIntegratorStep); + + if (nullPointer(S, "fmi2CompletedIntegratorStep", "enterEventMode", enterEventMode)) + return fmi2Error; + + if (nullPointer(S, "fmi2CompletedIntegratorStep", "terminateSimulation", terminateSimulation)) + return fmi2Error; + + *enterEventMode = fmi2False; + *terminateSimulation = fmi2False; + + return fmi2OK; +} + +/* Providing independent variables and re-initialization of caching */ +fmi2Status fmi2SetTime(fmi2Component c, fmi2Real time) +{ + + ASSERT_STATE(SetTime); + + S->time = time; + + return fmi2OK; +} + +fmi2Status fmi2SetContinuousStates(fmi2Component c, const fmi2Real x[], size_t nx) +{ + + ASSERT_STATE(SetContinuousStates); + + if (invalidNumber(S, "fmi2SetContinuousStates", "nx", nx, NX)) + return fmi2Error; + + if (nullPointer(S, "fmi2SetContinuousStates", "x[]", x)) + return fmi2Error; + + setContinuousStates(S, x, nx); + + return fmi2OK; +} + +/* Evaluation of the model equations */ +fmi2Status fmi2GetDerivatives(fmi2Component c, fmi2Real derivatives[], size_t nx) +{ + + ASSERT_STATE(GetDerivatives); + + if (invalidNumber(S, "fmi2GetDerivatives", "nx", nx, NX)) + return fmi2Error; + + if (nullPointer(S, "fmi2GetDerivatives", "derivatives[]", derivatives)) + return fmi2Error; + + getDerivatives(S, derivatives, nx); + + return fmi2OK; +} + +fmi2Status fmi2GetEventIndicators(fmi2Component c, fmi2Real eventIndicators[], size_t ni) +{ + + ASSERT_STATE(GetEventIndicators); + +#if NZ > 0 + + if (invalidNumber(S, "fmi2GetEventIndicators", "ni", ni, NZ)) + return fmi2Error; + + getEventIndicators(S, eventIndicators, ni); +#else + UNUSED(c); + UNUSED(eventIndicators); + if (ni > 0) + return fmi2Error; +#endif + return fmi2OK; +} + +fmi2Status fmi2GetContinuousStates(fmi2Component c, fmi2Real states[], size_t nx) +{ + + ASSERT_STATE(GetContinuousStates); + + if (invalidNumber(S, "fmi2GetContinuousStates", "nx", nx, NX)) + return fmi2Error; + + if (nullPointer(S, "fmi2GetContinuousStates", "states[]", states)) + return fmi2Error; + + getContinuousStates(S, states, nx); + + return fmi2OK; +} + +fmi2Status fmi2GetNominalsOfContinuousStates(fmi2Component c, fmi2Real x_nominal[], size_t nx) +{ + + ASSERT_STATE(GetNominalsOfContinuousStates); + + if (invalidNumber(S, "fmi2GetNominalContinuousStates", "nx", nx, NX)) + return fmi2Error; + + if (nullPointer(S, "fmi2GetNominalContinuousStates", "x_nominal[]", x_nominal)) + return fmi2Error; + + for (size_t i = 0; i < nx; i++) + x_nominal[i] = 1; + + return fmi2OK; +} diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/fmi3Functions.c b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/fmi3Functions.c new file mode 100644 index 000000000..7a33b924a --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/src/fmi3Functions.c @@ -0,0 +1,1544 @@ +#if FMI_VERSION != 3 +#error FMI_VERSION must be 3 +#endif + +#include +#include +#include +#include + +#include "config.h" +#include "cosimulation.h" +#include "model.h" + +// C-code FMUs have functions names prefixed with MODEL_IDENTIFIER_. +// Define DISABLE_PREFIX to build a binary FMU. +#if !defined(DISABLE_PREFIX) && !defined(FMI3_FUNCTION_PREFIX) +#define pasteA(a, b) a##b +#define pasteB(a, b) pasteA(a, b) +#define FMI3_FUNCTION_PREFIX pasteB(MODEL_IDENTIFIER, _) +#endif +#include "fmi3Functions.h" + +#define ASSERT_NOT_NULL(p) \ + do { \ + if (!p) { \ + logError(S, "Argument %s must not be NULL.", xstr(p)); \ + S->state = modelError; \ + return (fmi3Status) Error; \ + } \ + } while (0) + +#define GET_VARIABLES(T) \ + do { \ + Status status = OK; \ + if (nValueReferences == 0) \ + return (fmi3Status) status; \ + ASSERT_NOT_NULL(valueReferences); \ + ASSERT_NOT_NULL(values); \ + size_t index = 0; \ + if (nValueReferences == 0) \ + return (fmi3Status) status; \ + if (S->isDirtyValues) { \ + Status s = calculateValues(S); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi3Status) status; \ + S->isDirtyValues = false; \ + } \ + for (size_t i = 0; i < nValueReferences; i++) { \ + Status s = get##T(S, (ValueReference) valueReferences[i], values, &index); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi3Status) status; \ + } \ + return (fmi3Status) status; \ + } while (0) + +#define SET_VARIABLES(T) \ + do { \ + Status status = OK; \ + if (nValueReferences == 0) \ + return (fmi3Status) status; \ + ASSERT_NOT_NULL(valueReferences); \ + ASSERT_NOT_NULL(values); \ + size_t index = 0; \ + for (size_t i = 0; i < nValueReferences; i++) { \ + Status s = set##T(S, (ValueReference) valueReferences[i], values, &index); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi3Status) status; \ + } \ + if (nValueReferences > 0) \ + S->isDirtyValues = true; \ + return (fmi3Status) status; \ + } while (0) + +#ifndef max +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef DT_EVENT_DETECT +#define DT_EVENT_DETECT 1e-10 +#endif + +// --------------------------------------------------------------------------- +// Function calls allowed state masks for both Model-exchange and Co-simulation +// --------------------------------------------------------------------------- +#define MASK_AnyState (~0) + +/* Inquire version numbers and set debug logging */ +#define MASK_fmi3GetVersion MASK_AnyState +#define MASK_fmi3SetDebugLogging MASK_AnyState + +/* Creation and destruction of FMU instances */ +#define MASK_fmi3InstantiateInstantiateModelExchange MASK_AnyState +#define MASK_fmi3InstantiateCoSimulation MASK_AnyState +#define MASK_fmi3InstantiateScheduledExectuion MASK_AnyState +#define MASK_fmi3FreeInstance MASK_AnyState + +/* Enter and exit initialization mode, terminate and reset */ +#define MASK_fmi3EnterInitializationMode Instantiated +#define MASK_fmi3ExitInitializationMode InitializationMode +#define MASK_fmi3EnterEventMode (ContinuousTimeMode | StepMode) +#define MASK_fmi3Terminate (ContinuousTimeMode | StepMode | StepDiscarded | EventMode | ClockActivationMode | ReconfigurationMode) +#define MASK_fmi3Reset MASK_AnyState + +/* Common Functions */ + +/* Getting and setting variable values */ +#define MASK_fmi3GetFloat32 (InitializationMode | ConfigurationMode | ReconfigurationMode | EventMode | ContinuousTimeMode | StepMode | ClockActivationMode | IntermediateUpdateMode | Terminated) +#define MASK_fmi3GetFloat64 MASK_fmi3GetFloat32 +#define MASK_fmi3GetInt8 MASK_fmi3GetFloat32 +#define MASK_fmi3GetUInt8 MASK_fmi3GetFloat32 +#define MASK_fmi3GetInt16 MASK_fmi3GetFloat32 +#define MASK_fmi3GetUInt16 MASK_fmi3GetFloat32 +#define MASK_fmi3GetInt32 MASK_fmi3GetFloat32 +#define MASK_fmi3GetUInt32 MASK_fmi3GetFloat32 +#define MASK_fmi3GetInt64 MASK_fmi3GetFloat32 +#define MASK_fmi3GetUInt64 MASK_fmi3GetFloat32 +#define MASK_fmi3GetBoolean MASK_fmi3GetFloat32 +#define MASK_fmi3GetString MASK_fmi3GetFloat32 +#define MASK_fmi3GetBinary MASK_fmi3GetFloat32 +#define MASK_fmi3GetClock MASK_AnyState + +#define MASK_fmi3SetFloat32 (Instantiated | InitializationMode | ConfigurationMode | ReconfigurationMode | EventMode | ContinuousTimeMode | StepMode | ClockActivationMode | IntermediateUpdateMode | Terminated) +#define MASK_fmi3SetFloat64 MASK_fmi3SetFloat32 +#define MASK_fmi3SetInt8 (Instantiated | ConfigurationMode | ReconfigurationMode | InitializationMode | EventMode | StepMode | ClockActivationMode | Terminated) +#define MASK_fmi3SetUInt8 MASK_fmi3SetInt8 +#define MASK_fmi3SetInt16 MASK_fmi3SetInt8 +#define MASK_fmi3SetUInt16 MASK_fmi3SetInt8 +#define MASK_fmi3SetInt32 MASK_fmi3SetInt8 +#define MASK_fmi3SetUInt32 MASK_fmi3SetInt8 +#define MASK_fmi3SetInt64 MASK_fmi3SetInt8 +#define MASK_fmi3SetUInt64 MASK_fmi3SetInt8 +#define MASK_fmi3SetBoolean MASK_fmi3SetInt8 +#define MASK_fmi3SetString MASK_fmi3SetInt8 +#define MASK_fmi3SetBinary MASK_fmi3SetInt8 +#define MASK_fmi3SetClock MASK_AnyState + +/* Getting Variable Dependency Information */ +#define MASK_fmi3GetNumberOfVariableDependencies MASK_AnyState +#define MASK_fmi3GetVariableDependencies MASK_AnyState + +/* Getting and setting the internal FMU state */ +#define MASK_fmi3GetFMUState MASK_AnyState +#define MASK_fmi3SetFMUState MASK_AnyState +#define MASK_fmi3FreeFMUState MASK_AnyState +#define MASK_fmi3SerializedFMUStateSize MASK_AnyState +#define MASK_fmi3SerializeFMUState MASK_AnyState +#define MASK_fmi3DeserializeFMUState MASK_AnyState + +/* Getting partial derivatives */ +#define MASK_fmi3GetDirectionalDerivative (InitializationMode | StepMode | EventMode | ContinuousTimeMode | Terminated) +#define MASK_fmi3GetAdjointDerivative MASK_fmi3GetDirectionalDerivative + +/* Entering and exiting the Configuration or Reconfiguration Mode */ +#define MASK_fmi3EnterConfigurationMode (Instantiated | StepMode | EventMode | ClockActivationMode) +#define MASK_fmi3ExitConfigurationMode (ConfigurationMode | ReconfigurationMode) + +/* Clock related functions */ +// TODO: fix masks +#define MASK_fmi3GetIntervalDecimal MASK_AnyState +#define MASK_fmi3GetIntervalFraction MASK_AnyState +#define MASK_fmi3SetIntervalDecimal MASK_AnyState +#define MASK_fmi3SetIntervalFraction MASK_AnyState +#define MASK_fmi3NewDiscreteStates MASK_AnyState + +/* Functions for Model Exchange */ + +#define MASK_fmi3EnterContinuousTimeMode EventMode +#define MASK_fmi3CompletedIntegratorStep ContinuousTimeMode + +/* Providing independent variables and re-initialization of caching */ +#define MASK_fmi3SetTime (EventMode | ContinuousTimeMode) +#define MASK_fmi3SetContinuousStates ContinuousTimeMode + +/* Evaluation of the model equations */ +#define MASK_fmi3GetContinuousStateDerivatives (InitializationMode | EventMode | ContinuousTimeMode | Terminated) +#define MASK_fmi3GetEventIndicators MASK_fmi3GetContinuousStateDerivatives +#define MASK_fmi3GetContinuousStates MASK_fmi3GetContinuousStateDerivatives +#define MASK_fmi3GetNominalsOfContinuousStates MASK_fmi3GetContinuousStateDerivatives + +#define MASK_fmi3GetNumberOfContinuousStates MASK_AnyState +#define MASK_fmi3GetNumberOfEventIndicators MASK_AnyState + +/* Functions for Co-Simulation */ + +#define MASK_fmi3EnterStepMode (InitializationMode | EventMode) +#define MASK_fmi3SetInputDerivatives (Instantiated | InitializationMode | StepMode) +#define MASK_fmi3GetOutputDerivatives (StepMode | StepDiscarded | Terminated | Error) +#define MASK_fmi3DoStep StepMode +#define MASK_fmi3ActivateModelPartition ClockActivationMode +#define MASK_fmi3DoEarlyReturn IntermediateUpdateMode +#define MASK_fmi3GetDoStepDiscardedStatus StepMode + +// --------------------------------------------------------------------------- +// Private helpers used below to validate function arguments +// --------------------------------------------------------------------------- + +#define NOT_IMPLEMENTED \ + do { \ + ModelInstance *comp = (ModelInstance *) instance; \ + logError(comp, "Function is not implemented."); \ + return fmi3Error; \ + } while (0) + +#define ASSERT_STATE(F) \ + if (!instance) \ + return fmi3Error; \ + ModelInstance *S = (ModelInstance *) instance; \ + if (!allowedState(S, MASK_fmi3##F, #F)) \ + return fmi3Error; + +static bool allowedState(ModelInstance *instance, int statesExpected, char *name) +{ + + if (!instance) { + return false; + } + + if (!(instance->state & statesExpected)) { + logError(instance, "fmi3%s: Illegal call sequence.", name); + return false; + } + + return true; +} + +/*************************************************** + Common Functions + ****************************************************/ + +const char *fmi3GetVersion() +{ + return fmi3Version; +} + +fmi3Status fmi3SetDebugLogging(fmi3Instance instance, + fmi3Boolean loggingOn, + size_t nCategories, + const fmi3String categories[]) +{ + + ASSERT_STATE(SetDebugLogging) + + return (fmi3Status) setDebugLogging(S, loggingOn, nCategories, categories); +} + +fmi3Instance fmi3InstantiateModelExchange( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage) +{ + + UNUSED(visible); + +#ifndef MODEL_EXCHANGE + UNUSED(instanceName); + UNUSED(instantiationToken); + UNUSED(resourcePath); + UNUSED(loggingOn); + UNUSED(instanceEnvironment); + UNUSED(logMessage); + + return NULL; +#else + return createModelInstance( + (loggerType) logMessage, + NULL, + instanceEnvironment, + instanceName, + instantiationToken, + resourcePath, + loggingOn, + ModelExchange); +#endif +} + +fmi3Instance fmi3InstantiateCoSimulation( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3Boolean eventModeUsed, + fmi3Boolean earlyReturnAllowed, + const fmi3ValueReference requiredIntermediateVariables[], + size_t nRequiredIntermediateVariables, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3IntermediateUpdateCallback intermediateUpdate) +{ + + UNUSED(visible); + UNUSED(requiredIntermediateVariables); + UNUSED(nRequiredIntermediateVariables); + +#ifndef EVENT_UPDATE + if (eventModeUsed) { + if (logMessage) { + logMessage(instanceEnvironment, fmi3Error, "error", "Event Mode is not supported."); + } + return NULL; + } +#endif + + ModelInstance *instance = createModelInstance( + (loggerType) logMessage, + (intermediateUpdateType) intermediateUpdate, + instanceEnvironment, + instanceName, + instantiationToken, + resourcePath, + loggingOn, + CoSimulation); + + if (instance) { + instance->earlyReturnAllowed = earlyReturnAllowed; + instance->eventModeUsed = eventModeUsed; + instance->state = Instantiated; + } + + return instance; +} + +fmi3Instance fmi3InstantiateScheduledExecution( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3ClockUpdateCallback clockUpdate, + fmi3LockPreemptionCallback lockPreemption, + fmi3UnlockPreemptionCallback unlockPreemption) +{ + + UNUSED(visible); + +#ifndef SCHEDULED_CO_SIMULATION + + UNUSED(instanceName); + UNUSED(instantiationToken); + UNUSED(resourcePath); + UNUSED(loggingOn); + UNUSED(instanceEnvironment); + UNUSED(logMessage); + UNUSED(clockUpdate); + UNUSED(lockPreemption); + UNUSED(unlockPreemption); + + return NULL; +#else + ModelInstance *instance = createModelInstance( + (loggerType) logMessage, + NULL, + instanceEnvironment, + instanceName, + instantiationToken, + resourcePath, + loggingOn, + ScheduledExecution); + + if (instance) { + instance->state = Instantiated; + instance->clockUpdate = clockUpdate; + instance->lockPreemtion = lockPreemption; + instance->unlockPreemtion = unlockPreemption; + } + + return instance; +#endif +} + +void fmi3FreeInstance(fmi3Instance instance) +{ + + if (!instance) + return; + + freeModelInstance((ModelInstance *) instance); +} + +fmi3Status fmi3EnterInitializationMode(fmi3Instance instance, + fmi3Boolean toleranceDefined, + fmi3Float64 tolerance, + fmi3Float64 startTime, + fmi3Boolean stopTimeDefined, + fmi3Float64 stopTime) +{ + + UNUSED(toleranceDefined); + UNUSED(tolerance); + UNUSED(stopTimeDefined); + UNUSED(stopTime); + + ASSERT_STATE(EnterInitializationMode); + + S->startTime = startTime; + S->time = startTime; + S->state = InitializationMode; + + return fmi3OK; +} + +fmi3Status fmi3ExitInitializationMode(fmi3Instance instance) +{ + + ASSERT_STATE(ExitInitializationMode); + + fmi3Status status = fmi3OK; + + // if values were set and no fmi3GetXXX triggered update before, + // ensure calculated values are updated now + if (S->isDirtyValues) { + + status = (fmi3Status) calculateValues(S); + + if (status > fmi3Warning) { + return status; + } + + S->isDirtyValues = false; + } + + switch (S->type) { + case ModelExchange: + S->state = EventMode; + break; + case CoSimulation: + S->state = S->eventModeUsed ? EventMode : StepMode; + break; + case ScheduledExecution: + S->state = ClockActivationMode; + break; + } + +#if NZ > 0 + // initialize event indicators + getEventIndicators(S, S->z, NZ); +#endif + + return status; +} + +fmi3Status fmi3EnterEventMode(fmi3Instance instance) +{ + + ASSERT_STATE(EnterEventMode); + + S->state = EventMode; + + return fmi3OK; +} + +fmi3Status fmi3Terminate(fmi3Instance instance) +{ + + ASSERT_STATE(Terminate); + + S->state = Terminated; + + return fmi3OK; +} + +fmi3Status fmi3Reset(fmi3Instance instance) +{ + + ASSERT_STATE(Reset); + + reset(S); + + return fmi3OK; +} + +fmi3Status fmi3GetFloat32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetFloat32); + GET_VARIABLES(Float32); +} + +fmi3Status fmi3GetFloat64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetFloat64); + GET_VARIABLES(Float64); +} + +fmi3Status fmi3GetInt8(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int8 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetInt8); + GET_VARIABLES(Int8); +} + +fmi3Status fmi3GetUInt8(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt8 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetUInt8); + GET_VARIABLES(UInt8); +} + +fmi3Status fmi3GetInt16(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int16 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetInt16); + GET_VARIABLES(Int16); +} + +fmi3Status fmi3GetUInt16(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt16 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetUInt16); + GET_VARIABLES(UInt16); +} + +fmi3Status fmi3GetInt32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetInt32); + GET_VARIABLES(Int32); +} + +fmi3Status fmi3GetUInt32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetUInt32); + GET_VARIABLES(UInt32); +} + +fmi3Status fmi3GetInt64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetInt64); + GET_VARIABLES(Int64); +} + +fmi3Status fmi3GetUInt64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetUInt64); + GET_VARIABLES(UInt64); +} + +fmi3Status fmi3GetBoolean(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Boolean values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetBoolean); + GET_VARIABLES(Boolean); +} + +fmi3Status fmi3GetString(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3String values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetString); + GET_VARIABLES(String); +} + +fmi3Status fmi3GetBinary(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + size_t valueSizes[], + fmi3Binary values[], + size_t nValues) +{ + + UNUSED(nValues); + + ASSERT_STATE(GetBinary); + + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + size_t index = 0; + Status s = getBinary(S, (ValueReference) valueReferences[i], valueSizes, (const char **) values, &index); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + } + + return (fmi3Status) status; +} + +fmi3Status fmi3GetClock(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Clock values[]) +{ + + ASSERT_STATE(GetClock); + + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + Status s = getClock(instance, (ValueReference) valueReferences[i], &values[i]); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + } + + return (fmi3Status) status; +} + +fmi3Status fmi3SetFloat32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetFloat32); + SET_VARIABLES(Float32); +} + +fmi3Status fmi3SetFloat64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetFloat64); + SET_VARIABLES(Float64); +} + +fmi3Status fmi3SetInt8(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int8 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetInt8); + SET_VARIABLES(Int8); +} + +fmi3Status fmi3SetUInt8(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt8 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetUInt8); + SET_VARIABLES(UInt8); +} + +fmi3Status fmi3SetInt16(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int16 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetInt16); + SET_VARIABLES(Int16); +} + +fmi3Status fmi3SetUInt16(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt16 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetUInt16); + SET_VARIABLES(UInt16); +} + +fmi3Status fmi3SetInt32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetInt32); + SET_VARIABLES(Int32); +} + +fmi3Status fmi3SetUInt32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetUInt32); + SET_VARIABLES(UInt32); +} + +fmi3Status fmi3SetInt64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetInt64); + SET_VARIABLES(Int64); +} + +fmi3Status fmi3SetUInt64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetUInt64); + SET_VARIABLES(UInt64); +} + +fmi3Status fmi3SetBoolean(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Boolean values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetBoolean); + SET_VARIABLES(Boolean); +} + +fmi3Status fmi3SetString(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3String values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetString); + SET_VARIABLES(String); +} + +fmi3Status fmi3SetBinary(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const size_t valueSizes[], + const fmi3Binary values[], + size_t nValues) +{ + + UNUSED(nValues); + + ASSERT_STATE(SetBinary); + + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + size_t index = 0; + Status s = setBinary(S, (ValueReference) valueReferences[i], valueSizes, (const char *const *) values, &index); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + } + + return (fmi3Status) status; +} + +fmi3Status fmi3SetClock(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Clock values[]) +{ + + ASSERT_STATE(SetClock); + + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + if (values[i]) { + Status s = activateClock(instance, (ValueReference) valueReferences[i]); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + } + } + + return (fmi3Status) status; +} + +fmi3Status fmi3GetNumberOfVariableDependencies(fmi3Instance instance, + fmi3ValueReference valueReference, + size_t *nDependencies) +{ + UNUSED(valueReference); + UNUSED(nDependencies); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3GetVariableDependencies(fmi3Instance instance, + fmi3ValueReference dependent, + size_t elementIndicesOfDependent[], + fmi3ValueReference independents[], + size_t elementIndicesOfIndependents[], + fmi3DependencyKind dependencyKinds[], + size_t nDependencies) +{ + + UNUSED(dependent); + UNUSED(elementIndicesOfDependent); + UNUSED(independents); + UNUSED(elementIndicesOfIndependents); + UNUSED(dependencyKinds); + UNUSED(nDependencies); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3GetFMUState(fmi3Instance instance, fmi3FMUState *FMUState) +{ + + ASSERT_STATE(GetFMUState); + + *FMUState = getFMUState(S); + + return fmi3OK; +} + +fmi3Status fmi3SetFMUState(fmi3Instance instance, fmi3FMUState FMUState) +{ + + ASSERT_STATE(SetFMUState); + + if (nullPointer(S, "fmi3SetFMUState", "FMUState", FMUState)) { + return fmi3Error; + } + + setFMUState(S, FMUState); + + return fmi3OK; +} + +fmi3Status fmi3FreeFMUState(fmi3Instance instance, fmi3FMUState *FMUState) +{ + + ASSERT_STATE(FreeFMUState); + + free(*FMUState); + + *FMUState = NULL; + + return fmi3OK; +} + +fmi3Status fmi3SerializedFMUStateSize(fmi3Instance instance, + fmi3FMUState FMUState, + size_t *size) +{ + + UNUSED(instance); + UNUSED(FMUState); + + ASSERT_STATE(SerializedFMUStateSize); + + *size = sizeof(ModelInstance); + + return fmi3OK; +} + +fmi3Status fmi3SerializeFMUState(fmi3Instance instance, + fmi3FMUState FMUState, + fmi3Byte serializedState[], + size_t size) +{ + + ASSERT_STATE(SerializeFMUState); + + if (nullPointer(S, "fmi3SerializeFMUState", "FMUstate", FMUState)) { + return fmi3Error; + } + + if (invalidNumber(S, "fmi3SerializeFMUState", "size", size, sizeof(ModelInstance))) { + return fmi3Error; + } + + memcpy(serializedState, FMUState, sizeof(ModelInstance)); + + return fmi3OK; +} + +fmi3Status fmi3DeserializeFMUState(fmi3Instance instance, + const fmi3Byte serializedState[], + size_t size, + fmi3FMUState *FMUState) +{ + + ASSERT_STATE(DeserializeFMUState); + + if (invalidNumber(S, "fmi3DeserializeFMUState", "size", size, sizeof(ModelInstance))) { + return fmi3Error; + } + + if (*FMUState == NULL) { + *FMUState = calloc(1, sizeof(ModelInstance)); + } + + memcpy(*FMUState, serializedState, sizeof(ModelInstance)); + + return fmi3OK; +} + +fmi3Status fmi3GetDirectionalDerivative(fmi3Instance instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity) +{ + + UNUSED(nSeed); + UNUSED(nSensitivity); + + ASSERT_STATE(GetDirectionalDerivative); + + // TODO: check value references + // TODO: assert nUnknowns == nDeltaOfUnknowns + // TODO: assert nKnowns == nDeltaKnowns + + Status status = OK; + + for (size_t i = 0; i < nUnknowns; i++) { + sensitivity[i] = 0; + for (size_t j = 0; j < nKnowns; j++) { + double partialDerivative = 0; + Status s = getPartialDerivative(S, (ValueReference) unknowns[i], (ValueReference) knowns[j], &partialDerivative); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + sensitivity[i] += partialDerivative * seed[j]; + } + } + + return fmi3OK; +} + +fmi3Status fmi3GetAdjointDerivative(fmi3Instance instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity) +{ + + UNUSED(nSeed); + UNUSED(nSensitivity); + + ASSERT_STATE(GetAdjointDerivative); + + // TODO: check value references + + Status status = OK; + + for (size_t i = 0; i < nKnowns; i++) { + sensitivity[i] = 0; + for (size_t j = 0; j < nUnknowns; j++) { + double partialDerivative = 0; + Status s = getPartialDerivative(S, (ValueReference) unknowns[j], (ValueReference) knowns[i], &partialDerivative); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + sensitivity[i] += partialDerivative * seed[j]; + } + } + + return fmi3OK; +} + +fmi3Status fmi3EnterConfigurationMode(fmi3Instance instance) +{ + + ASSERT_STATE(EnterConfigurationMode); + + S->state = (S->state == Instantiated) ? ConfigurationMode : ReconfigurationMode; + + return fmi3OK; +} + +fmi3Status fmi3ExitConfigurationMode(fmi3Instance instance) +{ + + ASSERT_STATE(ExitConfigurationMode); + + if (S->state == ConfigurationMode) { + S->state = Instantiated; + } else { + switch (S->type) { + case ModelExchange: + S->state = EventMode; + break; + case CoSimulation: + S->state = StepMode; + break; + case ScheduledExecution: + S->state = ClockActivationMode; + break; + } + } + + return fmi3OK; +} + +fmi3Status fmi3GetIntervalDecimal(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 intervals[], + fmi3IntervalQualifier qualifiers[]) +{ + + ASSERT_STATE(GetIntervalDecimal); + + // ? Check nValueReferences != nValues + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + Status s = getInterval(instance, (ValueReference) valueReferences[i], &intervals[i], (int *) &qualifiers[i]); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + } + + return (fmi3Status) status; +} + +fmi3Status fmi3GetIntervalFraction(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 intervalCounters[], + fmi3UInt64 resolutions[], + fmi3IntervalQualifier qualifiers[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(intervalCounters); + UNUSED(resolutions); + UNUSED(qualifiers); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3GetShiftDecimal(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 shifts[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(shifts); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3GetShiftFraction(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 shiftCounters[], + fmi3UInt64 resolutions[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(shiftCounters); + UNUSED(resolutions); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3SetIntervalDecimal(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 intervals[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(intervals); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3SetIntervalFraction(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 intervalCounters[], + const fmi3UInt64 resolutions[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(intervalCounters); + UNUSED(resolutions); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3SetShiftDecimal(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 shifts[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(shifts); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3SetShiftFraction(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 shiftCounters[], + const fmi3UInt64 resolutions[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(shiftCounters); + UNUSED(resolutions); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3EvaluateDiscreteStates(fmi3Instance instance) +{ + NOT_IMPLEMENTED; +} + +fmi3Status fmi3UpdateDiscreteStates(fmi3Instance instance, + fmi3Boolean *discreteStatesNeedUpdate, + fmi3Boolean *terminateSimulation, + fmi3Boolean *nominalsOfContinuousStatesChanged, + fmi3Boolean *valuesOfContinuousStatesChanged, + fmi3Boolean *nextEventTimeDefined, + fmi3Float64 *nextEventTime) +{ + + ASSERT_STATE(NewDiscreteStates); + +#ifdef EVENT_UPDATE + eventUpdate(S); +#endif + + // copy internal eventInfo of component to output arguments + if (discreteStatesNeedUpdate) + *discreteStatesNeedUpdate = S->newDiscreteStatesNeeded; + if (terminateSimulation) + *terminateSimulation = S->terminateSimulation; + if (nominalsOfContinuousStatesChanged) + *nominalsOfContinuousStatesChanged = S->nominalsOfContinuousStatesChanged; + if (valuesOfContinuousStatesChanged) + *valuesOfContinuousStatesChanged = S->valuesOfContinuousStatesChanged; + if (nextEventTimeDefined) + *nextEventTimeDefined = S->nextEventTimeDefined; + if (nextEventTime) + *nextEventTime = S->nextEventTime; + + return fmi3OK; +} + +/*************************************************** + Functions for Model Exchange + ****************************************************/ + +fmi3Status fmi3EnterContinuousTimeMode(fmi3Instance instance) +{ + + ASSERT_STATE(EnterContinuousTimeMode); + + S->state = ContinuousTimeMode; + + return fmi3OK; +} + +fmi3Status fmi3CompletedIntegratorStep(fmi3Instance instance, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *enterEventMode, + fmi3Boolean *terminateSimulation) +{ + + UNUSED(noSetFMUStatePriorToCurrentPoint); + + ASSERT_STATE(CompletedIntegratorStep); + + ASSERT_NOT_NULL(enterEventMode); + ASSERT_NOT_NULL(terminateSimulation); + + *enterEventMode = fmi3False; + *terminateSimulation = fmi3False; + + return fmi3OK; +} + +/* Providing independent variables and re-initialization of caching */ +fmi3Status fmi3SetTime(fmi3Instance instance, fmi3Float64 time) +{ + + ASSERT_STATE(SetTime); + + S->time = time; + + return fmi3OK; +} + +fmi3Status fmi3SetContinuousStates(fmi3Instance instance, + const fmi3Float64 continuousStates[], + size_t nContinuousStates) +{ + + ASSERT_STATE(SetContinuousStates); + + if (invalidNumber(S, "fmi3SetContinuousStates", "nContinuousStates", nContinuousStates, NX)) + return fmi3Error; + + ASSERT_NOT_NULL(continuousStates); + + setContinuousStates(S, continuousStates, nContinuousStates); + + return fmi3OK; +} + +/* Evaluation of the model equations */ +fmi3Status fmi3GetContinuousStateDerivatives(fmi3Instance instance, + fmi3Float64 derivatives[], + size_t nContinuousStates) +{ + + ASSERT_STATE(GetContinuousStateDerivatives); + + if (invalidNumber(S, "fmi3GetContinuousStateDerivatives", "nContinuousStates", nContinuousStates, NX)) + return fmi3Error; + + if (nullPointer(S, "fmi3GetContinuousStateDerivatives", "derivatives[]", derivatives)) + return fmi3Error; + + getDerivatives(S, derivatives, nContinuousStates); + + return fmi3OK; +} + +fmi3Status fmi3GetEventIndicators(fmi3Instance instance, + fmi3Float64 eventIndicators[], + size_t nEventIndicators) +{ + + ASSERT_STATE(GetEventIndicators); + +#if NZ > 0 + if (invalidNumber(S, "fmi3GetEventIndicators", "nEventIndicators", nEventIndicators, NZ)) { + return fmi3Error; + } + + getEventIndicators(S, eventIndicators, nEventIndicators); +#else + + UNUSED(eventIndicators); + + if (nEventIndicators > 0) { + // TODO: log error + return fmi3Error; + } +#endif + + return fmi3OK; +} + +fmi3Status fmi3GetContinuousStates(fmi3Instance instance, + fmi3Float64 continuousStates[], + size_t nContinuousStates) +{ + + ASSERT_STATE(GetContinuousStates); + + if (invalidNumber(S, "fmi3GetContinuousStates", "nContinuousStates", nContinuousStates, NX)) + return fmi3Error; + + if (nullPointer(S, "fmi3GetContinuousStates", "continuousStates[]", continuousStates)) + return fmi3Error; + + getContinuousStates(S, continuousStates, nContinuousStates); + + return fmi3OK; +} + +fmi3Status fmi3GetNominalsOfContinuousStates(fmi3Instance instance, + fmi3Float64 nominals[], + size_t nContinuousStates) +{ + + ASSERT_STATE(GetNominalsOfContinuousStates); + + if (invalidNumber(S, "fmi3GetNominalContinuousStates", "nContinuousStates", nContinuousStates, NX)) + return fmi3Error; + + if (nullPointer(S, "fmi3GetNominalContinuousStates", "nominals[]", nominals)) + return fmi3Error; + + for (size_t i = 0; i < nContinuousStates; i++) { + nominals[i] = 1; + } + + return fmi3OK; +} + +fmi3Status fmi3GetNumberOfEventIndicators(fmi3Instance instance, + size_t *nEventIndicators) +{ + + ASSERT_STATE(GetNumberOfEventIndicators); + + ASSERT_NOT_NULL(nEventIndicators); + + *nEventIndicators = NZ; + + return fmi3OK; +} + +fmi3Status fmi3GetNumberOfContinuousStates(fmi3Instance instance, + size_t *nContinuousStates) +{ + + ASSERT_STATE(GetNumberOfContinuousStates); + + ASSERT_NOT_NULL(nContinuousStates); + + *nContinuousStates = NX; + + return fmi3OK; +} + +/*************************************************** + Functions for Co-Simulation + ****************************************************/ + +fmi3Status fmi3EnterStepMode(fmi3Instance instance) +{ + + ASSERT_STATE(EnterStepMode); + + S->state = StepMode; + + return fmi3OK; +} + +fmi3Status fmi3GetOutputDerivatives(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 orders[], + fmi3Float64 values[], + size_t nValues) +{ + + UNUSED(nValues); + + ASSERT_STATE(GetOutputDerivatives); + +#ifdef GET_OUTPUT_DERIVATIVE + + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + const Status s = getOutputDerivative(S, (ValueReference) valueReferences[i], orders[i], &values[i]); + status = max(status, s); + if (status > Warning) { + return (fmi3Status) status; + } + } + + return (fmi3Status) status; + +#else + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(orders); + UNUSED(values); + + NOT_IMPLEMENTED; +#endif +} + +fmi3Status fmi3DoStep(fmi3Instance instance, + fmi3Float64 currentCommunicationPoint, + fmi3Float64 communicationStepSize, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *eventHandlingNeeded, + fmi3Boolean *terminateSimulation, + fmi3Boolean *earlyReturn, + fmi3Float64 *lastSuccessfulTime) +{ + + UNUSED(noSetFMUStatePriorToCurrentPoint); + + ASSERT_STATE(DoStep); + + if (communicationStepSize <= 0) { + logError(S, "fmi3DoStep: communication step size must be > 0 but was %g.", communicationStepSize); + S->state = modelError; + return fmi3Error; + } + + const fmi3Float64 nextCommunicationPoint = currentCommunicationPoint + communicationStepSize + EPSILON; + + S->solverStepSize = communicationStepSize; + + fmi3Boolean nextCommunicationPointReached; + + *eventHandlingNeeded = fmi3False; + + while (true) { + + nextCommunicationPointReached = S->time + S->solverStepSize > nextCommunicationPoint; + + if (nextCommunicationPointReached) { + break; + } + + bool stateEvent, timeEvent; + + doAdaptiveStep(S, &stateEvent, &timeEvent); + +#ifdef EVENT_UPDATE + if (stateEvent || timeEvent) { + + *eventHandlingNeeded = fmi3True; + + if (S->eventModeUsed) { + break; + } + + eventUpdate(S); + + if (S->earlyReturnAllowed) { + break; + } + } +#endif + } + + *earlyReturn = !nextCommunicationPointReached; + + *terminateSimulation = fmi3False; + + *lastSuccessfulTime = S->time; + + return fmi3OK; +} + +fmi3Status fmi3ActivateModelPartition(fmi3Instance instance, + fmi3ValueReference clockReference, + fmi3Float64 activationTime) +{ + + ASSERT_STATE(ActivateModelPartition); + + return (fmi3Status) activateModelPartition(S, (ValueReference) clockReference, activationTime); +} diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/fmu/thirdparty/LICENSE.txt b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/thirdparty/LICENSE.txt new file mode 100644 index 000000000..d2ff5fb89 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/fmu/thirdparty/LICENSE.txt @@ -0,0 +1,148 @@ +Copyright (c) 2022, Modelica Association Project "FMI". +All rights reserved. + +The Reference FMUs and FMUSim are released under the 2-Clause BSD license: + +-------------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIEDi +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- + +The Reference FMUs are a fork of the Test FMUs (https://github.com/CATIA-Systems/Test-FMUs) +by Dassault Systemes, which are a fork of the FMU SDK (https://github.com/qtronic/fmusdk) +by QTronic, both released under the 2-Clause BSD License. + +FMUSim uses the following third party libraries. + +================================================================================ + +Libxml2 (https://gitlab.gnome.org/GNOME/libxml2) released under the MIT license: + +Except where otherwise noted in the source code (e.g. the files hash.c, +list.c and the trio files, which are covered by a similar licence but +with different Copyright notices) all the files are: + + Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is fur- +nished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- +NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +================================================================================ + +Zlib (http://zlib.net/) release under the zlib license: + +Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +Jean-loup Gailly Mark Adler +jloup@gzip.org madler@alumni.caltech.edu + +================================================================================ + +CSV-fast-reader (https://github.com/jandoczy/csv-fast-reader) release under the +MIT license: + +Copyright (c) 2019 Jan Doczy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +================================================================================ + +SUNDIALS: SUite of Nonlinear and DIfferential/ALgebraic equation Solvers +(https://computing.llnl.gov/projects/sundials) release under the BSD 3-Clause license: + +Copyright (c) 2002-2022, Lawrence Livermore National Security and Southern Methodist University. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +The FMI header files are copyright (c) 2008-2011 MODELISAR consortium, 2012-2022 +the Modelica Association Project "FMI" and released under the 2-Clause BSD License. diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/precice-settings.json b/flow-around-controlled-moving-cylinder/controller-fmi/precice-settings.json new file mode 100644 index 000000000..b962b5fdc --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/precice-settings.json @@ -0,0 +1,9 @@ +{ + "coupling_params": { + "participant_name": "Controller", + "config_file_name": "../precice-config.xml", + "mesh_name": "Mesh-Controller", + "write_data_name": "Displacement-Spring", + "read_data_name": "Displacement-Cylinder" + } +} diff --git a/flow-around-controlled-moving-cylinder/controller-fmi/run.sh b/flow-around-controlled-moving-cylinder/controller-fmi/run.sh new file mode 100755 index 000000000..46a4f217d --- /dev/null +++ b/flow-around-controlled-moving-cylinder/controller-fmi/run.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +if [ ! -f PIDcontroller.fmu ]; then + cd fmu + rm -rf build + mkdir build + cd build + cmake -DFMI_TYPE=CS -DFMI_VERSION=3 .. + make + cp ./PIDcontroller.fmu ../.. + cd ../../ +fi + +fmiprecice ./fmi-settings.json ./precice-settings.json + +close_log diff --git a/flow-around-controlled-moving-cylinder/fluid-openfoam/0.orig/U b/flow-around-controlled-moving-cylinder/fluid-openfoam/0.orig/U new file mode 100644 index 000000000..871adb944 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/fluid-openfoam/0.orig/U @@ -0,0 +1,44 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0.068018 0 0); + + +boundaryField +{ + topAndBottom + { + type slip; + } + + inlet + { + type fixedValue; + value $internalField; + } + + outlet + { + type zeroGradient; + } + + frontAndBack + { + type empty; + } + + + cylinder + { + type movingWallVelocity; + value uniform (0 0 0); + } + +} diff --git a/flow-around-controlled-moving-cylinder/fluid-openfoam/0.orig/p b/flow-around-controlled-moving-cylinder/fluid-openfoam/0.orig/p new file mode 100644 index 000000000..0445a8ee8 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/fluid-openfoam/0.orig/p @@ -0,0 +1,41 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p; +} + +dimensions [0 2 -2 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + + topAndBottom + { + type zeroGradient; + } + + outlet + { + type zeroGradient; + } + + inlet + { + type zeroGradient; + } + + frontAndBack + { + type empty; + } + + cylinder + { + type zeroGradient; + } + +} diff --git a/flow-around-controlled-moving-cylinder/fluid-openfoam/0.orig/pointDisplacement b/flow-around-controlled-moving-cylinder/fluid-openfoam/0.orig/pointDisplacement new file mode 100644 index 000000000..95801a57d --- /dev/null +++ b/flow-around-controlled-moving-cylinder/fluid-openfoam/0.orig/pointDisplacement @@ -0,0 +1,44 @@ +FoamFile +{ + version 2.0; + format ascii; + class pointVectorField; + location "0.01"; + object pointDisplacement; +} + +dimensions [0 1 0 0 0 0 0]; + +internalField uniform (0 0 0); + +boundaryField +{ + topAndBottom + { + type fixedValue; + value $internalField; + } + + inlet + { + type fixedValue; + value $internalField; + } + + outlet + { + type fixedValue; + value $internalField; + } + + cylinder + { + type fixedValue; + value $internalField; + } + + frontAndBack + { + type empty; + } +} diff --git a/flow-around-controlled-moving-cylinder/fluid-openfoam/clean.sh b/flow-around-controlled-moving-cylinder/fluid-openfoam/clean.sh new file mode 100755 index 000000000..59919cb21 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/fluid-openfoam/clean.sh @@ -0,0 +1,9 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +# since we work with a 0_orig folder here +rm -rf 0 + +clean_openfoam . diff --git a/flow-around-controlled-moving-cylinder/fluid-openfoam/constant/dynamicMeshDict b/flow-around-controlled-moving-cylinder/fluid-openfoam/constant/dynamicMeshDict new file mode 100644 index 000000000..c5a915d37 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/fluid-openfoam/constant/dynamicMeshDict @@ -0,0 +1,19 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object dynamicMeshDict; +} + +motionSolverLibs ("libfvMotionSolvers.so"); + +dynamicFvMesh dynamicMotionSolverFvMesh; + +solver displacementLaplacian; +// OpenFOAM9 or newer: rename "solver" to "motionSolver" + +displacementLaplacianCoeffs +{ + diffusivity inverseDistance 1(cylinder); +} diff --git a/flow-around-controlled-moving-cylinder/fluid-openfoam/constant/transportProperties b/flow-around-controlled-moving-cylinder/fluid-openfoam/constant/transportProperties new file mode 100644 index 000000000..69ccd8336 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/fluid-openfoam/constant/transportProperties @@ -0,0 +1,11 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object transportProperties; +} + +transportModel Newtonian; + +nu nu [ 0 2 -1 0 0 0 0 ] 1.0e-06; diff --git a/flow-around-controlled-moving-cylinder/fluid-openfoam/constant/turbulenceProperties b/flow-around-controlled-moving-cylinder/fluid-openfoam/constant/turbulenceProperties new file mode 100644 index 000000000..8271e5f76 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/fluid-openfoam/constant/turbulenceProperties @@ -0,0 +1,10 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object turbulenceProperties; +} + +simulationType laminar; diff --git a/flow-around-controlled-moving-cylinder/fluid-openfoam/run.sh b/flow-around-controlled-moving-cylinder/fluid-openfoam/run.sh new file mode 100755 index 000000000..e2a8415a0 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/fluid-openfoam/run.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh +transformPoints -scale '(0.0016 0.0016 1)' +transformPoints -translate '(0.0 0.0 -0.05)' + +rm -rf 0 +cp -r 0.orig 0 + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/flow-around-controlled-moving-cylinder/fluid-openfoam/system/blockMeshDict b/flow-around-controlled-moving-cylinder/fluid-openfoam/system/blockMeshDict new file mode 100644 index 000000000..0e2ec196f --- /dev/null +++ b/flow-around-controlled-moving-cylinder/fluid-openfoam/system/blockMeshDict @@ -0,0 +1,303 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +convertToMeters 0.1; + +vertices +( +//z=0 +//inner circle + (5 0 0) //0 + (3.535533906 3.535533906 0) //1 + (0 5 0) //2 + (-3.535533906 3.535533906 0) //3 + (-5 0 0) //4 + (-3.535533906 -3.535533906 0) //5 + (0 -5 0) //6 + (3.535533906 -3.535533906 0) //7 + +//outer circle + (30 0 0) //8 + (21.21320344 21.21320344 0) //9 + (0 30 0) //10 + (-21.21320344 21.21320344 0) //11 + (-30 0 0) //12 + (-21.21320344 -21.21320344 0) //13 + (0 -30 0) //14 + (21.21320344 -21.21320344 0) //15 + +//rectangle + (400 0 0) //16 + (400 21.21320344 0) //17 + (400 200 0) //18 + (21.21320344 200 0) //19 + (0 200 0) //20 + (-21.21320344 200 0) //21 + (-200 200 0) //22 + (-200 21.21320344 0) //23 + (-200 0 0) //24 + (-200 -21.21320344 0) //25 + (-200 -200 0) //26 + (-21.21320344 -200 0) //27 + (0 -200 0) //28 + (21.21320344 -200 0) //29 + (400 -200 0) //30 + (400 -21.21320344 0) //31 + + +//z=1 +//inner circle + (5 0 1) //32 + (3.535533906 3.535533906 1) //33 + (0 5 1) //34 + (-3.535533906 3.535533906 1) //35 + (-5 0 1) //36 + (-3.535533906 -3.535533906 1) //37 + (0 -5 1) //38 + (3.535533906 -3.535533906 1) //39 + +//outer circle + (30 0 1) //40 + (21.21320344 21.21320344 1) //41 + (0 30 1) //42 + (-21.21320344 21.21320344 1) //43 + (-30 0 1) //44 + (-21.21320344 -21.21320344 1) //45 + (0 -30 1) //46 + (21.21320344 -21.21320344 1) //47 + +//rectangle + (400 0 1) //48 + (400 21.21320344 1) //49 + (400 200 1) //50 + (21.21320344 200 1) //51 + (0 200 1) //52 + (-21.21320344 200 1) //53 + (-200 200 1) //54 + (-200 21.21320344 1) //55 + (-200 0 1) //56 + (-200 -21.21320344 1) //57 + (-200 -200 1) //58 + (-21.21320344 -200 1) //59 + (0 -200 1) //60 + (21.21320344 -200 1) //61 + (400 -200 1) //62 + (400 -21.21320344 1) //63 +); + +blocks +( + hex (1 0 8 9 33 32 40 41) (15 51 1) simpleGrading (1 8 1) //Block 0 + hex (2 1 9 10 34 33 41 42) (15 51 1) simpleGrading (1 8 1) //Block 1 + hex (3 2 10 11 35 34 42 43) (15 51 1) simpleGrading (1 8 1) //Block 2 + hex (4 3 11 12 36 35 43 44) (15 51 1) simpleGrading (1 8 1) //Block 3 + hex (5 4 12 13 37 36 44 45) (15 51 1) simpleGrading (1 8 1) //Block 4 + hex (6 5 13 14 38 37 45 46) (15 51 1) simpleGrading (1 8 1) //Block 5 + hex (7 6 14 15 39 38 46 47) (15 51 1) simpleGrading (1 8 1) //Block 6 + hex (0 7 15 8 32 39 47 40) (15 51 1) simpleGrading (1 8 1) //Block 7 + hex (8 16 17 9 40 48 49 41) (32 15 1) simpleGrading (50 1 1) //Block 8 + hex (9 17 18 19 41 49 50 51) (32 28 1) simpleGrading (50 20 1) //Block 9 + hex (10 9 19 20 42 41 51 52) (15 28 1) simpleGrading (1 20 1) //Block 10 + hex (11 10 20 21 43 42 52 53) (15 28 1) simpleGrading (1 20 1) //Block 11 + hex (23 11 21 22 55 43 53 54) (25 28 1) simpleGrading (.03 20 1) //Block 12 + hex (24 12 11 23 56 44 43 55) (25 15 1) simpleGrading (.03 1 1) //Block 13 + hex (25 13 12 24 57 45 44 56) (25 15 1) simpleGrading (.03 1 1) //Block 14 + hex (26 27 13 25 58 59 45 57) (25 28 1) simpleGrading (.03 0.05 1) //Block 15 + hex (27 28 14 13 59 60 46 45) (15 28 1) simpleGrading (1 0.05 1) //Block 16 + hex (28 29 15 14 60 61 47 46) (15 28 1) simpleGrading (1 0.05 1) //Block 17 + hex (29 30 31 15 61 62 63 47) (32 28 1) simpleGrading (50 0.05 1) //Block 18 + hex (15 31 16 8 47 63 48 40) (32 15 1) simpleGrading (50 1 1) //Block 19 +); + +edges +( + //inner cylinder surface + arc 0 1 (4 3 0) + arc 32 33 (4 3 1) + + arc 1 2 (3 4 0) + arc 33 34 (3 4 1) + + arc 2 3 (-3 4 0) + arc 34 35 (-3 4 1) + + arc 3 4 (-4 3 0) + arc 35 36 (-4 3 1) + + arc 4 5 (-4 -3 0) + arc 36 37 (-4 -3 1) + + arc 5 6 (-3 -4 0) + arc 37 38 (-3 -4 1) + + arc 6 7 (3 -4 0) + arc 38 39 (3 -4 1) + + arc 7 0 (4 -3 0) + arc 39 32 (4 -3 1) + + //outer cylinder surface + arc 8 9 (24 18 0) + arc 40 41 (24 18 1) + + arc 9 10 (18 24 0) + arc 41 42 (18 24 1) + + arc 10 11 (-18 24 0) + arc 42 43 (-18 24 1) + + arc 11 12 (-24 18 0) + arc 43 44 (-24 18 1) + + arc 12 13 (-24 -18 0) + arc 44 45 (-24 -18 1) + + arc 13 14 (-18 -24 0) + arc 45 46 (-18 -24 1) + + arc 14 15 (18 -24 0) + arc 46 47 (18 -24 1) + + arc 15 8 (24 -18 0) + arc 47 40 (24 -18 1) + +); + +boundary +( + inlet + { + type patch; + faces + ( + (22 23 55 54) + (23 24 56 55) + (24 25 57 56) + (25 26 58 57) + ); + } + + outlet + { + type patch; + faces + ( + (30 31 63 62) + (31 16 48 63) + (16 17 49 48) + (17 18 50 49) + ); + } + + topAndBottom + { + type patch; + faces + ( + (18 19 51 50) + (19 20 52 51) + (20 21 53 52) + (21 22 54 53) + + (26 27 59 58) + (27 28 60 59) + (28 29 61 60) + (29 30 62 61) + ); + } + + + cylinder + { + type wall; + faces + ( + (1 0 32 33) + (2 1 33 34) + (3 2 34 35) + (4 3 35 36) + (5 4 36 37) + (6 5 37 38) + (7 6 38 39) + (0 7 39 32) + ); + } + + frontAndBack + { + type empty; + faces + ( +//circular faces + (0 1 9 8) + (32 40 41 33) + + (1 2 10 9) + (33 41 42 34) + + (2 3 11 10) + (34 42 43 35) + + (3 4 12 11) + (35 43 44 36) + + (4 5 13 12) + (36 44 45 37) + + (5 6 14 13) + (37 45 46 38) + + (6 7 15 14) + (38 46 47 39) + + (7 0 8 15) + (39 47 40 32) + +//rectangular faces + (8 9 17 16) + (40 48 49 41) + + (9 19 18 17) + (41 49 50 51) + + (9 10 20 19) + (41 51 52 42) + + (10 11 21 20) + (42 52 53 43) + + (11 23 22 21) + (43 53 54 55) + + (11 12 24 23) + (43 55 56 44) + + (12 13 25 24) + (44 56 57 45) + + (13 27 26 25) + (45 57 58 59) + + (13 14 28 27) + (45 59 60 46) + + (14 15 29 28) + (46 60 61 47) + + (15 31 30 29) + (47 61 62 63) + + (15 8 16 31) + (47 63 48 40) + ); + } +); + +mergePatchPairs +( +); diff --git a/flow-around-controlled-moving-cylinder/fluid-openfoam/system/controlDict b/flow-around-controlled-moving-cylinder/fluid-openfoam/system/controlDict new file mode 100644 index 000000000..fd21869a4 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/fluid-openfoam/system/controlDict @@ -0,0 +1,52 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object controlDict; +} + +application pimpleFoam; + +startFrom latestTime; + +startTime 0; + +stopAt endTime; + +endTime 7; + +deltaT 0.00025; + +writeControl adjustableRunTime; + +writeInterval .5; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable no; + +adjustTimeStep no; + +maxCo 0.75; + +functions +{ + #includeFunc forces + preCICE_Adapter + { + type preciceAdapterFunctionObject; + libs ("libpreciceAdapterFunctionObject.so"); + } +} diff --git a/flow-around-controlled-moving-cylinder/fluid-openfoam/system/decomposeParDict b/flow-around-controlled-moving-cylinder/fluid-openfoam/system/decomposeParDict new file mode 100644 index 000000000..4b1bd487c --- /dev/null +++ b/flow-around-controlled-moving-cylinder/fluid-openfoam/system/decomposeParDict @@ -0,0 +1,16 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object decomposeParDict; +} + +numberOfSubdomains 4; +method simple; + +simpleCoeffs +{ + n (2 2 1); + delta 0.001; +} diff --git a/flow-around-controlled-moving-cylinder/fluid-openfoam/system/forces b/flow-around-controlled-moving-cylinder/fluid-openfoam/system/forces new file mode 100644 index 000000000..ec62b36a9 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/fluid-openfoam/system/forces @@ -0,0 +1,13 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +Description + Calculates pressure and viscous forces over specified patches for a case + where the solver is incompressible (pressure is kinematic, e.g. m^2/s^2). +\*---------------------------------------------------------------------------*/ + +#includeEtc "caseDicts/postProcessing/forces/forcesIncompressible.cfg" +log yes; +rho rhoInf; // Indicates incompressible +rhoInf 1000; // Redundant for incompressible +patches (cylinder); +CofR (0 0 0); +pitchAxis (0 0 1); diff --git a/flow-around-controlled-moving-cylinder/fluid-openfoam/system/fvSchemes b/flow-around-controlled-moving-cylinder/fluid-openfoam/system/fvSchemes new file mode 100644 index 000000000..76aabdcfe --- /dev/null +++ b/flow-around-controlled-moving-cylinder/fluid-openfoam/system/fvSchemes @@ -0,0 +1,42 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} + +ddtSchemes +{ + default backward; +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ + default none; + div(phi,U) Gauss cubic; + div((nuEff*dev(T(grad(U))))) Gauss linear; + div((nuEff*dev2(T(grad(U))))) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; + laplacian(diffusivity,cellMotionU) Gauss linear uncorrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/flow-around-controlled-moving-cylinder/fluid-openfoam/system/fvSolution b/flow-around-controlled-moving-cylinder/fluid-openfoam/system/fvSolution new file mode 100644 index 000000000..d76563980 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/fluid-openfoam/system/fvSolution @@ -0,0 +1,116 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} + +solvers +{ + pcorr + { + solver GAMG; + tolerance 0.02; + relTol 0; + smoother GaussSeidel; + nPreSweeps 0; + nPostSweeps 2; + cacheAgglomeration no; + nCellsInCoarsestLevel 10; + agglomerator faceAreaPair; + mergeLevels 1; + } + + p + { + solver GAMG; + tolerance 0; + relTol 0.01; + smoother GaussSeidel; + nPreSweeps 0; + nPostSweeps 2; + cacheAgglomeration no; + nCellsInCoarsestLevel 10; + agglomerator faceAreaPair; + mergeLevels 1; + } + + pFinal + { + $p; + tolerance 1e-06; + relTol 0; + } + + pcorrFinal + { + $pcorr; + tolerance 1e-06; + relTol 0; + } + U + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-05; + relTol 0.01; + } + + UFinal + { + $U; + tolerance 1e-05; + relTol 0; + } + + cellMotionUx + { + solver PCG; + preconditioner DIC; + tolerance 1e-08; + relTol 0; + } + cellMotionUxFinal + { + solver PCG; + preconditioner DIC; + tolerance 1e-08; + relTol 0; + } + + "cellDisplacement.*" + { + solver GAMG; + tolerance 1e-5; + relTol 0; + smoother GaussSeidel; + cacheAgglomeration true; + nCellsInCoarsestLevel 10; + agglomerator faceAreaPair; + mergeLevels 1; + } + +} + +PIMPLE +{ + correctPhi yes; + nOuterCorrectors 3; + nCorrectors 1; + nNonOrthogonalCorrectors 0; + pRefCell 1001; + pRefValue 0; +} + +relaxationFactors +{ + fields + { + } + equations + { + "U.*" 1; + } +} diff --git a/flow-around-controlled-moving-cylinder/fluid-openfoam/system/preciceDict b/flow-around-controlled-moving-cylinder/fluid-openfoam/system/preciceDict new file mode 100644 index 000000000..1185752c1 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/fluid-openfoam/system/preciceDict @@ -0,0 +1,40 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Fluid; + +modules (FSI); + +interfaces +{ + Interface1 + { + mesh Mesh-Fluid; + locations faceCenters; + patches (cylinder); + + readData + ( + Displacement-Cylinder + ); + + writeData + ( + Force + ); + }; +}; + +FSI +{ + rho rho [1 -3 0 0 0 0 0] 1000; + nu nu [ 0 2 -1 0 0 0 0 ] 1.0e-06; +} diff --git a/flow-around-controlled-moving-cylinder/images/tutorials-flow-around-controlled-moving-cylinder-precice-config.png b/flow-around-controlled-moving-cylinder/images/tutorials-flow-around-controlled-moving-cylinder-precice-config.png new file mode 100644 index 000000000..59d09d0ad Binary files /dev/null and b/flow-around-controlled-moving-cylinder/images/tutorials-flow-around-controlled-moving-cylinder-precice-config.png differ diff --git a/flow-around-controlled-moving-cylinder/images/tutorials-flow-around-controlled-moving-cylinder-setup.png b/flow-around-controlled-moving-cylinder/images/tutorials-flow-around-controlled-moving-cylinder-setup.png new file mode 100644 index 000000000..4f4568310 Binary files /dev/null and b/flow-around-controlled-moving-cylinder/images/tutorials-flow-around-controlled-moving-cylinder-setup.png differ diff --git a/flow-around-controlled-moving-cylinder/images/tutorials-flow-around-controlled-moving-cylinder-watchpoint.png b/flow-around-controlled-moving-cylinder/images/tutorials-flow-around-controlled-moving-cylinder-watchpoint.png new file mode 100644 index 000000000..3c1486c5d Binary files /dev/null and b/flow-around-controlled-moving-cylinder/images/tutorials-flow-around-controlled-moving-cylinder-watchpoint.png differ diff --git a/flow-around-controlled-moving-cylinder/plot-timeseries.py b/flow-around-controlled-moving-cylinder/plot-timeseries.py new file mode 100644 index 000000000..ad8577e27 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/plot-timeseries.py @@ -0,0 +1,64 @@ +import pandas as pd +from matplotlib import pyplot as plt +import argparse +from enum import Enum + + +class PlotType(Enum): + E_OVER_T = "error over time" + P_OVER_T = "proportional term over time" + I_OVER_T = "integral term over time" + D_OVER_T = "derivative term over time" + U1_OVER_T = "control output 1 over time" + U2_OVER_T = "control output 2 over time" + Y1_OVER_T = "control input 1 over time" + Y2_OVER_T = "control input 2 over time" + + +parser = argparse.ArgumentParser() +parser.add_argument("csvFile", help="Path to CSV file.", type=str) +parser.add_argument( + "plotType", + help="Which data should be plotted, e.g. E_OVER_T = Error over time", + type=str, + choices=[ + pt.name for pt in PlotType]) +args = parser.parse_args() + +filename = args.csvFile +split_filename = filename.split('/') +solver = split_filename[0] +if solver == ".": + solver = split_filename[1] + + +if solver == 'controller-fmi': + df = pd.read_csv(filename, delimiter=',') + if args.plotType == PlotType.E_OVER_T.name: + plt.plot(df['time'].to_numpy(), df['e'].to_numpy()) + plt.title(PlotType.E_OVER_T.value) + elif args.plotType == PlotType.P_OVER_T.name: + plt.plot(df['time'].to_numpy(), df['P'].to_numpy()) + plt.title(PlotType.P_OVER_T.value) + elif args.plotType == PlotType.I_OVER_T.name: + plt.plot(df['time'].to_numpy(), df['I'].to_numpy()) + plt.title(PlotType.I_OVER_T.value) + elif args.plotType == PlotType.D_OVER_T.name: + plt.plot(df['time'].to_numpy(), df['D'].to_numpy()) + plt.title(PlotType.D_OVER_T.value) + elif args.plotType == PlotType.U1_OVER_T.name: + plt.plot(df['time'].to_numpy(), df['u_1'].to_numpy()) + plt.title(PlotType.U1_OVER_T.value) + elif args.plotType == PlotType.U2_OVER_T.name: + plt.plot(df['time'].to_numpy(), df['u_2'].to_numpy()) + plt.title(PlotType.U2_OVER_T.value) + elif args.plotType == PlotType.Y1_OVER_T.name: + plt.plot(df['time'].to_numpy(), df['y_1'].to_numpy()) + plt.title(PlotType.Y1_OVER_T.value) + elif args.plotType == PlotType.Y2_OVER_T.name: + plt.plot(df['time'].to_numpy(), df['y_2'].to_numpy()) + plt.title(PlotType.Y2_OVER_T.value) + else: + print("Warning: Controller can not plot this value. Please type run python3 plot-timeseries.py -h to see the available commands.") + +plt.show() diff --git a/flow-around-controlled-moving-cylinder/plot-watchpoint.sh b/flow-around-controlled-moving-cylinder/plot-watchpoint.sh new file mode 100755 index 000000000..396654c7c --- /dev/null +++ b/flow-around-controlled-moving-cylinder/plot-watchpoint.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +if [ "${1:-}" = "" ]; then + echo "No target directory specified. Please specify the directory of the Solid participant containing the watchpoint, e.g. ./plot-watchpoint.sh solid-python." + exit 1 +fi + +FILE="$1/precice-Solid-watchpoint-Spring.log" + +if [ ! -f "$FILE" ]; then + echo "Unable to locate the watchpoint file (*.log) in the specified directory '${1}'. Make sure the specified directory matches the fluid or solid participant you used for the calculations." + exit 1 +fi + +gnuplot -p < + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flow-around-controlled-moving-cylinder/solid-python/clean.sh b/flow-around-controlled-moving-cylinder/solid-python/clean.sh new file mode 100755 index 000000000..9e559af3b --- /dev/null +++ b/flow-around-controlled-moving-cylinder/solid-python/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +. ../../tools/cleaning-tools.sh + +clean_precice_logs . +clean_case_logs . diff --git a/flow-around-controlled-moving-cylinder/solid-python/run.sh b/flow-around-controlled-moving-cylinder/solid-python/run.sh new file mode 100755 index 000000000..678a825eb --- /dev/null +++ b/flow-around-controlled-moving-cylinder/solid-python/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 solid.py ../precice-config.xml + +close_log diff --git a/flow-around-controlled-moving-cylinder/solid-python/solid.py b/flow-around-controlled-moving-cylinder/solid-python/solid.py new file mode 100644 index 000000000..6bbfa13f3 --- /dev/null +++ b/flow-around-controlled-moving-cylinder/solid-python/solid.py @@ -0,0 +1,105 @@ +from __future__ import division + +import argparse +import numpy as np +import precice + +parser = argparse.ArgumentParser() +parser.add_argument("configurationFileName", default="../precice-config.xml", + help="Name of the xml config file.", type=str) + +try: + args = parser.parse_args() + print(args) +except SystemExit: + print("") + print("Usage: python3 ./solverdummy.py precice-config.xml") + quit() + +# mass-spring-damper system parameters +mass = 0.03575 # kg +k_spring = 69.48 # N/m +d_damper = 0.0043 # N s/m + +state_old = np.zeros(3) +state = np.zeros(3) + + +def update(m, k, d, state, dt, force, controlled_spring_displacement): + x_old, v_old, a_old = state + x = x_old + v_old * dt + 0.5 * a_old * dt**2 + a = (force - d * v_old - k * x + k * controlled_spring_displacement) / m + v = v_old + 0.5 * (a_old + a) * dt + return np.array([x, v, a]) + + +configuration_file_name = args.configurationFileName + +participant_name = "Solid" +write_data_name = "Displacement-Cylinder" +read_data_name_force = "Force" +read_data_name_displacement = "Displacement-Spring" +mesh_name = "Mesh-Solid" + +num_vertices = 1 # Number of vertices +solver_process_index = 0 +solver_process_size = 1 + +participant = precice.Participant(participant_name, configuration_file_name, + solver_process_index, solver_process_size) + +assert (not participant.requires_mesh_connectivity_for(mesh_name)) + +dimensions = participant.get_mesh_dimensions(mesh_name) + +vertices = np.zeros((num_vertices, dimensions)) +read_data_force = np.zeros((num_vertices, dimensions)) +read_data_displacement = np.zeros((num_vertices, dimensions)) +write_data = np.zeros((num_vertices, dimensions)) + +vertex_ids = participant.set_mesh_vertices(mesh_name, vertices) + +# initialize data +if participant.requires_initial_data(): + participant.write_data(mesh_name, write_data_name, vertex_ids, write_data) + +participant.initialize() +t = 0 + +while participant.is_coupling_ongoing(): + if participant.requires_writing_checkpoint(): + print("Writing checkpoint") + state_old_cp = state_old + state_cp = state + + dt = participant.get_max_time_step_size() + + read_data_force = participant.read_data(mesh_name, read_data_name_force, vertex_ids, dt) + force = read_data_force[0, 1] + read_data_displacement = participant.read_data(mesh_name, read_data_name_displacement, vertex_ids, dt) + displacement_spring = read_data_displacement[0, 1] + + # compute next time step + state = update(mass, k_spring, d_damper, state_old, dt, force, displacement_spring) + + # cylinder is fixed in x-direction + write_data[0, 0] = 0 + + # cylinder moves in y-direction according to spring-damper-mass-equation + write_data[0, 1] = state[0] + + participant.write_data(mesh_name, write_data_name, vertex_ids, write_data) + + print("Solid: Advancing in time") + participant.advance(dt) + + if participant.requires_reading_checkpoint(): + print("Reading checkpoint") + state_old = state_old_cp + state = state_cp + + else: + state_old = state + t = t + dt + +participant.finalize() diff --git a/flow-over-heated-plate-nearest-projection/README.md b/flow-over-heated-plate-nearest-projection/README.md index 20984011c..ba671c1a1 100644 --- a/flow-over-heated-plate-nearest-projection/README.md +++ b/flow-over-heated-plate-nearest-projection/README.md @@ -25,6 +25,12 @@ Solid participant: The solvers are currently only OpenFOAM related. For information regarding the nearest-projection mapping, have a look in the [OpenFOAM configuration section](https://www.precice.org/adapter-openfoam-config.html). +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-flow-over-heated-plate-nearest-projection-precice-config.png) + ## Running the Simulation Open two separate terminals and start each participant by calling the respective run script. @@ -69,7 +75,7 @@ From the preCICE point of view, the simulation here is in 3D, as opposed to the ## Post-processing Have a look at the [flow-over heated-plate](https://www.precice.org/tutorials-flow-over-heated-plate.html) tutorial for the general aspects of post-processing. -Since we now defined mesh connectivity on our interface, we can export the coupling interface with the tag `` in our `precice-config.xml`. +Since we now defined mesh connectivity on our interface, we can export the coupling interface with the tag `` in our `precice-config.xml`. Visualizing these files (e.g. using ParaView) will show a triangular mesh, even though you use hexahedral meshes. This has nothing to do with your mesh and is just caused by the way the connectivity is defined in preCICE. As described above, the function `setMeshTriangles` is used to define the connectivity. Hence, every interface cell/face is represented by two triangles. The following image should give you an impression of a possible triangulated coupling mesh, which consists purely of hexahedral cells: ![triangulated](https://user-images.githubusercontent.com/33414590/55974257-96b07d80-5c87-11e9-9965-972b922c483d.png) diff --git a/flow-over-heated-plate-nearest-projection/fluid-openfoam/run.sh b/flow-over-heated-plate-nearest-projection/fluid-openfoam/run.sh index c191b9e48..da82a9ba2 100755 --- a/flow-over-heated-plate-nearest-projection/fluid-openfoam/run.sh +++ b/flow-over-heated-plate-nearest-projection/fluid-openfoam/run.sh @@ -1,8 +1,12 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + blockMesh -touch fluid-openfoam.foam ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/flow-over-heated-plate-nearest-projection/images/tutorials-flow-over-heated-plate-nearest-projection-precice-config.png b/flow-over-heated-plate-nearest-projection/images/tutorials-flow-over-heated-plate-nearest-projection-precice-config.png new file mode 100644 index 000000000..0980acc94 Binary files /dev/null and b/flow-over-heated-plate-nearest-projection/images/tutorials-flow-over-heated-plate-nearest-projection-precice-config.png differ diff --git a/flow-over-heated-plate-nearest-projection/precice-config.xml b/flow-over-heated-plate-nearest-projection/precice-config.xml index 017f10b79..2a5472b42 100644 --- a/flow-over-heated-plate-nearest-projection/precice-config.xml +++ b/flow-over-heated-plate-nearest-projection/precice-config.xml @@ -1,4 +1,4 @@ - + - - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + - + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/flow-over-heated-plate-nearest-projection/solid-openfoam/run.sh b/flow-over-heated-plate-nearest-projection/solid-openfoam/run.sh index 57e9395ee..da82a9ba2 100755 --- a/flow-over-heated-plate-nearest-projection/solid-openfoam/run.sh +++ b/flow-over-heated-plate-nearest-projection/solid-openfoam/run.sh @@ -1,8 +1,12 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + blockMesh -touch solid-openfoam.foam ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/flow-over-heated-plate-partitioned-flow/README.md b/flow-over-heated-plate-partitioned-flow/README.md new file mode 100644 index 000000000..d0c4f0829 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/README.md @@ -0,0 +1,81 @@ +--- +title: Flow over heated plate with partitioned flow +permalink: tutorials-flow-over-heated-plate-partitioned-flow.html +keywords: tutorial, CHT, conjugate-heat transfer, OpenFOAM, FF, flow partitioning +summary: This tutorial describes how to run a conjugate heat transfer coupled simulation using preCICE and any fluid-solid solver combination of our officially provided adapter codes. +--- + +{% note %} +Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/flow-over-heated-plate-partitioned-flow). Read how in the [tutorials introduction](https://www.precice.org/tutorials.html). +{% endnote %} + +## Setup + +The setup for this tutorial is similar to the [flow over a heated plate](https://www.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. + +The flow partitioning is done with the fluid-fluid module of the [preCICE OpenFOAM adapter](https://www.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. + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-flow-over-heated-plate-partitioned-flow-precice-config.png) + +## Available solvers + +The following participants are available: + +Fluid1 and Fluid2 participant: + +* OpenFOAM (buoyantPimpleFoam). For more information, have a look at the [OpenFOAM adapter documentation](https://www.precice.org/adapter-openfoam-overview.html). + +Solid participant: + +* OpenFOAM (laplacianFoam). For more information, have a look at the [OpenFOAM adapter documentation](https://www.precice.org/adapter-openfoam-overview.html). + +We only provide an OpenFOAM for the solid participant here, but other solvers would also work. See the standard [flow-over-heated-plate](https://precice.org/tutorials-flow-over-heated-plate.html) tutorial for other possible solid solvers. + +## Running the Simulation + +Open three separate terminals and start the OpenFOAM fluid participants and the solid participant by calling the respective run script `run.sh` located in the participant directory: + +```bash +cd fluid1-openfoam +./run.sh +``` + +and + +```bash +cd fluid2-openfoam +./run.sh +``` + +and + +```bash +cd solid-openfoam +./run.sh +``` + +## Post-processing + +Have a look at the [flow-over-heated-plate](https://www.precice.org/tutorials-flow-over-heated-plate.html) tutorial for the general aspects of post-processing. + +An example of the visualized expected results looks as follows: + +![result](images/tutorials-flow-over-heated-plate-partitioned-flow-results.png) + +Observe that the temperature at the bottom of the plate is 310K and at the inlet 300K. On the interface, the temperature is between these values. An area of higher temperature is formed above the plate, which is shifted towards the front, driven by the flow. +The below graph shows that the temperature is now coupled smoothly across both the solid-fluid and the fluid-fluid coupling interface. + +![result](images/tutorials-flow-over-heated-plate-partitioned-flow-graph.png) + +The temperature is sampled along the black line seen in the inset image. It is compared to the values obtained from the basic flow-over-heated-plate tutorial case without the additional fluid-fluid coupling. + +{% disclaimer %} +This offering is not approved or endorsed by OpenCFD Limited, producer and distributor of the OpenFOAM software via www.openfoam.com, and owner of the OPENFOAM® and OpenCFD® trade marks. +{% enddisclaimer %} diff --git a/flow-over-heated-plate-partitioned-flow/clean-tutorial.sh b/flow-over-heated-plate-partitioned-flow/clean-tutorial.sh new file mode 120000 index 000000000..4713f5092 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/clean-tutorial.sh @@ -0,0 +1 @@ +../tools/clean-tutorial-base.sh \ No newline at end of file diff --git a/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/0/T b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/0/T new file mode 100644 index 000000000..fd0100e48 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/0/T @@ -0,0 +1,46 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} + +dimensions [ 0 0 0 1 0 0 0 ]; + +internalField uniform 300; + +boundaryField +{ + interface + { + type fixedGradient; + gradient uniform 0; + } + inlet + { + type fixedValue; + value $internalField; + } + outlet + { + type fixedGradient; + gradient uniform 0; + } + top + { + type zeroGradient; + } + slip-bottom + { + type zeroGradient; + } + outerWall + { + type zeroGradient; + } + defaultFaces + { + type empty; + } +} diff --git a/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/0/U b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/0/U new file mode 100644 index 000000000..011906dca --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/0/U @@ -0,0 +1,41 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} + +dimensions [ 0 1 -1 0 0 0 0 ]; + +internalField uniform ( 0.1 0 0 ); + +boundaryField +{ + interface + { + type noSlip; + } + inlet + { + type fixedValue; + value $internalField; + } + outlet + { + type fixedGradient; + gradient uniform (0 0 0); + } + top + { + type slip; + } + slip-bottom + { + type slip; + } + defaultFaces + { + type empty; + } +} diff --git a/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/0/p b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/0/p new file mode 100644 index 000000000..bc3d18ae6 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/0/p @@ -0,0 +1,49 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p; +} + +dimensions [ 1 -1 -2 0 0 0 0 ]; + +internalField uniform 103500; + +boundaryField +{ + interface + { + type calculated; + value $internalField; + } + inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + outerWall + { + type calculated; + value $internalField; + } + top + { + type calculated; + value $internalField; + } + slip-bottom + { + type calculated; + value $internalField; + } + defaultFaces + { + type empty; + } +} diff --git a/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/0/p_rgh b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/0/p_rgh new file mode 100644 index 000000000..94db6e574 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/0/p_rgh @@ -0,0 +1,40 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p_rgh; +} + +dimensions [ 1 -1 -2 0 0 0 0 ]; + +internalField uniform 103500; + +boundaryField +{ + interface + { + type zeroGradient; + } + inlet + { + type zeroGradient; + } + outlet + { + type fixedValue; + value $internalField; + } + top + { + type zeroGradient; + } + slip-bottom + { + type zeroGradient; + } + defaultFaces + { + type empty; + } +} diff --git a/partitioned-heat-conduction/openfoam-neumann/clean.sh b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/clean.sh similarity index 87% rename from partitioned-heat-conduction/openfoam-neumann/clean.sh rename to flow-over-heated-plate-partitioned-flow/fluid1-openfoam/clean.sh index 1d4095dbf..c31d9fc76 100755 --- a/partitioned-heat-conduction/openfoam-neumann/clean.sh +++ b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/clean.sh @@ -4,4 +4,3 @@ set -e -u . ../../tools/cleaning-tools.sh clean_openfoam . -rm -rfv 0 diff --git a/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/constant/g b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/constant/g new file mode 100644 index 000000000..ca544e1f1 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/constant/g @@ -0,0 +1,10 @@ +FoamFile +{ + version 2.0; + format ascii; + class uniformDimensionedVectorField; + object g; +} + +dimensions [0 1 -2 0 0 0 0]; +value (0 -9.81 0); diff --git a/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/constant/thermophysicalProperties b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/constant/thermophysicalProperties new file mode 100644 index 000000000..7b93ee2ea --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/constant/thermophysicalProperties @@ -0,0 +1,37 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties; +} + +thermoType +{ + type heRhoThermo; + mixture pureMixture; + transport const; + thermo hConst; + equationOfState perfectGas; + specie specie; + energy sensibleEnthalpy; +} + +mixture +{ + specie + { + molWeight 24.0999; + } + thermodynamics + { + Cp 5000.0; + Hf 0; + } + transport + { + mu 0.0002; + Pr 0.01; + } +} diff --git a/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/constant/turbulenceProperties b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/constant/turbulenceProperties new file mode 100644 index 000000000..b75c49530 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/constant/turbulenceProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object turbulenceProperties; +} + +simulationType laminar; diff --git a/partitioned-heat-conduction/openfoam-neumann/run.sh b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/run.sh similarity index 60% rename from partitioned-heat-conduction/openfoam-neumann/run.sh rename to flow-over-heated-plate-partitioned-flow/fluid1-openfoam/run.sh index 78b68a942..da82a9ba2 100755 --- a/partitioned-heat-conduction/openfoam-neumann/run.sh +++ b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/run.sh @@ -1,9 +1,12 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + blockMesh -touch openfoam-neumann.foam -./setInitialField.sh ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/blockMeshDict b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/blockMeshDict new file mode 100644 index 000000000..86b05c4c3 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/blockMeshDict @@ -0,0 +1,88 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +vertices +( + (0 0 0) + (1 0 0) + (1 .5 0) + (0 .5 0) + + (0 0 .4) + (1 0 .4) + (1 .5 .4) + (0 .5 .4) + + (3 0 0) + (3 .5 0) + + (3 0 .4) + (3 .5 .4) + + (-.5 0 0) + (-.5 .5 0) + + (-.5 .5 .4) + (-.5 0 .4) +); + +blocks +( + hex (12 0 3 13 15 4 7 14) (81 41 1) simpleGrading (.2 15 1) + hex (0 1 2 3 4 5 6 7) (161 41 1) simpleGrading (5 15 1) +); + +boundary +( + + inlet + { + type wall; + faces + ( + (13 12 15 14) + ); + } + + outlet + { + type wall; + faces + ( + (1 2 6 5) + ); + } + + top + { + type wall; + faces + ( + (13 3 7 14) + (7 6 2 3) + ); + } + + slip-bottom + { + type wall; + faces + ( + (15 12 0 4) + ); + } + + interface + { + type wall; + faces + ( + (4 0 1 5) + ); + } +); diff --git a/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/controlDict b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/controlDict new file mode 100644 index 000000000..455f56484 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/controlDict @@ -0,0 +1,47 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} + +application buoyantPimpleFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 1; + +deltaT 0.01; + +writeControl runTime; + +writeInterval 0.2; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable false; + + +libs ("libpreciceAdapterFunctionObject.so"); +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + } +} diff --git a/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/decomposeParDict b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/decomposeParDict new file mode 100644 index 000000000..0d1859e14 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/decomposeParDict @@ -0,0 +1,16 @@ +FoamFile { + version 2.0; + class dictionary; + object decomposeParDict; + format ascii; +} + +numberOfSubdomains 2; + +method simple; + +simpleCoeffs +{ + n (2 1 1); + delta 0.001; +} diff --git a/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/fvSchemes b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/fvSchemes new file mode 100644 index 000000000..fd48cb5b7 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/fvSchemes @@ -0,0 +1,48 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ + default none; + div(phi,U) Gauss upwind; + div(phi,h) Gauss upwind; + div(phi,e) Gauss upwind; + div(phi,k) Gauss upwind; + div(phi,epsilon) Gauss upwind; + div(phi,R) Gauss upwind; + div(phi,K) Gauss linear; + div(phi,Ekp) Gauss linear; + div(R) Gauss linear; + div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/fvSolution b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/fvSolution new file mode 100644 index 000000000..ed6521f5e --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/fvSolution @@ -0,0 +1,55 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} + +solvers +{ + "rho.*" + { + solver PCG; + preconditioner DIC; + tolerance 0; + relTol 0; + } + + p_rgh + { + solver PCG; + preconditioner DIC; + tolerance 1e-8; + relTol 0.01; + } + + p_rghFinal + { + $p_rgh; + relTol 0; + } + + "(U|h|e|k|epsilon|R)" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-6; + relTol 0.1; + } + + "(U|h|e|k|epsilon|R)Final" + { + $U; + relTol 0; + } +} + +PIMPLE +{ + momentumPredictor yes; + nOuterCorrectors 2; + nCorrectors 2; + nNonOrthogonalCorrectors 0; +} diff --git a/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/preciceDict b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/preciceDict new file mode 100644 index 000000000..7735bf806 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid1-openfoam/system/preciceDict @@ -0,0 +1,57 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Fluid1; + +modules (CHT FF); + +interfaces +{ + Interface1 + { + mesh Fluid1-Solid-Mesh; + patches (interface); + + readData + ( + Heat-Flux + ); + + writeData + ( + Temperature-Solid + ); + }; + + Interface2 + { + mesh Fluid1-Fluid-Mesh; + patches (outlet); + + readData + ( + Pressure + VelocityGradient + FlowTemperatureGradient + ); + + writeData + ( + Velocity + FlowTemperature-Fluid + ); + }; +}; + +FF +{ + nameP p_rgh; +} diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/0/T b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/0/T new file mode 100644 index 000000000..083f4afbe --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/0/T @@ -0,0 +1,40 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} + +dimensions [0 0 0 1 0 0 0]; + +internalField uniform 300; + +boundaryField +{ + inlet + { + type fixedValue; + value $internalField; + } + outlet + { + type zeroGradient; + } + top + { + type zeroGradient; + } + bottom + { + type zeroGradient; + } + outerWall + { + type zeroGradient; + } + defaultFaces + { + type empty; + } +} diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/0/U b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/0/U new file mode 100644 index 000000000..4c90f60c1 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/0/U @@ -0,0 +1,44 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (.1 0 0); + +boundaryField +{ + inlet + { + type fixedValue; + value uniform (.1 0 0); + } + + outlet + { + type zeroGradient; + } + + top + { + type slip; + } + + bottom + { + type noSlip; + } + + defaultFaces + { + type empty; + } + +} + +// ************************************************************************* // diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/0/p b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/0/p new file mode 100644 index 000000000..c67ede5ac --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/0/p @@ -0,0 +1,50 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 103500; + +boundaryField +{ + + inlet + { + type calculated; + value $internalField; + } + + outlet + + { + type calculated; + value $internalField; + } + + top + { + type calculated; + value $internalField; + } + + bottom + { + type calculated; + value $internalField; + } + + + defaultFaces + { + type empty; + } + +} + +// ************************************************************************* // diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/0/p_rgh b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/0/p_rgh new file mode 100644 index 000000000..42fc092c2 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/0/p_rgh @@ -0,0 +1,39 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p_rgh; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 103500; + +boundaryField +{ + inlet + { + type fixedFluxExtrapolatedPressure; + } + outlet + { + type fixedValue; + value $internalField; + } + top + { + type zeroGradient; + } + bottom + { + type zeroGradient; + } + defaultFaces + { + type empty; + } +} + +// ************************************************************************* // diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/0/uniform/functionObjects/functionObjectProperties.gz b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/0/uniform/functionObjects/functionObjectProperties.gz new file mode 100644 index 000000000..438fd1519 Binary files /dev/null and b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/0/uniform/functionObjects/functionObjectProperties.gz differ diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/clean.sh b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/clean.sh new file mode 100755 index 000000000..c31d9fc76 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/constant/g b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/constant/g new file mode 100644 index 000000000..ca544e1f1 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/constant/g @@ -0,0 +1,10 @@ +FoamFile +{ + version 2.0; + format ascii; + class uniformDimensionedVectorField; + object g; +} + +dimensions [0 1 -2 0 0 0 0]; +value (0 -9.81 0); diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/constant/thermophysicalProperties b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/constant/thermophysicalProperties new file mode 100644 index 000000000..7b93ee2ea --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/constant/thermophysicalProperties @@ -0,0 +1,37 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties; +} + +thermoType +{ + type heRhoThermo; + mixture pureMixture; + transport const; + thermo hConst; + equationOfState perfectGas; + specie specie; + energy sensibleEnthalpy; +} + +mixture +{ + specie + { + molWeight 24.0999; + } + thermodynamics + { + Cp 5000.0; + Hf 0; + } + transport + { + mu 0.0002; + Pr 0.01; + } +} diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/constant/turbulenceProperties b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/constant/turbulenceProperties new file mode 100644 index 000000000..b75c49530 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/constant/turbulenceProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object turbulenceProperties; +} + +simulationType laminar; diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/run.sh b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/run.sh new file mode 100755 index 000000000..da82a9ba2 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/run.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/blockMeshDict b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/blockMeshDict new file mode 100755 index 000000000..0d0de2011 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/blockMeshDict @@ -0,0 +1,77 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +vertices +( + (0 0 0) + (1 0 0) + (1 .5 0) + (0 .5 0) + + (0 0 .4) + (1 0 .4) + (1 .5 .4) + (0 .5 .4) + + (3 0 0) + (3 .5 0) + + (3 0 .4) + (3 .5 .4) + + (-.5 0 0) + (-.5 .5 0) + + (-.5 .5 .4) + (-.5 0 .4) +); + +blocks +( + hex (1 8 9 2 5 10 11 6) (51 41 1) simpleGrading (1 15 1) +); + +boundary +( + + inlet + { + type wall; + faces + ( + (2 1 6 5) + ); + } + + outlet + { + type wall; + faces + ( + (8 9 11 10) + ); + } + + top + { + type wall; + faces + ( + (9 2 6 11) + ); + } + + bottom + { + type wall; + faces + ( + (1 8 10 5) + ); + } +); diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/controlDict b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/controlDict new file mode 100644 index 000000000..455f56484 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/controlDict @@ -0,0 +1,47 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} + +application buoyantPimpleFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 1; + +deltaT 0.01; + +writeControl runTime; + +writeInterval 0.2; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable false; + + +libs ("libpreciceAdapterFunctionObject.so"); +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + } +} diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/decomposeParDict b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/decomposeParDict new file mode 100644 index 000000000..0d1859e14 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/decomposeParDict @@ -0,0 +1,16 @@ +FoamFile { + version 2.0; + class dictionary; + object decomposeParDict; + format ascii; +} + +numberOfSubdomains 2; + +method simple; + +simpleCoeffs +{ + n (2 1 1); + delta 0.001; +} diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/fvSchemes b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/fvSchemes new file mode 100644 index 000000000..fd48cb5b7 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/fvSchemes @@ -0,0 +1,48 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ + default none; + div(phi,U) Gauss upwind; + div(phi,h) Gauss upwind; + div(phi,e) Gauss upwind; + div(phi,k) Gauss upwind; + div(phi,epsilon) Gauss upwind; + div(phi,R) Gauss upwind; + div(phi,K) Gauss linear; + div(phi,Ekp) Gauss linear; + div(R) Gauss linear; + div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/fvSolution b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/fvSolution new file mode 100644 index 000000000..cbdd5b679 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/fvSolution @@ -0,0 +1,89 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + "rho.*" + { + solver PCG; + preconditioner DIC; + tolerance 0; + relTol 0; + } + + p_rgh + { + solver PCG; + preconditioner DIC; + tolerance 1e-8; + relTol 0.01; + } + + p_rghFinal + { + $p_rgh; + relTol 0; + } + + "(U|e|k|epsilon|R)" + { + solver PBiCG; + preconditioner DILU; + tolerance 1e-6; + relTol 0.1; + } + + "(U|e|k|epsilon|R)Final" + { + $U; + relTol 0; + } + + h + { + solver PBiCG; + preconditioner DILU; + tolerance 1e-6; + relTol 0; + } + + hFinal + { + $h; + relTol 0; + } + + +} + + +PIMPLE +{ + nCorrectors 2; + nNonOrthogonalCorrectors 0; + momentumPredictor true; + nOuterCorrectors 2; +} + + +/*relaxationFactors +{ + fields + { + p_rgh 0.3; + } + equations + { + U 0.7; + h 0.99; + } +}*/ + +// ************************************************************************* // diff --git a/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/preciceDict b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/preciceDict new file mode 100644 index 000000000..9c705a03f --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/fluid2-openfoam/system/preciceDict @@ -0,0 +1,43 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Fluid2; + +modules (FF); + +interfaces +{ + Interface1 + { + mesh Fluid2-Mesh; + patches (inlet); + + readData + ( + Velocity + FlowTemperature-Fluid + // PressureGradient + + ); + + writeData + ( + Pressure + VelocityGradient + FlowTemperatureGradient + ); + }; +}; + +FF +{ + nameP p_rgh; +} diff --git a/flow-over-heated-plate-partitioned-flow/images/tutorials-flow-over-heated-plate-partitioned-flow-graph.png b/flow-over-heated-plate-partitioned-flow/images/tutorials-flow-over-heated-plate-partitioned-flow-graph.png new file mode 100644 index 000000000..1407d79d3 Binary files /dev/null and b/flow-over-heated-plate-partitioned-flow/images/tutorials-flow-over-heated-plate-partitioned-flow-graph.png differ diff --git a/flow-over-heated-plate-partitioned-flow/images/tutorials-flow-over-heated-plate-partitioned-flow-precice-config.png b/flow-over-heated-plate-partitioned-flow/images/tutorials-flow-over-heated-plate-partitioned-flow-precice-config.png new file mode 100644 index 000000000..0b033158a Binary files /dev/null and b/flow-over-heated-plate-partitioned-flow/images/tutorials-flow-over-heated-plate-partitioned-flow-precice-config.png differ diff --git a/flow-over-heated-plate-partitioned-flow/images/tutorials-flow-over-heated-plate-partitioned-flow-results.png b/flow-over-heated-plate-partitioned-flow/images/tutorials-flow-over-heated-plate-partitioned-flow-results.png new file mode 100644 index 000000000..9e4774e91 Binary files /dev/null and b/flow-over-heated-plate-partitioned-flow/images/tutorials-flow-over-heated-plate-partitioned-flow-results.png differ diff --git a/flow-over-heated-plate-partitioned-flow/precice-config.xml b/flow-over-heated-plate-partitioned-flow/precice-config.xml new file mode 100644 index 000000000..9e60b3b28 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/precice-config.xml @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flow-over-heated-plate-partitioned-flow/solid-openfoam/0/T b/flow-over-heated-plate-partitioned-flow/solid-openfoam/0/T new file mode 100644 index 000000000..c2c16a1d9 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/solid-openfoam/0/T @@ -0,0 +1,37 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} + +dimensions [0 0 0 1 0 0 0]; + +internalField uniform 310; + +boundaryField +{ + interface + { + type fixedValue; + value $internalField; + } + left + { + type zeroGradient; + } + right + { + type zeroGradient; + } + bottom + { + type fixedValue; + value $internalField; + } + defaultFaces + { + type empty; + } +} diff --git a/flow-over-heated-plate-partitioned-flow/solid-openfoam/clean.sh b/flow-over-heated-plate-partitioned-flow/solid-openfoam/clean.sh new file mode 100755 index 000000000..c31d9fc76 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/solid-openfoam/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . diff --git a/flow-over-heated-plate-partitioned-flow/solid-openfoam/constant/transportProperties b/flow-over-heated-plate-partitioned-flow/solid-openfoam/constant/transportProperties new file mode 100644 index 000000000..40dc0a36b --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/solid-openfoam/constant/transportProperties @@ -0,0 +1,10 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object transportProperties; +} + +DT DT [ 0 2 -1 0 0 0 0 ] 1; diff --git a/flow-over-heated-plate-partitioned-flow/solid-openfoam/run.sh b/flow-over-heated-plate-partitioned-flow/solid-openfoam/run.sh new file mode 100755 index 000000000..da82a9ba2 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/solid-openfoam/run.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/blockMeshDict b/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/blockMeshDict new file mode 100644 index 000000000..5149926c5 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/blockMeshDict @@ -0,0 +1,76 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +vertices +( + + (0 -.25 0) + (1 -.25 0) + (1 0 0) + (0 0 0) + + (0 -.25 .4) + (1 -.25 .4) + (1 0 .4) + (0 0 .4) + +); + +blocks +( + hex (0 1 2 3 4 5 6 7) (32 16 1) simpleGrading (1 1 1) +); + +edges +( +); + +boundary +( + + left + { + type wall; + faces + ( + (4 7 3 0) + ); + } + + right + { + type wall; + faces + ( + (1 2 6 5) + ); + } + + interface + { + type wall; + faces + ( + (7 6 2 3) + ); + } + + bottom + { + type wall; + faces + ( + (4 0 1 5) + ); + } + +); + +mergePatchPairs +( +); diff --git a/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/controlDict b/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/controlDict new file mode 100644 index 000000000..23d0cbfe2 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/controlDict @@ -0,0 +1,48 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object controlDict; +} + +application laplacianFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 1; + +deltaT 0.01; + +writeControl runTime; + +writeInterval 0.2; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable false; + + +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + libs ("libpreciceAdapterFunctionObject.so"); + } +} diff --git a/partitioned-heat-conduction/openfoam-dirichlet/system/decomposeParDict b/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/decomposeParDict similarity index 100% rename from partitioned-heat-conduction/openfoam-dirichlet/system/decomposeParDict rename to flow-over-heated-plate-partitioned-flow/solid-openfoam/system/decomposeParDict diff --git a/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/fvSchemes b/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/fvSchemes new file mode 100644 index 000000000..528752472 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/fvSchemes @@ -0,0 +1,40 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; + grad(T) Gauss linear; +} + +divSchemes +{ + default none; +} + +laplacianSchemes +{ + default none; + laplacian(DT,T) Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/partitioned-heat-conduction/openfoam-dirichlet/system/fvSolution b/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/fvSolution similarity index 92% rename from partitioned-heat-conduction/openfoam-dirichlet/system/fvSolution rename to flow-over-heated-plate-partitioned-flow/solid-openfoam/system/fvSolution index 30a932586..86a2ab7f1 100644 --- a/partitioned-heat-conduction/openfoam-dirichlet/system/fvSolution +++ b/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/fvSolution @@ -3,6 +3,7 @@ FoamFile version 2.0; format ascii; class dictionary; + location "system"; object fvSolution; } diff --git a/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/preciceDict b/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/preciceDict new file mode 100644 index 000000000..e11313a14 --- /dev/null +++ b/flow-over-heated-plate-partitioned-flow/solid-openfoam/system/preciceDict @@ -0,0 +1,39 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Solid; + +modules (CHT); + +interfaces +{ + Interface1 + { + mesh Solid-Mesh; + patches (interface); + + readData + ( + Temperature-Solid + ); + + writeData + ( + Heat-Flux + ); + }; +}; + +CHT +{ + k [ 1 1 -3 -1 0 0 0 ] 100; + solverType "basic"; +}; diff --git a/flow-over-heated-plate-steady-state/README.md b/flow-over-heated-plate-steady-state/README.md index d2cb3dfdd..3165bb094 100644 --- a/flow-over-heated-plate-steady-state/README.md +++ b/flow-over-heated-plate-steady-state/README.md @@ -17,6 +17,12 @@ The setup for this tutorial is similar to the [flow over a heated plate](https:/ This is a pseudo-2D case, but we still set a 3D `solver-interface` in `precice-config.xml`, because the code_aster case is set up like this at the moment. Contributions here are particularly welcome! {% endnote %} +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-flow-over-heated-plate-steady-state-precice-config.png) + ## Available solvers Fluid participant: diff --git a/flow-over-heated-plate-steady-state/fluid-openfoam/run.sh b/flow-over-heated-plate-steady-state/fluid-openfoam/run.sh index c191b9e48..da82a9ba2 100755 --- a/flow-over-heated-plate-steady-state/fluid-openfoam/run.sh +++ b/flow-over-heated-plate-steady-state/fluid-openfoam/run.sh @@ -1,8 +1,12 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + blockMesh -touch fluid-openfoam.foam ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/flow-over-heated-plate-steady-state/fluid-openfoam/system/controlDict b/flow-over-heated-plate-steady-state/fluid-openfoam/system/controlDict index f13daf050..b5c9b5298 100644 --- a/flow-over-heated-plate-steady-state/fluid-openfoam/system/controlDict +++ b/flow-over-heated-plate-steady-state/fluid-openfoam/system/controlDict @@ -14,7 +14,7 @@ startTime 0; stopAt endTime; -endTime 1000; +endTime 100; deltaT 1; diff --git a/flow-over-heated-plate-steady-state/images/tutorials-flow-over-heated-plate-steady-state-precice-config.png b/flow-over-heated-plate-steady-state/images/tutorials-flow-over-heated-plate-steady-state-precice-config.png new file mode 100644 index 000000000..efc74f4c0 Binary files /dev/null and b/flow-over-heated-plate-steady-state/images/tutorials-flow-over-heated-plate-steady-state-precice-config.png differ diff --git a/flow-over-heated-plate-steady-state/precice-config.xml b/flow-over-heated-plate-steady-state/precice-config.xml index 28d57303f..abddf50aa 100644 --- a/flow-over-heated-plate-steady-state/precice-config.xml +++ b/flow-over-heated-plate-steady-state/precice-config.xml @@ -7,87 +7,81 @@ enabled="true" /> - - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - + + - - - - - - - - - - + + + + + + + + + diff --git a/flow-over-heated-plate-steady-state/solid-codeaster/run.sh b/flow-over-heated-plate-steady-state/solid-codeaster/run.sh index 0af4b021f..e3075712b 100755 --- a/flow-over-heated-plate-steady-state/solid-codeaster/run.sh +++ b/flow-over-heated-plate-steady-state/solid-codeaster/run.sh @@ -1,6 +1,9 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + echo "Warning: this case requires a manual preparation step for code_aster." echo "You also need to set an absolute path as exchange-directory in precice-config.xml." echo "See the tutorial and code_aster adapter documentation pages for more:" @@ -10,3 +13,5 @@ echo "" export TUTORIAL_ROOT="${PWD}" export PRECICE_PARTICIPANT=Solid as_run --run solid.export + +close_log diff --git a/flow-over-heated-plate-two-meshes/README.md b/flow-over-heated-plate-two-meshes/README.md new file mode 100644 index 000000000..8fe5fa1dc --- /dev/null +++ b/flow-over-heated-plate-two-meshes/README.md @@ -0,0 +1,60 @@ +--- +title: Flow over heated plate with two meshes +permalink: tutorials-flow-over-heated-plate-two-meshes.html +keywords: tutorial, CHT, conjugate-heat transfer, OpenFOAM, CalculiX +summary: This tutorial describes how to run a conjugate heat transfer coupled simulation using preCICE and CalculiX as solid solver, which requires two meshes instead of one. +--- + + +{% note %} +Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/flow-over-heated-plate-calculix). Read how in the [tutorials introduction](https://www.precice.org/tutorials.html). +{% endnote %} + +## Setup + +The scenario is exactly the same as the one described in the [flow over heated plate tutorial](https://precice.org/tutorials-flow-over-heated-plate.html). However, this tutorial is specialized for the case when heat fluxes and temperatures live on different meshes. This is the case with CalculiX: heat fluxes are written on face centers, while temperatures are read on nodes. This requires updating the `precice-config.xml` file to take this into account. On the fluid side, a single mesh can still be used. + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-flow-over-heated-plate-two-meshes-precice-config.png) + +## Available solvers + +By default, the fluid participant reads heat-flux values and the solid participant reads temperature values for the coupled simulation. The following participants are available: + +Fluid participant: + +* OpenFOAM (buoyantPimpleFoam). For more information, have a look at the [OpenFOAM adapter documentation](https://www.precice.org/adapter-openfoam-overview.html). +* SU2 (copy the `fluid-su2` directory from the `flow-over-heated-plate` tutorial as-is). For more information, have a look at the [SU2 adapter docmentation](https://www.precice.org/adapter-su2.html). + +Solid participant: + +* CalculiX. For more information, have a look at the [CalculiX adapter documentation](https://precice.org/adapter-calculix-overview.html). Be sure to use at least version 2.19.1 of the adapter. + +## Running the Simulation + +Open two separate terminals and start the desired fluid and solid participant by calling the respective run script `run.sh` located in the participant directory. For example: + +```bash +cd fluid-openfoam +./run.sh +``` + +and + +```bash +cd solid-calculix +./run.sh +``` + +## Post-processing + +On the OpenFOAM side, you can open the `.foam` file with ParaView, or create VTK files with `foamToVTK`. CalculiX outputs `.frd` files which can be opened with `cgx` or converted into VTK files using the converter available in the adapter repository. + +CalculiX produces 1000 result files, which one can then synchronize with OpenFOAM using the "Temporal Shift Scale" filter on the CalculiX results, using a scale of 0.01. This is because CalculiX considers that each time window (of length 0.01 by default) is one time step, and increases the total time by 1 in the VTK files. Since the two datasets use different data names for temperature, just use the same scale for temperature on both outputs (from 300K to 310K, which should be the minimum and maximum values in this setup). Alternatively, apply a "Calculator" filter on the CalculiX results, creating a variable `T` as a point data field with values from `NDTEMP_T`, and then group the two data sets. + +{% disclaimer %} +This offering is not approved or endorsed by OpenCFD Limited, producer and distributor of the OpenFOAM software via www.openfoam.com, and owner of the OPENFOAM® and OpenCFD® trade marks. +{% enddisclaimer %} diff --git a/flow-over-heated-plate-two-meshes/clean-tutorial.sh b/flow-over-heated-plate-two-meshes/clean-tutorial.sh new file mode 120000 index 000000000..4713f5092 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/clean-tutorial.sh @@ -0,0 +1 @@ +../tools/clean-tutorial-base.sh \ No newline at end of file diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/0/T b/flow-over-heated-plate-two-meshes/fluid-openfoam/0/T new file mode 100644 index 000000000..abf1bce54 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/0/T @@ -0,0 +1,49 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} + +dimensions [ 0 0 0 1 0 0 0 ]; + +internalField uniform 300; + +boundaryField +{ + interface + { + type fixedGradient; + gradient uniform 0; + } + inlet + { + type fixedValue; + value $internalField; + } + outlet + { + type zeroGradient; + } + top + { + type zeroGradient; + } + bottom + { + type zeroGradient; + } + slip-bottom + { + type zeroGradient; + } + outerWall + { + type zeroGradient; + } + defaultFaces + { + type empty; + } +} diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/0/U b/flow-over-heated-plate-two-meshes/fluid-openfoam/0/U new file mode 100644 index 000000000..cfe775cf3 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/0/U @@ -0,0 +1,44 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} + +dimensions [ 0 1 -1 0 0 0 0 ]; + +internalField uniform ( 0.1 0 0 ); + +boundaryField +{ + interface + { + type noSlip; + } + inlet + { + type fixedValue; + value $internalField; + } + outlet + { + type zeroGradient; + } + top + { + type slip; + } + bottom + { + type noSlip; + } + slip-bottom + { + type slip; + } + defaultFaces + { + type empty; + } +} diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/0/alphat b/flow-over-heated-plate-two-meshes/fluid-openfoam/0/alphat new file mode 100644 index 000000000..1d3ac72d0 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/0/alphat @@ -0,0 +1,49 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object alphat; +} + +dimensions [ 1 -1 -1 0 0 0 0 ]; + +internalField uniform 0; + +boundaryField +{ + interface + { + type compressible::alphatWallFunction; + value uniform 0; + } + inlet + { + type compressible::alphatWallFunction; + value uniform 0; + } + outlet + { + type compressible::alphatWallFunction; + value uniform 0; + } + top + { + type compressible::alphatWallFunction; + value uniform 0; + } + bottom + { + type compressible::alphatWallFunction; + value uniform 0; + } + slip-bottom + { + type compressible::alphatWallFunction; + value uniform 0; + } + defaultFaces + { + type empty; + } +} diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/0/epsilon b/flow-over-heated-plate-two-meshes/fluid-openfoam/0/epsilon new file mode 100644 index 000000000..c419576fc --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/0/epsilon @@ -0,0 +1,49 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object epsilon; +} + +dimensions [ 0 2 -3 0 0 0 0 ]; + +internalField uniform 0.01; + +boundaryField +{ + interface + { + type epsilonWallFunction; + value uniform 0.01; + } + inlet + { + type epsilonWallFunction; + value uniform 0.01; + } + outlet + { + type epsilonWallFunction; + value uniform 0.01; + } + top + { + type epsilonWallFunction; + value uniform 0.01; + } + bottom + { + type epsilonWallFunction; + value uniform 0.01; + } + slip-bottom + { + type epsilonWallFunction; + value uniform 0.01; + } + defaultFaces + { + type empty; + } +} diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/0/k b/flow-over-heated-plate-two-meshes/fluid-openfoam/0/k new file mode 100644 index 000000000..a09c9617c --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/0/k @@ -0,0 +1,49 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object k; +} + +dimensions [ 0 2 -2 0 0 0 0 ]; + +internalField uniform 0.1; + +boundaryField +{ + interface + { + type kqRWallFunction; + value uniform 0.1; + } + inlet + { + type kqRWallFunction; + value uniform 0.1; + } + outlet + { + type kqRWallFunction; + value uniform 0.1; + } + top + { + type kqRWallFunction; + value uniform 0.1; + } + slip-bottom + { + type kqRWallFunction; + value uniform 0.1; + } + bottom + { + type kqRWallFunction; + value uniform 0.1; + } + defaultFaces + { + type empty; + } +} diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/0/nut b/flow-over-heated-plate-two-meshes/fluid-openfoam/0/nut new file mode 100644 index 000000000..580e908d7 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/0/nut @@ -0,0 +1,49 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object nut; +} + +dimensions [ 0 2 -1 0 0 0 0 ]; + +internalField uniform 0; + +boundaryField +{ + interface + { + type nutkWallFunction; + value uniform 0; + } + inlet + { + type nutkWallFunction; + value uniform 0; + } + outlet + { + type nutkWallFunction; + value uniform 0; + } + top + { + type nutkWallFunction; + value uniform 0; + } + bottom + { + type nutkWallFunction; + value uniform 0; + } + slip-bottom + { + type nutkWallFunction; + value uniform 0; + } + defaultFaces + { + type empty; + } +} diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/0/p b/flow-over-heated-plate-two-meshes/fluid-openfoam/0/p new file mode 100644 index 000000000..654bb4023 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/0/p @@ -0,0 +1,54 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p; +} + +dimensions [ 1 -1 -2 0 0 0 0 ]; + +internalField uniform 103500; + +boundaryField +{ + interface + { + type calculated; + value $internalField; + } + inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + outerWall + { + type calculated; + value $internalField; + } + top + { + type calculated; + value $internalField; + } + bottom + { + type calculated; + value $internalField; + } + slip-bottom + { + type calculated; + value $internalField; + } + defaultFaces + { + type empty; + } +} diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/0/p_rgh b/flow-over-heated-plate-two-meshes/fluid-openfoam/0/p_rgh new file mode 100644 index 000000000..c5eebe883 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/0/p_rgh @@ -0,0 +1,44 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p_rgh; +} + +dimensions [ 1 -1 -2 0 0 0 0 ]; + +internalField uniform 103500; + +boundaryField +{ + interface + { + type zeroGradient; + } + inlet + { + type zeroGradient; + } + outlet + { + type fixedValue; + value $internalField; + } + top + { + type zeroGradient; + } + slip-bottom + { + type zeroGradient; + } + bottom + { + type zeroGradient; + } + defaultFaces + { + type empty; + } +} diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/clean.sh b/flow-over-heated-plate-two-meshes/fluid-openfoam/clean.sh new file mode 100755 index 000000000..c31d9fc76 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/constant/g b/flow-over-heated-plate-two-meshes/fluid-openfoam/constant/g new file mode 100644 index 000000000..ca544e1f1 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/constant/g @@ -0,0 +1,10 @@ +FoamFile +{ + version 2.0; + format ascii; + class uniformDimensionedVectorField; + object g; +} + +dimensions [0 1 -2 0 0 0 0]; +value (0 -9.81 0); diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/constant/thermophysicalProperties b/flow-over-heated-plate-two-meshes/fluid-openfoam/constant/thermophysicalProperties new file mode 100644 index 000000000..7b93ee2ea --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/constant/thermophysicalProperties @@ -0,0 +1,37 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties; +} + +thermoType +{ + type heRhoThermo; + mixture pureMixture; + transport const; + thermo hConst; + equationOfState perfectGas; + specie specie; + energy sensibleEnthalpy; +} + +mixture +{ + specie + { + molWeight 24.0999; + } + thermodynamics + { + Cp 5000.0; + Hf 0; + } + transport + { + mu 0.0002; + Pr 0.01; + } +} diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/constant/turbulenceProperties b/flow-over-heated-plate-two-meshes/fluid-openfoam/constant/turbulenceProperties new file mode 100644 index 000000000..b75c49530 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/constant/turbulenceProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object turbulenceProperties; +} + +simulationType laminar; diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/run.sh b/flow-over-heated-plate-two-meshes/fluid-openfoam/run.sh new file mode 100755 index 000000000..da82a9ba2 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/run.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/system/blockMeshDict b/flow-over-heated-plate-two-meshes/fluid-openfoam/system/blockMeshDict new file mode 100644 index 000000000..de95b0ace --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/system/blockMeshDict @@ -0,0 +1,101 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +vertices +( + (0 0 0) + (1 0 0) + (1 .5 0) + (0 .5 0) + + (0 0 .4) + (1 0 .4) + (1 .5 .4) + (0 .5 .4) + + (3 0 0) + (3 .5 0) + + (3 0 .4) + (3 .5 .4) + + (-.5 0 0) + (-.5 .5 0) + + (-.5 .5 .4) + (-.5 0 .4) + +); + +blocks +( + hex (12 0 3 13 15 4 7 14) (81 41 1) simpleGrading (.2 15 1) + hex (0 1 2 3 4 5 6 7) (161 41 1) simpleGrading (5 15 1) + hex (1 8 9 2 5 10 11 6) (51 41 1) simpleGrading (1 15 1) +); + +boundary +( + + inlet + { + type wall; + faces + ( + (13 12 15 14) + ); + } + + outlet + { + type wall; + faces + ( + (8 9 11 10) + ); + } + + top + { + type wall; + faces + ( + (7 6 2 3) + (9 2 6 11) + (13 3 7 14) + ); + } + + slip-bottom + { + type wall; + faces + ( + (15 12 0 4) + ); + } + + bottom + { + type wall; + faces + ( + (1 8 10 5) + ); + } + + interface + { + type wall; + faces + ( + (4 0 1 5) + ); + } + +); diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/system/controlDict b/flow-over-heated-plate-two-meshes/fluid-openfoam/system/controlDict new file mode 100644 index 000000000..65ef4eb73 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/system/controlDict @@ -0,0 +1,46 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} + +application buoyantPimpleFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 1; + +deltaT 0.01; + +writeControl runTime; + +writeInterval 0.01; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable false; + +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + libs ("libpreciceAdapterFunctionObject.so"); + } +} diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/system/decomposeParDict b/flow-over-heated-plate-two-meshes/fluid-openfoam/system/decomposeParDict new file mode 100644 index 000000000..0d1859e14 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/system/decomposeParDict @@ -0,0 +1,16 @@ +FoamFile { + version 2.0; + class dictionary; + object decomposeParDict; + format ascii; +} + +numberOfSubdomains 2; + +method simple; + +simpleCoeffs +{ + n (2 1 1); + delta 0.001; +} diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/system/fvSchemes b/flow-over-heated-plate-two-meshes/fluid-openfoam/system/fvSchemes new file mode 100644 index 000000000..fd48cb5b7 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/system/fvSchemes @@ -0,0 +1,48 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ + default none; + div(phi,U) Gauss upwind; + div(phi,h) Gauss upwind; + div(phi,e) Gauss upwind; + div(phi,k) Gauss upwind; + div(phi,epsilon) Gauss upwind; + div(phi,R) Gauss upwind; + div(phi,K) Gauss linear; + div(phi,Ekp) Gauss linear; + div(R) Gauss linear; + div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/system/fvSolution b/flow-over-heated-plate-two-meshes/fluid-openfoam/system/fvSolution new file mode 100644 index 000000000..e7047fa96 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/system/fvSolution @@ -0,0 +1,55 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} + +solvers +{ + "rho.*" + { + solver PCG; + preconditioner DIC; + tolerance 0; + relTol 0; + } + + p_rgh + { + solver PCG; + preconditioner DIC; + tolerance 1e-8; + relTol 0.01; + } + + p_rghFinal + { + $p_rgh; + relTol 0; + } + + "(U|h|e|k|epsilon|R)" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-6; + relTol 0.1; + } + + "(U|h|e|k|epsilon|R)Final" + { + $U; + relTol 0; + } +} + +PIMPLE +{ + momentumPredictor yes; + nOuterCorrectors 1; + nCorrectors 2; + nNonOrthogonalCorrectors 0; +} diff --git a/flow-over-heated-plate-two-meshes/fluid-openfoam/system/preciceDict b/flow-over-heated-plate-two-meshes/fluid-openfoam/system/preciceDict new file mode 100644 index 000000000..be3dc807c --- /dev/null +++ b/flow-over-heated-plate-two-meshes/fluid-openfoam/system/preciceDict @@ -0,0 +1,33 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Fluid; + +modules (CHT); + +interfaces +{ + Interface1 + { + mesh Fluid-Mesh; + patches (interface); + + readData + ( + Heat-Flux + ); + + writeData + ( + Temperature + ); + }; +}; diff --git a/flow-over-heated-plate-two-meshes/images/tutorials-flow-over-heated-plate-two-meshes-precice-config.png b/flow-over-heated-plate-two-meshes/images/tutorials-flow-over-heated-plate-two-meshes-precice-config.png new file mode 100644 index 000000000..e5ea5b185 Binary files /dev/null and b/flow-over-heated-plate-two-meshes/images/tutorials-flow-over-heated-plate-two-meshes-precice-config.png differ diff --git a/flow-over-heated-plate-two-meshes/precice-config.xml b/flow-over-heated-plate-two-meshes/precice-config.xml new file mode 100644 index 000000000..738e6f8ec --- /dev/null +++ b/flow-over-heated-plate-two-meshes/precice-config.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flow-over-heated-plate-two-meshes/solid-calculix/.gitignore b/flow-over-heated-plate-two-meshes/solid-calculix/.gitignore new file mode 100644 index 000000000..6be26c1d3 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/solid-calculix/.gitignore @@ -0,0 +1 @@ +all.msh diff --git a/flow-over-heated-plate-two-meshes/solid-calculix/clean.sh b/flow-over-heated-plate-two-meshes/solid-calculix/clean.sh new file mode 100755 index 000000000..e9fdde0e3 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/solid-calculix/clean.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_calculix . +rm -fv all.msh # The mesh is generated by generate_mesh.py in this case diff --git a/flow-over-heated-plate-two-meshes/solid-calculix/config.yml b/flow-over-heated-plate-two-meshes/solid-calculix/config.yml new file mode 100644 index 000000000..5d28dae98 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/solid-calculix/config.yml @@ -0,0 +1,12 @@ +participants: + Solid: + interfaces: + - nodes-mesh: Solid-Mesh-nodes + patch: yend + read-data: [Temperature] + - faces-mesh: Solid-Mesh + patch: flux_interface + write-data: [Heat-Flux] + + +precice-config-file: ../precice-config.xml diff --git a/flow-over-heated-plate-two-meshes/solid-calculix/generate_mesh.py b/flow-over-heated-plate-two-meshes/solid-calculix/generate_mesh.py new file mode 100644 index 000000000..89962f22d --- /dev/null +++ b/flow-over-heated-plate-two-meshes/solid-calculix/generate_mesh.py @@ -0,0 +1,88 @@ +import numpy as np + +# Output, geometric parameters +output_file_name = "out.msh" + +x_begin, x_end = 0, 1 +y_begin, y_end = -0.25, 0 +z_begin, z_end = 0, 0.4 + +# Number of elements. Add one for number of nodes! +n_x, n_y, n_z = 400, 50, 1 + +# Coordinates in (i, j, k) space. i = 0, ..., n_x etc +xs = np.linspace(x_begin, x_end, n_x + 1) +ys = np.linspace(y_begin, y_end, n_y + 1) +zs = np.linspace(z_begin, z_end, n_z + 1) + +# List of 3D points +nodes = [] +# Map from (i,j,k) pos to index +indices = dict() + +# Build nodes +for i in range(0, n_x + 1): + for j in range(0, n_y + 1): + for k in range(0, n_z + 1): + nodes.append((xs[i], ys[j], zs[k])) + # CCX index starts at 1! + v = len(nodes) + indices[(i, j, k)] = v + 1 + +print("** Nodes") +print("*Node, NSET=Nall") +for v, (x, y, z) in enumerate(nodes): + print("{}, {:10.4f}, {:10.4f}, {:10.4f},".format(v + 2, x, y, z)) + +# Build elements +print("** Volume elements") +print("* Element, TYPE=C3D8, ELSET=Evolumes") + +elems_top_surface = [] + +elem_id = 1 +for i in range(0, n_x): + for j in range(0, n_y): + for k in range(0, n_z): + print("{}, {}, {}, {}, {}, {}, {}, {}, {},".format(elem_id, + indices[( + i, j, k)], + indices[( + i + 1, j, k)], + indices[( + i + 1, j + 1, k)], + indices[( + i, j + 1, k)], + indices[( + i, j, k + 1)], + indices[( + i + 1, j, k + 1)], + indices[( + i + 1, j + 1, k + 1)], + indices[(i, j + 1, k + 1)],)) + if j == n_y - 1: + elems_top_surface.append(elem_id) + elem_id += 1 + + +# Set of border. Adapt freely +print("** Nodes, border with y = y_end") +print("*NSET, NSET=Nyend") +str = "" +for i in range(0, n_x + 1): + for k in range(0, n_z + 1): + str = "{}, ".format(indices[i, n_y, k]) + print(str) +print("** Nodes, border with y = y_begin") +print("*NSET, NSET=Nybegin") +str = "" +for i in range(0, n_x + 1): + for k in range(0, n_z + 1): + str = "{}, ".format(indices[i, 0, k]) + print(str) + + +# Upper surface +print("*SURFACE, NAME=Sflux_interface") +for id in elems_top_surface: + print("{}, S5".format(id)) diff --git a/flow-over-heated-plate-two-meshes/solid-calculix/run.sh b/flow-over-heated-plate-two-meshes/solid-calculix/run.sh new file mode 100755 index 000000000..460b914bd --- /dev/null +++ b/flow-over-heated-plate-two-meshes/solid-calculix/run.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 ./generate_mesh.py > all.msh +ccx_preCICE -i solid -precice-participant Solid + +close_log diff --git a/flow-over-heated-plate-two-meshes/solid-calculix/solid.inp b/flow-over-heated-plate-two-meshes/solid-calculix/solid.inp new file mode 100644 index 000000000..f9f77ac55 --- /dev/null +++ b/flow-over-heated-plate-two-meshes/solid-calculix/solid.inp @@ -0,0 +1,112 @@ +** Case file adapted from one generated by FreeCAD inp file writer for CalculiX,Abaqus meshes +** Mesh generated from https://gist.github.com/boris-martin/1cdcc53bac909449632076a614450949 + +*INCLUDE, INPUT=./all.msh + +** Define element set Eall +*ELSET, ELSET=Eall +Evolumes + + + +*********************************************************** +** Element sets for materials and FEM element type (solid, shell, beam, fluid) +** written by write_element_sets_material_and_femelement_type function +*ELSET,ELSET=MaterialSolidSolid +Evolumes + + +*********************************************************** +** Materials +** written by write_materials function +** Young's modulus unit is Pa = N/m2 +** Thermal conductivity unit is W/(m*K) +** Specific Heat unit is J/(kg*K) +** FreeCAD material name: CalculiX-Steel +** MaterialSolid +*MATERIAL, NAME=MaterialSolid +*ELASTIC +210000, 0.300 +*CONDUCTIVITY +100.000 +*EXPANSION +1.200e-05 +*SPECIFIC HEAT +100.0 + +** conductivity / (density * Specific Heat) = 1 +*DENSITY +1.0 + +*********************************************************** +** Initial temperature constraint +** written by write_constraints_initialtemperature function +*INITIAL CONDITIONS,TYPE=TEMPERATURE +Nall,310.0 + +*********************************************************** +** Sections +** written by write_femelementsets function +*SOLID SECTION, ELSET=MaterialSolidSolid, MATERIAL=MaterialSolid + +*********************************************************** +** At least one step is needed to run an CalculiX analysis of FreeCAD +** written by write_step_begin function +*STEP, INC=2000 +*HEAT TRANSFER, DIRECT +0.01,1.0 + +*********************************************************** +** Fixed temperature constraint applied +** written by write_constraints_temperature function +** HeatedPlate +*BOUNDARY +Nybegin,11,11,310.0 + +** ConstraintTemperature001 +*BOUNDARY +Nyend,11,11,0.0 + + +*********************************************************** +** Outputs --> frd file +** written by write_outputs_types function +*NODE FILE +NT + +*********************************************************** +** written by write_step_end function +*END STEP + +*********************************************************** +** CalculiX Input file +** written by write_footer function +** written by --> FreeCAD 0.19.24267 +99 (Git) +** written on --> Sat Feb 19 21:15:15 2022 +** file name --> heat_plate_ccx.FCStd +** analysis name --> Analysis +** +** +*********************************************************** +** About units: +** See ccx manual, ccx does not know about any unit. +** Golden rule: The user must make sure that the numbers he provides have consistent units. +** The user is the FreeCAD calculix writer module ;-) +** +** The unit system which is used at Guido Dhondt's company: mm, N, s, K +** Since Length and Mass are connected by Force, if Length is mm the Mass is in t to get N +** The following units are used to write to inp file: +** +** Length: mm (this includes the mesh geometry) +** Mass: t +** TimeSpan: s +** Temperature: K +** +** This leads to: +** Force: N +** Pressure: N/mm^2 +** Density: t/mm^3 +** Gravity: mm/s^2 +** Thermal conductivity: t*mm/K/s^3 (same as W/m/K) +** Specific Heat: mm^2/s^2/K (same as J/kg/K) +** diff --git a/flow-over-heated-plate/README.md b/flow-over-heated-plate/README.md index 6328eab6b..d61a6751b 100644 --- a/flow-over-heated-plate/README.md +++ b/flow-over-heated-plate/README.md @@ -17,7 +17,13 @@ This scenario consists of one fluid and one solid participant and it is inspired The test case is two-dimensional and a serial-implicit coupling with Aitken underrelaxation is used for the coupling. -The inlet velocity is $$ u_{\infty} = 0.1 m/s $$, the inlet temperature is $$ T_{\infty} = 300K $$. The fluid and solid have the same thermal conductivities $$ k_S = k_F = 100 W/m/K $$. Further material properties of the fluid are its viscosity $$ mu = 0.0002 kg/m/s $$ and specific heat capacity $$ c_p = 5000 J/kg/K $$. The Prandtl number $$ Pr = 0.01 $$ follows from thermal conductivity, viscosity and specific heat capacity. The solid has the thermal diffusivity $$ \alpha = 1 m^2/s $$. The gravitational acceleration is $$ g = 9.81 m/s^2 $$. +The inlet velocity is $$ u_{\infty} = 0.1 m/s $$, the inlet temperature is $$ T_{\infty} = 300K $$. The fluid and solid have the same thermal conductivities $$ k_S = k_F = 100 W/m/K $$. Further material properties of the fluid are its viscosity $$ \mu = 0.0002 kg/m/s $$ and specific heat capacity $$ c_p = 5000 J/kg/K $$. The Prandtl number $$ Pr = 0.01 $$ follows from thermal conductivity, viscosity and specific heat capacity. The solid has the thermal diffusivity $$ \alpha = 1 m^2/s $$. The gravitational acceleration is $$ g = 9.81 m/s^2 $$. + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-flow-over-heated-plate-precice-config.png) ## Available solvers @@ -27,6 +33,8 @@ Fluid participant: * OpenFOAM (buoyantFoam). For more information, have a look at the [OpenFOAM adapter documentation](https://www.precice.org/adapter-openfoam-overview.html). +* SU2. For more information, have a look at the [SU2 adapter docmentation](https://www.precice.org/adapter-su2.html). + Solid participant: * OpenFOAM (laplacianFoam). For more information, have a look at the [OpenFOAM adapter documentation](https://www.precice.org/adapter-openfoam-overview.html). @@ -35,7 +43,9 @@ Solid participant: * Nutils. For more information, have a look at the [Nutils adapter documentation](https://precice.org/adapter-nutils.html). -* Dune-Fem. For more information, have a look at the [official documentation of Dune-Fem](https://www.dune-project.org/sphinx/dune-fem/). The solver can be installed through [PyPI](https://pypi.org/project/dune-fem/). Make sure that you are in a Python virtual environment first, which you can create inside the `solid-dune` directory and load again before running (you may need to install some tools again in this environment). Please note that Dune-Fem uses just-in-time compilation: The first time you run the solver script, it will take some time. +* Dune-Fem. For more information, have a look at the [official documentation of Dune-Fem](https://www.dune-project.org/sphinx/dune-fem/). The `run.sh` script installs the solver from [PyPI](https://pypi.org/project/dune-fem/) into a Python virtual environment. Please note that Dune-Fem uses just-in-time compilation: The first time you run the solver script, it will take some time. + +It is also possible to use CalculiX as solid solver. In that case, two coupling meshes are needed: CalculiX read/writes temperatures on nodes, but read/writes heat-fluxes on face centers. This requires some adaptation of the `precice-config.xml` file, and [a separate tutorial](tutorials-flow-over-heated-plate-two-meshes.html) has been designed for it. ## Running the Simulation @@ -76,14 +86,14 @@ First generate the output for each run by adding export to the participant `Soli ```xml - - - + + + ... ``` -After that running a case from this tutorial will export data into `solid-*/preCICE-output`. To visualize and compare these results run `python3 plot-final-interface-temperature.py` (You can install the required python packages by running `pip3 install -r plot-final-interface-temperature-requirements.txt`). This will plot the dimensionless temperature `theta = (T-300)/(310-300)` (with `T` being the temperature) across the coupling interface, i.e. where the solid and the fluid meet and exchange heat. The x-axis shows the x coordinate and the y-axis the dimensionless temperature `theta` at the interface. If you want to exclude certain cases, simply comment out the corresponding lines in the script. For reference see below: +After that running a case from this tutorial will export data into `solid-*/precice-exports`. To visualize and compare these results run `python3 plot-final-interface-temperature.py` (You can install the required python packages by running `pip3 install -r plot-final-interface-temperature-requirements.txt`). This will plot the dimensionless temperature `theta = (T-300)/(310-300)` (with `T` being the temperature) across the coupling interface, i.e. where the solid and the fluid meet and exchange heat. The x-axis shows the x coordinate and the y-axis the dimensionless temperature `theta` at the interface. If you want to exclude certain cases, simply comment out the corresponding lines in the script. For reference see below: ![Comparison of the results with different solvers](images/tutorials-flow-over-heated-plate-results-comparison.png) diff --git a/flow-over-heated-plate/fluid-openfoam/run.sh b/flow-over-heated-plate/fluid-openfoam/run.sh index c191b9e48..da82a9ba2 100755 --- a/flow-over-heated-plate/fluid-openfoam/run.sh +++ b/flow-over-heated-plate/fluid-openfoam/run.sh @@ -1,8 +1,12 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + blockMesh -touch fluid-openfoam.foam ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/flow-over-heated-plate/fluid-su2/clean.sh b/flow-over-heated-plate/fluid-su2/clean.sh new file mode 100755 index 000000000..54a3623e3 --- /dev/null +++ b/flow-over-heated-plate/fluid-su2/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_su2 . diff --git a/flow-over-heated-plate/fluid-su2/fluid_mesh.su2 b/flow-over-heated-plate/fluid-su2/fluid_mesh.su2 new file mode 100644 index 000000000..abbdab462 --- /dev/null +++ b/flow-over-heated-plate/fluid-su2/fluid_mesh.su2 @@ -0,0 +1,23387 @@ +% Problem dimension +NDIME= 2 +% +% Inner element connectivity +% +NELEM= 11200 + 9 0 1 42 41 0 + 9 1 2 43 42 1 + 9 2 3 44 43 2 + 9 3 4 45 44 3 + 9 4 5 46 45 4 + 9 5 6 47 46 5 + 9 6 7 48 47 6 + 9 7 8 49 48 7 + 9 8 9 50 49 8 + 9 9 10 51 50 9 + 9 10 11 52 51 10 + 9 11 12 53 52 11 + 9 12 13 54 53 12 + 9 13 14 55 54 13 + 9 14 15 56 55 14 + 9 15 16 57 56 15 + 9 16 17 58 57 16 + 9 17 18 59 58 17 + 9 18 19 60 59 18 + 9 19 20 61 60 19 + 9 20 21 62 61 20 + 9 21 22 63 62 21 + 9 22 23 64 63 22 + 9 23 24 65 64 23 + 9 24 25 66 65 24 + 9 25 26 67 66 25 + 9 26 27 68 67 26 + 9 27 28 69 68 27 + 9 28 29 70 69 28 + 9 29 30 71 70 29 + 9 30 31 72 71 30 + 9 31 32 73 72 31 + 9 32 33 74 73 32 + 9 33 34 75 74 33 + 9 34 35 76 75 34 + 9 35 36 77 76 35 + 9 36 37 78 77 36 + 9 37 38 79 78 37 + 9 38 39 80 79 38 + 9 39 40 81 80 39 + 9 41 42 83 82 40 + 9 42 43 84 83 41 + 9 43 44 85 84 42 + 9 44 45 86 85 43 + 9 45 46 87 86 44 + 9 46 47 88 87 45 + 9 47 48 89 88 46 + 9 48 49 90 89 47 + 9 49 50 91 90 48 + 9 50 51 92 91 49 + 9 51 52 93 92 50 + 9 52 53 94 93 51 + 9 53 54 95 94 52 + 9 54 55 96 95 53 + 9 55 56 97 96 54 + 9 56 57 98 97 55 + 9 57 58 99 98 56 + 9 58 59 100 99 57 + 9 59 60 101 100 58 + 9 60 61 102 101 59 + 9 61 62 103 102 60 + 9 62 63 104 103 61 + 9 63 64 105 104 62 + 9 64 65 106 105 63 + 9 65 66 107 106 64 + 9 66 67 108 107 65 + 9 67 68 109 108 66 + 9 68 69 110 109 67 + 9 69 70 111 110 68 + 9 70 71 112 111 69 + 9 71 72 113 112 70 + 9 72 73 114 113 71 + 9 73 74 115 114 72 + 9 74 75 116 115 73 + 9 75 76 117 116 74 + 9 76 77 118 117 75 + 9 77 78 119 118 76 + 9 78 79 120 119 77 + 9 79 80 121 120 78 + 9 80 81 122 121 79 + 9 82 83 124 123 80 + 9 83 84 125 124 81 + 9 84 85 126 125 82 + 9 85 86 127 126 83 + 9 86 87 128 127 84 + 9 87 88 129 128 85 + 9 88 89 130 129 86 + 9 89 90 131 130 87 + 9 90 91 132 131 88 + 9 91 92 133 132 89 + 9 92 93 134 133 90 + 9 93 94 135 134 91 + 9 94 95 136 135 92 + 9 95 96 137 136 93 + 9 96 97 138 137 94 + 9 97 98 139 138 95 + 9 98 99 140 139 96 + 9 99 100 141 140 97 + 9 100 101 142 141 98 + 9 101 102 143 142 99 + 9 102 103 144 143 100 + 9 103 104 145 144 101 + 9 104 105 146 145 102 + 9 105 106 147 146 103 + 9 106 107 148 147 104 + 9 107 108 149 148 105 + 9 108 109 150 149 106 + 9 109 110 151 150 107 + 9 110 111 152 151 108 + 9 111 112 153 152 109 + 9 112 113 154 153 110 + 9 113 114 155 154 111 + 9 114 115 156 155 112 + 9 115 116 157 156 113 + 9 116 117 158 157 114 + 9 117 118 159 158 115 + 9 118 119 160 159 116 + 9 119 120 161 160 117 + 9 120 121 162 161 118 + 9 121 122 163 162 119 + 9 123 124 165 164 120 + 9 124 125 166 165 121 + 9 125 126 167 166 122 + 9 126 127 168 167 123 + 9 127 128 169 168 124 + 9 128 129 170 169 125 + 9 129 130 171 170 126 + 9 130 131 172 171 127 + 9 131 132 173 172 128 + 9 132 133 174 173 129 + 9 133 134 175 174 130 + 9 134 135 176 175 131 + 9 135 136 177 176 132 + 9 136 137 178 177 133 + 9 137 138 179 178 134 + 9 138 139 180 179 135 + 9 139 140 181 180 136 + 9 140 141 182 181 137 + 9 141 142 183 182 138 + 9 142 143 184 183 139 + 9 143 144 185 184 140 + 9 144 145 186 185 141 + 9 145 146 187 186 142 + 9 146 147 188 187 143 + 9 147 148 189 188 144 + 9 148 149 190 189 145 + 9 149 150 191 190 146 + 9 150 151 192 191 147 + 9 151 152 193 192 148 + 9 152 153 194 193 149 + 9 153 154 195 194 150 + 9 154 155 196 195 151 + 9 155 156 197 196 152 + 9 156 157 198 197 153 + 9 157 158 199 198 154 + 9 158 159 200 199 155 + 9 159 160 201 200 156 + 9 160 161 202 201 157 + 9 161 162 203 202 158 + 9 162 163 204 203 159 + 9 164 165 206 205 160 + 9 165 166 207 206 161 + 9 166 167 208 207 162 + 9 167 168 209 208 163 + 9 168 169 210 209 164 + 9 169 170 211 210 165 + 9 170 171 212 211 166 + 9 171 172 213 212 167 + 9 172 173 214 213 168 + 9 173 174 215 214 169 + 9 174 175 216 215 170 + 9 175 176 217 216 171 + 9 176 177 218 217 172 + 9 177 178 219 218 173 + 9 178 179 220 219 174 + 9 179 180 221 220 175 + 9 180 181 222 221 176 + 9 181 182 223 222 177 + 9 182 183 224 223 178 + 9 183 184 225 224 179 + 9 184 185 226 225 180 + 9 185 186 227 226 181 + 9 186 187 228 227 182 + 9 187 188 229 228 183 + 9 188 189 230 229 184 + 9 189 190 231 230 185 + 9 190 191 232 231 186 + 9 191 192 233 232 187 + 9 192 193 234 233 188 + 9 193 194 235 234 189 + 9 194 195 236 235 190 + 9 195 196 237 236 191 + 9 196 197 238 237 192 + 9 197 198 239 238 193 + 9 198 199 240 239 194 + 9 199 200 241 240 195 + 9 200 201 242 241 196 + 9 201 202 243 242 197 + 9 202 203 244 243 198 + 9 203 204 245 244 199 + 9 205 206 247 246 200 + 9 206 207 248 247 201 + 9 207 208 249 248 202 + 9 208 209 250 249 203 + 9 209 210 251 250 204 + 9 210 211 252 251 205 + 9 211 212 253 252 206 + 9 212 213 254 253 207 + 9 213 214 255 254 208 + 9 214 215 256 255 209 + 9 215 216 257 256 210 + 9 216 217 258 257 211 + 9 217 218 259 258 212 + 9 218 219 260 259 213 + 9 219 220 261 260 214 + 9 220 221 262 261 215 + 9 221 222 263 262 216 + 9 222 223 264 263 217 + 9 223 224 265 264 218 + 9 224 225 266 265 219 + 9 225 226 267 266 220 + 9 226 227 268 267 221 + 9 227 228 269 268 222 + 9 228 229 270 269 223 + 9 229 230 271 270 224 + 9 230 231 272 271 225 + 9 231 232 273 272 226 + 9 232 233 274 273 227 + 9 233 234 275 274 228 + 9 234 235 276 275 229 + 9 235 236 277 276 230 + 9 236 237 278 277 231 + 9 237 238 279 278 232 + 9 238 239 280 279 233 + 9 239 240 281 280 234 + 9 240 241 282 281 235 + 9 241 242 283 282 236 + 9 242 243 284 283 237 + 9 243 244 285 284 238 + 9 244 245 286 285 239 + 9 246 247 288 287 240 + 9 247 248 289 288 241 + 9 248 249 290 289 242 + 9 249 250 291 290 243 + 9 250 251 292 291 244 + 9 251 252 293 292 245 + 9 252 253 294 293 246 + 9 253 254 295 294 247 + 9 254 255 296 295 248 + 9 255 256 297 296 249 + 9 256 257 298 297 250 + 9 257 258 299 298 251 + 9 258 259 300 299 252 + 9 259 260 301 300 253 + 9 260 261 302 301 254 + 9 261 262 303 302 255 + 9 262 263 304 303 256 + 9 263 264 305 304 257 + 9 264 265 306 305 258 + 9 265 266 307 306 259 + 9 266 267 308 307 260 + 9 267 268 309 308 261 + 9 268 269 310 309 262 + 9 269 270 311 310 263 + 9 270 271 312 311 264 + 9 271 272 313 312 265 + 9 272 273 314 313 266 + 9 273 274 315 314 267 + 9 274 275 316 315 268 + 9 275 276 317 316 269 + 9 276 277 318 317 270 + 9 277 278 319 318 271 + 9 278 279 320 319 272 + 9 279 280 321 320 273 + 9 280 281 322 321 274 + 9 281 282 323 322 275 + 9 282 283 324 323 276 + 9 283 284 325 324 277 + 9 284 285 326 325 278 + 9 285 286 327 326 279 + 9 287 288 329 328 280 + 9 288 289 330 329 281 + 9 289 290 331 330 282 + 9 290 291 332 331 283 + 9 291 292 333 332 284 + 9 292 293 334 333 285 + 9 293 294 335 334 286 + 9 294 295 336 335 287 + 9 295 296 337 336 288 + 9 296 297 338 337 289 + 9 297 298 339 338 290 + 9 298 299 340 339 291 + 9 299 300 341 340 292 + 9 300 301 342 341 293 + 9 301 302 343 342 294 + 9 302 303 344 343 295 + 9 303 304 345 344 296 + 9 304 305 346 345 297 + 9 305 306 347 346 298 + 9 306 307 348 347 299 + 9 307 308 349 348 300 + 9 308 309 350 349 301 + 9 309 310 351 350 302 + 9 310 311 352 351 303 + 9 311 312 353 352 304 + 9 312 313 354 353 305 + 9 313 314 355 354 306 + 9 314 315 356 355 307 + 9 315 316 357 356 308 + 9 316 317 358 357 309 + 9 317 318 359 358 310 + 9 318 319 360 359 311 + 9 319 320 361 360 312 + 9 320 321 362 361 313 + 9 321 322 363 362 314 + 9 322 323 364 363 315 + 9 323 324 365 364 316 + 9 324 325 366 365 317 + 9 325 326 367 366 318 + 9 326 327 368 367 319 + 9 328 329 370 369 320 + 9 329 330 371 370 321 + 9 330 331 372 371 322 + 9 331 332 373 372 323 + 9 332 333 374 373 324 + 9 333 334 375 374 325 + 9 334 335 376 375 326 + 9 335 336 377 376 327 + 9 336 337 378 377 328 + 9 337 338 379 378 329 + 9 338 339 380 379 330 + 9 339 340 381 380 331 + 9 340 341 382 381 332 + 9 341 342 383 382 333 + 9 342 343 384 383 334 + 9 343 344 385 384 335 + 9 344 345 386 385 336 + 9 345 346 387 386 337 + 9 346 347 388 387 338 + 9 347 348 389 388 339 + 9 348 349 390 389 340 + 9 349 350 391 390 341 + 9 350 351 392 391 342 + 9 351 352 393 392 343 + 9 352 353 394 393 344 + 9 353 354 395 394 345 + 9 354 355 396 395 346 + 9 355 356 397 396 347 + 9 356 357 398 397 348 + 9 357 358 399 398 349 + 9 358 359 400 399 350 + 9 359 360 401 400 351 + 9 360 361 402 401 352 + 9 361 362 403 402 353 + 9 362 363 404 403 354 + 9 363 364 405 404 355 + 9 364 365 406 405 356 + 9 365 366 407 406 357 + 9 366 367 408 407 358 + 9 367 368 409 408 359 + 9 369 370 411 410 360 + 9 370 371 412 411 361 + 9 371 372 413 412 362 + 9 372 373 414 413 363 + 9 373 374 415 414 364 + 9 374 375 416 415 365 + 9 375 376 417 416 366 + 9 376 377 418 417 367 + 9 377 378 419 418 368 + 9 378 379 420 419 369 + 9 379 380 421 420 370 + 9 380 381 422 421 371 + 9 381 382 423 422 372 + 9 382 383 424 423 373 + 9 383 384 425 424 374 + 9 384 385 426 425 375 + 9 385 386 427 426 376 + 9 386 387 428 427 377 + 9 387 388 429 428 378 + 9 388 389 430 429 379 + 9 389 390 431 430 380 + 9 390 391 432 431 381 + 9 391 392 433 432 382 + 9 392 393 434 433 383 + 9 393 394 435 434 384 + 9 394 395 436 435 385 + 9 395 396 437 436 386 + 9 396 397 438 437 387 + 9 397 398 439 438 388 + 9 398 399 440 439 389 + 9 399 400 441 440 390 + 9 400 401 442 441 391 + 9 401 402 443 442 392 + 9 402 403 444 443 393 + 9 403 404 445 444 394 + 9 404 405 446 445 395 + 9 405 406 447 446 396 + 9 406 407 448 447 397 + 9 407 408 449 448 398 + 9 408 409 450 449 399 + 9 410 411 452 451 400 + 9 411 412 453 452 401 + 9 412 413 454 453 402 + 9 413 414 455 454 403 + 9 414 415 456 455 404 + 9 415 416 457 456 405 + 9 416 417 458 457 406 + 9 417 418 459 458 407 + 9 418 419 460 459 408 + 9 419 420 461 460 409 + 9 420 421 462 461 410 + 9 421 422 463 462 411 + 9 422 423 464 463 412 + 9 423 424 465 464 413 + 9 424 425 466 465 414 + 9 425 426 467 466 415 + 9 426 427 468 467 416 + 9 427 428 469 468 417 + 9 428 429 470 469 418 + 9 429 430 471 470 419 + 9 430 431 472 471 420 + 9 431 432 473 472 421 + 9 432 433 474 473 422 + 9 433 434 475 474 423 + 9 434 435 476 475 424 + 9 435 436 477 476 425 + 9 436 437 478 477 426 + 9 437 438 479 478 427 + 9 438 439 480 479 428 + 9 439 440 481 480 429 + 9 440 441 482 481 430 + 9 441 442 483 482 431 + 9 442 443 484 483 432 + 9 443 444 485 484 433 + 9 444 445 486 485 434 + 9 445 446 487 486 435 + 9 446 447 488 487 436 + 9 447 448 489 488 437 + 9 448 449 490 489 438 + 9 449 450 491 490 439 + 9 451 452 493 492 440 + 9 452 453 494 493 441 + 9 453 454 495 494 442 + 9 454 455 496 495 443 + 9 455 456 497 496 444 + 9 456 457 498 497 445 + 9 457 458 499 498 446 + 9 458 459 500 499 447 + 9 459 460 501 500 448 + 9 460 461 502 501 449 + 9 461 462 503 502 450 + 9 462 463 504 503 451 + 9 463 464 505 504 452 + 9 464 465 506 505 453 + 9 465 466 507 506 454 + 9 466 467 508 507 455 + 9 467 468 509 508 456 + 9 468 469 510 509 457 + 9 469 470 511 510 458 + 9 470 471 512 511 459 + 9 471 472 513 512 460 + 9 472 473 514 513 461 + 9 473 474 515 514 462 + 9 474 475 516 515 463 + 9 475 476 517 516 464 + 9 476 477 518 517 465 + 9 477 478 519 518 466 + 9 478 479 520 519 467 + 9 479 480 521 520 468 + 9 480 481 522 521 469 + 9 481 482 523 522 470 + 9 482 483 524 523 471 + 9 483 484 525 524 472 + 9 484 485 526 525 473 + 9 485 486 527 526 474 + 9 486 487 528 527 475 + 9 487 488 529 528 476 + 9 488 489 530 529 477 + 9 489 490 531 530 478 + 9 490 491 532 531 479 + 9 492 493 534 533 480 + 9 493 494 535 534 481 + 9 494 495 536 535 482 + 9 495 496 537 536 483 + 9 496 497 538 537 484 + 9 497 498 539 538 485 + 9 498 499 540 539 486 + 9 499 500 541 540 487 + 9 500 501 542 541 488 + 9 501 502 543 542 489 + 9 502 503 544 543 490 + 9 503 504 545 544 491 + 9 504 505 546 545 492 + 9 505 506 547 546 493 + 9 506 507 548 547 494 + 9 507 508 549 548 495 + 9 508 509 550 549 496 + 9 509 510 551 550 497 + 9 510 511 552 551 498 + 9 511 512 553 552 499 + 9 512 513 554 553 500 + 9 513 514 555 554 501 + 9 514 515 556 555 502 + 9 515 516 557 556 503 + 9 516 517 558 557 504 + 9 517 518 559 558 505 + 9 518 519 560 559 506 + 9 519 520 561 560 507 + 9 520 521 562 561 508 + 9 521 522 563 562 509 + 9 522 523 564 563 510 + 9 523 524 565 564 511 + 9 524 525 566 565 512 + 9 525 526 567 566 513 + 9 526 527 568 567 514 + 9 527 528 569 568 515 + 9 528 529 570 569 516 + 9 529 530 571 570 517 + 9 530 531 572 571 518 + 9 531 532 573 572 519 + 9 533 534 575 574 520 + 9 534 535 576 575 521 + 9 535 536 577 576 522 + 9 536 537 578 577 523 + 9 537 538 579 578 524 + 9 538 539 580 579 525 + 9 539 540 581 580 526 + 9 540 541 582 581 527 + 9 541 542 583 582 528 + 9 542 543 584 583 529 + 9 543 544 585 584 530 + 9 544 545 586 585 531 + 9 545 546 587 586 532 + 9 546 547 588 587 533 + 9 547 548 589 588 534 + 9 548 549 590 589 535 + 9 549 550 591 590 536 + 9 550 551 592 591 537 + 9 551 552 593 592 538 + 9 552 553 594 593 539 + 9 553 554 595 594 540 + 9 554 555 596 595 541 + 9 555 556 597 596 542 + 9 556 557 598 597 543 + 9 557 558 599 598 544 + 9 558 559 600 599 545 + 9 559 560 601 600 546 + 9 560 561 602 601 547 + 9 561 562 603 602 548 + 9 562 563 604 603 549 + 9 563 564 605 604 550 + 9 564 565 606 605 551 + 9 565 566 607 606 552 + 9 566 567 608 607 553 + 9 567 568 609 608 554 + 9 568 569 610 609 555 + 9 569 570 611 610 556 + 9 570 571 612 611 557 + 9 571 572 613 612 558 + 9 572 573 614 613 559 + 9 574 575 616 615 560 + 9 575 576 617 616 561 + 9 576 577 618 617 562 + 9 577 578 619 618 563 + 9 578 579 620 619 564 + 9 579 580 621 620 565 + 9 580 581 622 621 566 + 9 581 582 623 622 567 + 9 582 583 624 623 568 + 9 583 584 625 624 569 + 9 584 585 626 625 570 + 9 585 586 627 626 571 + 9 586 587 628 627 572 + 9 587 588 629 628 573 + 9 588 589 630 629 574 + 9 589 590 631 630 575 + 9 590 591 632 631 576 + 9 591 592 633 632 577 + 9 592 593 634 633 578 + 9 593 594 635 634 579 + 9 594 595 636 635 580 + 9 595 596 637 636 581 + 9 596 597 638 637 582 + 9 597 598 639 638 583 + 9 598 599 640 639 584 + 9 599 600 641 640 585 + 9 600 601 642 641 586 + 9 601 602 643 642 587 + 9 602 603 644 643 588 + 9 603 604 645 644 589 + 9 604 605 646 645 590 + 9 605 606 647 646 591 + 9 606 607 648 647 592 + 9 607 608 649 648 593 + 9 608 609 650 649 594 + 9 609 610 651 650 595 + 9 610 611 652 651 596 + 9 611 612 653 652 597 + 9 612 613 654 653 598 + 9 613 614 655 654 599 + 9 615 616 657 656 600 + 9 616 617 658 657 601 + 9 617 618 659 658 602 + 9 618 619 660 659 603 + 9 619 620 661 660 604 + 9 620 621 662 661 605 + 9 621 622 663 662 606 + 9 622 623 664 663 607 + 9 623 624 665 664 608 + 9 624 625 666 665 609 + 9 625 626 667 666 610 + 9 626 627 668 667 611 + 9 627 628 669 668 612 + 9 628 629 670 669 613 + 9 629 630 671 670 614 + 9 630 631 672 671 615 + 9 631 632 673 672 616 + 9 632 633 674 673 617 + 9 633 634 675 674 618 + 9 634 635 676 675 619 + 9 635 636 677 676 620 + 9 636 637 678 677 621 + 9 637 638 679 678 622 + 9 638 639 680 679 623 + 9 639 640 681 680 624 + 9 640 641 682 681 625 + 9 641 642 683 682 626 + 9 642 643 684 683 627 + 9 643 644 685 684 628 + 9 644 645 686 685 629 + 9 645 646 687 686 630 + 9 646 647 688 687 631 + 9 647 648 689 688 632 + 9 648 649 690 689 633 + 9 649 650 691 690 634 + 9 650 651 692 691 635 + 9 651 652 693 692 636 + 9 652 653 694 693 637 + 9 653 654 695 694 638 + 9 654 655 696 695 639 + 9 656 657 698 697 640 + 9 657 658 699 698 641 + 9 658 659 700 699 642 + 9 659 660 701 700 643 + 9 660 661 702 701 644 + 9 661 662 703 702 645 + 9 662 663 704 703 646 + 9 663 664 705 704 647 + 9 664 665 706 705 648 + 9 665 666 707 706 649 + 9 666 667 708 707 650 + 9 667 668 709 708 651 + 9 668 669 710 709 652 + 9 669 670 711 710 653 + 9 670 671 712 711 654 + 9 671 672 713 712 655 + 9 672 673 714 713 656 + 9 673 674 715 714 657 + 9 674 675 716 715 658 + 9 675 676 717 716 659 + 9 676 677 718 717 660 + 9 677 678 719 718 661 + 9 678 679 720 719 662 + 9 679 680 721 720 663 + 9 680 681 722 721 664 + 9 681 682 723 722 665 + 9 682 683 724 723 666 + 9 683 684 725 724 667 + 9 684 685 726 725 668 + 9 685 686 727 726 669 + 9 686 687 728 727 670 + 9 687 688 729 728 671 + 9 688 689 730 729 672 + 9 689 690 731 730 673 + 9 690 691 732 731 674 + 9 691 692 733 732 675 + 9 692 693 734 733 676 + 9 693 694 735 734 677 + 9 694 695 736 735 678 + 9 695 696 737 736 679 + 9 697 698 739 738 680 + 9 698 699 740 739 681 + 9 699 700 741 740 682 + 9 700 701 742 741 683 + 9 701 702 743 742 684 + 9 702 703 744 743 685 + 9 703 704 745 744 686 + 9 704 705 746 745 687 + 9 705 706 747 746 688 + 9 706 707 748 747 689 + 9 707 708 749 748 690 + 9 708 709 750 749 691 + 9 709 710 751 750 692 + 9 710 711 752 751 693 + 9 711 712 753 752 694 + 9 712 713 754 753 695 + 9 713 714 755 754 696 + 9 714 715 756 755 697 + 9 715 716 757 756 698 + 9 716 717 758 757 699 + 9 717 718 759 758 700 + 9 718 719 760 759 701 + 9 719 720 761 760 702 + 9 720 721 762 761 703 + 9 721 722 763 762 704 + 9 722 723 764 763 705 + 9 723 724 765 764 706 + 9 724 725 766 765 707 + 9 725 726 767 766 708 + 9 726 727 768 767 709 + 9 727 728 769 768 710 + 9 728 729 770 769 711 + 9 729 730 771 770 712 + 9 730 731 772 771 713 + 9 731 732 773 772 714 + 9 732 733 774 773 715 + 9 733 734 775 774 716 + 9 734 735 776 775 717 + 9 735 736 777 776 718 + 9 736 737 778 777 719 + 9 738 739 780 779 720 + 9 739 740 781 780 721 + 9 740 741 782 781 722 + 9 741 742 783 782 723 + 9 742 743 784 783 724 + 9 743 744 785 784 725 + 9 744 745 786 785 726 + 9 745 746 787 786 727 + 9 746 747 788 787 728 + 9 747 748 789 788 729 + 9 748 749 790 789 730 + 9 749 750 791 790 731 + 9 750 751 792 791 732 + 9 751 752 793 792 733 + 9 752 753 794 793 734 + 9 753 754 795 794 735 + 9 754 755 796 795 736 + 9 755 756 797 796 737 + 9 756 757 798 797 738 + 9 757 758 799 798 739 + 9 758 759 800 799 740 + 9 759 760 801 800 741 + 9 760 761 802 801 742 + 9 761 762 803 802 743 + 9 762 763 804 803 744 + 9 763 764 805 804 745 + 9 764 765 806 805 746 + 9 765 766 807 806 747 + 9 766 767 808 807 748 + 9 767 768 809 808 749 + 9 768 769 810 809 750 + 9 769 770 811 810 751 + 9 770 771 812 811 752 + 9 771 772 813 812 753 + 9 772 773 814 813 754 + 9 773 774 815 814 755 + 9 774 775 816 815 756 + 9 775 776 817 816 757 + 9 776 777 818 817 758 + 9 777 778 819 818 759 + 9 779 780 821 820 760 + 9 780 781 822 821 761 + 9 781 782 823 822 762 + 9 782 783 824 823 763 + 9 783 784 825 824 764 + 9 784 785 826 825 765 + 9 785 786 827 826 766 + 9 786 787 828 827 767 + 9 787 788 829 828 768 + 9 788 789 830 829 769 + 9 789 790 831 830 770 + 9 790 791 832 831 771 + 9 791 792 833 832 772 + 9 792 793 834 833 773 + 9 793 794 835 834 774 + 9 794 795 836 835 775 + 9 795 796 837 836 776 + 9 796 797 838 837 777 + 9 797 798 839 838 778 + 9 798 799 840 839 779 + 9 799 800 841 840 780 + 9 800 801 842 841 781 + 9 801 802 843 842 782 + 9 802 803 844 843 783 + 9 803 804 845 844 784 + 9 804 805 846 845 785 + 9 805 806 847 846 786 + 9 806 807 848 847 787 + 9 807 808 849 848 788 + 9 808 809 850 849 789 + 9 809 810 851 850 790 + 9 810 811 852 851 791 + 9 811 812 853 852 792 + 9 812 813 854 853 793 + 9 813 814 855 854 794 + 9 814 815 856 855 795 + 9 815 816 857 856 796 + 9 816 817 858 857 797 + 9 817 818 859 858 798 + 9 818 819 860 859 799 + 9 820 821 862 861 800 + 9 821 822 863 862 801 + 9 822 823 864 863 802 + 9 823 824 865 864 803 + 9 824 825 866 865 804 + 9 825 826 867 866 805 + 9 826 827 868 867 806 + 9 827 828 869 868 807 + 9 828 829 870 869 808 + 9 829 830 871 870 809 + 9 830 831 872 871 810 + 9 831 832 873 872 811 + 9 832 833 874 873 812 + 9 833 834 875 874 813 + 9 834 835 876 875 814 + 9 835 836 877 876 815 + 9 836 837 878 877 816 + 9 837 838 879 878 817 + 9 838 839 880 879 818 + 9 839 840 881 880 819 + 9 840 841 882 881 820 + 9 841 842 883 882 821 + 9 842 843 884 883 822 + 9 843 844 885 884 823 + 9 844 845 886 885 824 + 9 845 846 887 886 825 + 9 846 847 888 887 826 + 9 847 848 889 888 827 + 9 848 849 890 889 828 + 9 849 850 891 890 829 + 9 850 851 892 891 830 + 9 851 852 893 892 831 + 9 852 853 894 893 832 + 9 853 854 895 894 833 + 9 854 855 896 895 834 + 9 855 856 897 896 835 + 9 856 857 898 897 836 + 9 857 858 899 898 837 + 9 858 859 900 899 838 + 9 859 860 901 900 839 + 9 861 862 903 902 840 + 9 862 863 904 903 841 + 9 863 864 905 904 842 + 9 864 865 906 905 843 + 9 865 866 907 906 844 + 9 866 867 908 907 845 + 9 867 868 909 908 846 + 9 868 869 910 909 847 + 9 869 870 911 910 848 + 9 870 871 912 911 849 + 9 871 872 913 912 850 + 9 872 873 914 913 851 + 9 873 874 915 914 852 + 9 874 875 916 915 853 + 9 875 876 917 916 854 + 9 876 877 918 917 855 + 9 877 878 919 918 856 + 9 878 879 920 919 857 + 9 879 880 921 920 858 + 9 880 881 922 921 859 + 9 881 882 923 922 860 + 9 882 883 924 923 861 + 9 883 884 925 924 862 + 9 884 885 926 925 863 + 9 885 886 927 926 864 + 9 886 887 928 927 865 + 9 887 888 929 928 866 + 9 888 889 930 929 867 + 9 889 890 931 930 868 + 9 890 891 932 931 869 + 9 891 892 933 932 870 + 9 892 893 934 933 871 + 9 893 894 935 934 872 + 9 894 895 936 935 873 + 9 895 896 937 936 874 + 9 896 897 938 937 875 + 9 897 898 939 938 876 + 9 898 899 940 939 877 + 9 899 900 941 940 878 + 9 900 901 942 941 879 + 9 902 903 944 943 880 + 9 903 904 945 944 881 + 9 904 905 946 945 882 + 9 905 906 947 946 883 + 9 906 907 948 947 884 + 9 907 908 949 948 885 + 9 908 909 950 949 886 + 9 909 910 951 950 887 + 9 910 911 952 951 888 + 9 911 912 953 952 889 + 9 912 913 954 953 890 + 9 913 914 955 954 891 + 9 914 915 956 955 892 + 9 915 916 957 956 893 + 9 916 917 958 957 894 + 9 917 918 959 958 895 + 9 918 919 960 959 896 + 9 919 920 961 960 897 + 9 920 921 962 961 898 + 9 921 922 963 962 899 + 9 922 923 964 963 900 + 9 923 924 965 964 901 + 9 924 925 966 965 902 + 9 925 926 967 966 903 + 9 926 927 968 967 904 + 9 927 928 969 968 905 + 9 928 929 970 969 906 + 9 929 930 971 970 907 + 9 930 931 972 971 908 + 9 931 932 973 972 909 + 9 932 933 974 973 910 + 9 933 934 975 974 911 + 9 934 935 976 975 912 + 9 935 936 977 976 913 + 9 936 937 978 977 914 + 9 937 938 979 978 915 + 9 938 939 980 979 916 + 9 939 940 981 980 917 + 9 940 941 982 981 918 + 9 941 942 983 982 919 + 9 943 944 985 984 920 + 9 944 945 986 985 921 + 9 945 946 987 986 922 + 9 946 947 988 987 923 + 9 947 948 989 988 924 + 9 948 949 990 989 925 + 9 949 950 991 990 926 + 9 950 951 992 991 927 + 9 951 952 993 992 928 + 9 952 953 994 993 929 + 9 953 954 995 994 930 + 9 954 955 996 995 931 + 9 955 956 997 996 932 + 9 956 957 998 997 933 + 9 957 958 999 998 934 + 9 958 959 1000 999 935 + 9 959 960 1001 1000 936 + 9 960 961 1002 1001 937 + 9 961 962 1003 1002 938 + 9 962 963 1004 1003 939 + 9 963 964 1005 1004 940 + 9 964 965 1006 1005 941 + 9 965 966 1007 1006 942 + 9 966 967 1008 1007 943 + 9 967 968 1009 1008 944 + 9 968 969 1010 1009 945 + 9 969 970 1011 1010 946 + 9 970 971 1012 1011 947 + 9 971 972 1013 1012 948 + 9 972 973 1014 1013 949 + 9 973 974 1015 1014 950 + 9 974 975 1016 1015 951 + 9 975 976 1017 1016 952 + 9 976 977 1018 1017 953 + 9 977 978 1019 1018 954 + 9 978 979 1020 1019 955 + 9 979 980 1021 1020 956 + 9 980 981 1022 1021 957 + 9 981 982 1023 1022 958 + 9 982 983 1024 1023 959 + 9 984 985 1026 1025 960 + 9 985 986 1027 1026 961 + 9 986 987 1028 1027 962 + 9 987 988 1029 1028 963 + 9 988 989 1030 1029 964 + 9 989 990 1031 1030 965 + 9 990 991 1032 1031 966 + 9 991 992 1033 1032 967 + 9 992 993 1034 1033 968 + 9 993 994 1035 1034 969 + 9 994 995 1036 1035 970 + 9 995 996 1037 1036 971 + 9 996 997 1038 1037 972 + 9 997 998 1039 1038 973 + 9 998 999 1040 1039 974 + 9 999 1000 1041 1040 975 + 9 1000 1001 1042 1041 976 + 9 1001 1002 1043 1042 977 + 9 1002 1003 1044 1043 978 + 9 1003 1004 1045 1044 979 + 9 1004 1005 1046 1045 980 + 9 1005 1006 1047 1046 981 + 9 1006 1007 1048 1047 982 + 9 1007 1008 1049 1048 983 + 9 1008 1009 1050 1049 984 + 9 1009 1010 1051 1050 985 + 9 1010 1011 1052 1051 986 + 9 1011 1012 1053 1052 987 + 9 1012 1013 1054 1053 988 + 9 1013 1014 1055 1054 989 + 9 1014 1015 1056 1055 990 + 9 1015 1016 1057 1056 991 + 9 1016 1017 1058 1057 992 + 9 1017 1018 1059 1058 993 + 9 1018 1019 1060 1059 994 + 9 1019 1020 1061 1060 995 + 9 1020 1021 1062 1061 996 + 9 1021 1022 1063 1062 997 + 9 1022 1023 1064 1063 998 + 9 1023 1024 1065 1064 999 + 9 1025 1026 1067 1066 1000 + 9 1026 1027 1068 1067 1001 + 9 1027 1028 1069 1068 1002 + 9 1028 1029 1070 1069 1003 + 9 1029 1030 1071 1070 1004 + 9 1030 1031 1072 1071 1005 + 9 1031 1032 1073 1072 1006 + 9 1032 1033 1074 1073 1007 + 9 1033 1034 1075 1074 1008 + 9 1034 1035 1076 1075 1009 + 9 1035 1036 1077 1076 1010 + 9 1036 1037 1078 1077 1011 + 9 1037 1038 1079 1078 1012 + 9 1038 1039 1080 1079 1013 + 9 1039 1040 1081 1080 1014 + 9 1040 1041 1082 1081 1015 + 9 1041 1042 1083 1082 1016 + 9 1042 1043 1084 1083 1017 + 9 1043 1044 1085 1084 1018 + 9 1044 1045 1086 1085 1019 + 9 1045 1046 1087 1086 1020 + 9 1046 1047 1088 1087 1021 + 9 1047 1048 1089 1088 1022 + 9 1048 1049 1090 1089 1023 + 9 1049 1050 1091 1090 1024 + 9 1050 1051 1092 1091 1025 + 9 1051 1052 1093 1092 1026 + 9 1052 1053 1094 1093 1027 + 9 1053 1054 1095 1094 1028 + 9 1054 1055 1096 1095 1029 + 9 1055 1056 1097 1096 1030 + 9 1056 1057 1098 1097 1031 + 9 1057 1058 1099 1098 1032 + 9 1058 1059 1100 1099 1033 + 9 1059 1060 1101 1100 1034 + 9 1060 1061 1102 1101 1035 + 9 1061 1062 1103 1102 1036 + 9 1062 1063 1104 1103 1037 + 9 1063 1064 1105 1104 1038 + 9 1064 1065 1106 1105 1039 + 9 1066 1067 1108 1107 1040 + 9 1067 1068 1109 1108 1041 + 9 1068 1069 1110 1109 1042 + 9 1069 1070 1111 1110 1043 + 9 1070 1071 1112 1111 1044 + 9 1071 1072 1113 1112 1045 + 9 1072 1073 1114 1113 1046 + 9 1073 1074 1115 1114 1047 + 9 1074 1075 1116 1115 1048 + 9 1075 1076 1117 1116 1049 + 9 1076 1077 1118 1117 1050 + 9 1077 1078 1119 1118 1051 + 9 1078 1079 1120 1119 1052 + 9 1079 1080 1121 1120 1053 + 9 1080 1081 1122 1121 1054 + 9 1081 1082 1123 1122 1055 + 9 1082 1083 1124 1123 1056 + 9 1083 1084 1125 1124 1057 + 9 1084 1085 1126 1125 1058 + 9 1085 1086 1127 1126 1059 + 9 1086 1087 1128 1127 1060 + 9 1087 1088 1129 1128 1061 + 9 1088 1089 1130 1129 1062 + 9 1089 1090 1131 1130 1063 + 9 1090 1091 1132 1131 1064 + 9 1091 1092 1133 1132 1065 + 9 1092 1093 1134 1133 1066 + 9 1093 1094 1135 1134 1067 + 9 1094 1095 1136 1135 1068 + 9 1095 1096 1137 1136 1069 + 9 1096 1097 1138 1137 1070 + 9 1097 1098 1139 1138 1071 + 9 1098 1099 1140 1139 1072 + 9 1099 1100 1141 1140 1073 + 9 1100 1101 1142 1141 1074 + 9 1101 1102 1143 1142 1075 + 9 1102 1103 1144 1143 1076 + 9 1103 1104 1145 1144 1077 + 9 1104 1105 1146 1145 1078 + 9 1105 1106 1147 1146 1079 + 9 1107 1108 1149 1148 1080 + 9 1108 1109 1150 1149 1081 + 9 1109 1110 1151 1150 1082 + 9 1110 1111 1152 1151 1083 + 9 1111 1112 1153 1152 1084 + 9 1112 1113 1154 1153 1085 + 9 1113 1114 1155 1154 1086 + 9 1114 1115 1156 1155 1087 + 9 1115 1116 1157 1156 1088 + 9 1116 1117 1158 1157 1089 + 9 1117 1118 1159 1158 1090 + 9 1118 1119 1160 1159 1091 + 9 1119 1120 1161 1160 1092 + 9 1120 1121 1162 1161 1093 + 9 1121 1122 1163 1162 1094 + 9 1122 1123 1164 1163 1095 + 9 1123 1124 1165 1164 1096 + 9 1124 1125 1166 1165 1097 + 9 1125 1126 1167 1166 1098 + 9 1126 1127 1168 1167 1099 + 9 1127 1128 1169 1168 1100 + 9 1128 1129 1170 1169 1101 + 9 1129 1130 1171 1170 1102 + 9 1130 1131 1172 1171 1103 + 9 1131 1132 1173 1172 1104 + 9 1132 1133 1174 1173 1105 + 9 1133 1134 1175 1174 1106 + 9 1134 1135 1176 1175 1107 + 9 1135 1136 1177 1176 1108 + 9 1136 1137 1178 1177 1109 + 9 1137 1138 1179 1178 1110 + 9 1138 1139 1180 1179 1111 + 9 1139 1140 1181 1180 1112 + 9 1140 1141 1182 1181 1113 + 9 1141 1142 1183 1182 1114 + 9 1142 1143 1184 1183 1115 + 9 1143 1144 1185 1184 1116 + 9 1144 1145 1186 1185 1117 + 9 1145 1146 1187 1186 1118 + 9 1146 1147 1188 1187 1119 + 9 1148 1149 1190 1189 1120 + 9 1149 1150 1191 1190 1121 + 9 1150 1151 1192 1191 1122 + 9 1151 1152 1193 1192 1123 + 9 1152 1153 1194 1193 1124 + 9 1153 1154 1195 1194 1125 + 9 1154 1155 1196 1195 1126 + 9 1155 1156 1197 1196 1127 + 9 1156 1157 1198 1197 1128 + 9 1157 1158 1199 1198 1129 + 9 1158 1159 1200 1199 1130 + 9 1159 1160 1201 1200 1131 + 9 1160 1161 1202 1201 1132 + 9 1161 1162 1203 1202 1133 + 9 1162 1163 1204 1203 1134 + 9 1163 1164 1205 1204 1135 + 9 1164 1165 1206 1205 1136 + 9 1165 1166 1207 1206 1137 + 9 1166 1167 1208 1207 1138 + 9 1167 1168 1209 1208 1139 + 9 1168 1169 1210 1209 1140 + 9 1169 1170 1211 1210 1141 + 9 1170 1171 1212 1211 1142 + 9 1171 1172 1213 1212 1143 + 9 1172 1173 1214 1213 1144 + 9 1173 1174 1215 1214 1145 + 9 1174 1175 1216 1215 1146 + 9 1175 1176 1217 1216 1147 + 9 1176 1177 1218 1217 1148 + 9 1177 1178 1219 1218 1149 + 9 1178 1179 1220 1219 1150 + 9 1179 1180 1221 1220 1151 + 9 1180 1181 1222 1221 1152 + 9 1181 1182 1223 1222 1153 + 9 1182 1183 1224 1223 1154 + 9 1183 1184 1225 1224 1155 + 9 1184 1185 1226 1225 1156 + 9 1185 1186 1227 1226 1157 + 9 1186 1187 1228 1227 1158 + 9 1187 1188 1229 1228 1159 + 9 1189 1190 1231 1230 1160 + 9 1190 1191 1232 1231 1161 + 9 1191 1192 1233 1232 1162 + 9 1192 1193 1234 1233 1163 + 9 1193 1194 1235 1234 1164 + 9 1194 1195 1236 1235 1165 + 9 1195 1196 1237 1236 1166 + 9 1196 1197 1238 1237 1167 + 9 1197 1198 1239 1238 1168 + 9 1198 1199 1240 1239 1169 + 9 1199 1200 1241 1240 1170 + 9 1200 1201 1242 1241 1171 + 9 1201 1202 1243 1242 1172 + 9 1202 1203 1244 1243 1173 + 9 1203 1204 1245 1244 1174 + 9 1204 1205 1246 1245 1175 + 9 1205 1206 1247 1246 1176 + 9 1206 1207 1248 1247 1177 + 9 1207 1208 1249 1248 1178 + 9 1208 1209 1250 1249 1179 + 9 1209 1210 1251 1250 1180 + 9 1210 1211 1252 1251 1181 + 9 1211 1212 1253 1252 1182 + 9 1212 1213 1254 1253 1183 + 9 1213 1214 1255 1254 1184 + 9 1214 1215 1256 1255 1185 + 9 1215 1216 1257 1256 1186 + 9 1216 1217 1258 1257 1187 + 9 1217 1218 1259 1258 1188 + 9 1218 1219 1260 1259 1189 + 9 1219 1220 1261 1260 1190 + 9 1220 1221 1262 1261 1191 + 9 1221 1222 1263 1262 1192 + 9 1222 1223 1264 1263 1193 + 9 1223 1224 1265 1264 1194 + 9 1224 1225 1266 1265 1195 + 9 1225 1226 1267 1266 1196 + 9 1226 1227 1268 1267 1197 + 9 1227 1228 1269 1268 1198 + 9 1228 1229 1270 1269 1199 + 9 1230 1231 1272 1271 1200 + 9 1231 1232 1273 1272 1201 + 9 1232 1233 1274 1273 1202 + 9 1233 1234 1275 1274 1203 + 9 1234 1235 1276 1275 1204 + 9 1235 1236 1277 1276 1205 + 9 1236 1237 1278 1277 1206 + 9 1237 1238 1279 1278 1207 + 9 1238 1239 1280 1279 1208 + 9 1239 1240 1281 1280 1209 + 9 1240 1241 1282 1281 1210 + 9 1241 1242 1283 1282 1211 + 9 1242 1243 1284 1283 1212 + 9 1243 1244 1285 1284 1213 + 9 1244 1245 1286 1285 1214 + 9 1245 1246 1287 1286 1215 + 9 1246 1247 1288 1287 1216 + 9 1247 1248 1289 1288 1217 + 9 1248 1249 1290 1289 1218 + 9 1249 1250 1291 1290 1219 + 9 1250 1251 1292 1291 1220 + 9 1251 1252 1293 1292 1221 + 9 1252 1253 1294 1293 1222 + 9 1253 1254 1295 1294 1223 + 9 1254 1255 1296 1295 1224 + 9 1255 1256 1297 1296 1225 + 9 1256 1257 1298 1297 1226 + 9 1257 1258 1299 1298 1227 + 9 1258 1259 1300 1299 1228 + 9 1259 1260 1301 1300 1229 + 9 1260 1261 1302 1301 1230 + 9 1261 1262 1303 1302 1231 + 9 1262 1263 1304 1303 1232 + 9 1263 1264 1305 1304 1233 + 9 1264 1265 1306 1305 1234 + 9 1265 1266 1307 1306 1235 + 9 1266 1267 1308 1307 1236 + 9 1267 1268 1309 1308 1237 + 9 1268 1269 1310 1309 1238 + 9 1269 1270 1311 1310 1239 + 9 1271 1272 1313 1312 1240 + 9 1272 1273 1314 1313 1241 + 9 1273 1274 1315 1314 1242 + 9 1274 1275 1316 1315 1243 + 9 1275 1276 1317 1316 1244 + 9 1276 1277 1318 1317 1245 + 9 1277 1278 1319 1318 1246 + 9 1278 1279 1320 1319 1247 + 9 1279 1280 1321 1320 1248 + 9 1280 1281 1322 1321 1249 + 9 1281 1282 1323 1322 1250 + 9 1282 1283 1324 1323 1251 + 9 1283 1284 1325 1324 1252 + 9 1284 1285 1326 1325 1253 + 9 1285 1286 1327 1326 1254 + 9 1286 1287 1328 1327 1255 + 9 1287 1288 1329 1328 1256 + 9 1288 1289 1330 1329 1257 + 9 1289 1290 1331 1330 1258 + 9 1290 1291 1332 1331 1259 + 9 1291 1292 1333 1332 1260 + 9 1292 1293 1334 1333 1261 + 9 1293 1294 1335 1334 1262 + 9 1294 1295 1336 1335 1263 + 9 1295 1296 1337 1336 1264 + 9 1296 1297 1338 1337 1265 + 9 1297 1298 1339 1338 1266 + 9 1298 1299 1340 1339 1267 + 9 1299 1300 1341 1340 1268 + 9 1300 1301 1342 1341 1269 + 9 1301 1302 1343 1342 1270 + 9 1302 1303 1344 1343 1271 + 9 1303 1304 1345 1344 1272 + 9 1304 1305 1346 1345 1273 + 9 1305 1306 1347 1346 1274 + 9 1306 1307 1348 1347 1275 + 9 1307 1308 1349 1348 1276 + 9 1308 1309 1350 1349 1277 + 9 1309 1310 1351 1350 1278 + 9 1310 1311 1352 1351 1279 + 9 1312 1313 1354 1353 1280 + 9 1313 1314 1355 1354 1281 + 9 1314 1315 1356 1355 1282 + 9 1315 1316 1357 1356 1283 + 9 1316 1317 1358 1357 1284 + 9 1317 1318 1359 1358 1285 + 9 1318 1319 1360 1359 1286 + 9 1319 1320 1361 1360 1287 + 9 1320 1321 1362 1361 1288 + 9 1321 1322 1363 1362 1289 + 9 1322 1323 1364 1363 1290 + 9 1323 1324 1365 1364 1291 + 9 1324 1325 1366 1365 1292 + 9 1325 1326 1367 1366 1293 + 9 1326 1327 1368 1367 1294 + 9 1327 1328 1369 1368 1295 + 9 1328 1329 1370 1369 1296 + 9 1329 1330 1371 1370 1297 + 9 1330 1331 1372 1371 1298 + 9 1331 1332 1373 1372 1299 + 9 1332 1333 1374 1373 1300 + 9 1333 1334 1375 1374 1301 + 9 1334 1335 1376 1375 1302 + 9 1335 1336 1377 1376 1303 + 9 1336 1337 1378 1377 1304 + 9 1337 1338 1379 1378 1305 + 9 1338 1339 1380 1379 1306 + 9 1339 1340 1381 1380 1307 + 9 1340 1341 1382 1381 1308 + 9 1341 1342 1383 1382 1309 + 9 1342 1343 1384 1383 1310 + 9 1343 1344 1385 1384 1311 + 9 1344 1345 1386 1385 1312 + 9 1345 1346 1387 1386 1313 + 9 1346 1347 1388 1387 1314 + 9 1347 1348 1389 1388 1315 + 9 1348 1349 1390 1389 1316 + 9 1349 1350 1391 1390 1317 + 9 1350 1351 1392 1391 1318 + 9 1351 1352 1393 1392 1319 + 9 1353 1354 1395 1394 1320 + 9 1354 1355 1396 1395 1321 + 9 1355 1356 1397 1396 1322 + 9 1356 1357 1398 1397 1323 + 9 1357 1358 1399 1398 1324 + 9 1358 1359 1400 1399 1325 + 9 1359 1360 1401 1400 1326 + 9 1360 1361 1402 1401 1327 + 9 1361 1362 1403 1402 1328 + 9 1362 1363 1404 1403 1329 + 9 1363 1364 1405 1404 1330 + 9 1364 1365 1406 1405 1331 + 9 1365 1366 1407 1406 1332 + 9 1366 1367 1408 1407 1333 + 9 1367 1368 1409 1408 1334 + 9 1368 1369 1410 1409 1335 + 9 1369 1370 1411 1410 1336 + 9 1370 1371 1412 1411 1337 + 9 1371 1372 1413 1412 1338 + 9 1372 1373 1414 1413 1339 + 9 1373 1374 1415 1414 1340 + 9 1374 1375 1416 1415 1341 + 9 1375 1376 1417 1416 1342 + 9 1376 1377 1418 1417 1343 + 9 1377 1378 1419 1418 1344 + 9 1378 1379 1420 1419 1345 + 9 1379 1380 1421 1420 1346 + 9 1380 1381 1422 1421 1347 + 9 1381 1382 1423 1422 1348 + 9 1382 1383 1424 1423 1349 + 9 1383 1384 1425 1424 1350 + 9 1384 1385 1426 1425 1351 + 9 1385 1386 1427 1426 1352 + 9 1386 1387 1428 1427 1353 + 9 1387 1388 1429 1428 1354 + 9 1388 1389 1430 1429 1355 + 9 1389 1390 1431 1430 1356 + 9 1390 1391 1432 1431 1357 + 9 1391 1392 1433 1432 1358 + 9 1392 1393 1434 1433 1359 + 9 1394 1395 1436 1435 1360 + 9 1395 1396 1437 1436 1361 + 9 1396 1397 1438 1437 1362 + 9 1397 1398 1439 1438 1363 + 9 1398 1399 1440 1439 1364 + 9 1399 1400 1441 1440 1365 + 9 1400 1401 1442 1441 1366 + 9 1401 1402 1443 1442 1367 + 9 1402 1403 1444 1443 1368 + 9 1403 1404 1445 1444 1369 + 9 1404 1405 1446 1445 1370 + 9 1405 1406 1447 1446 1371 + 9 1406 1407 1448 1447 1372 + 9 1407 1408 1449 1448 1373 + 9 1408 1409 1450 1449 1374 + 9 1409 1410 1451 1450 1375 + 9 1410 1411 1452 1451 1376 + 9 1411 1412 1453 1452 1377 + 9 1412 1413 1454 1453 1378 + 9 1413 1414 1455 1454 1379 + 9 1414 1415 1456 1455 1380 + 9 1415 1416 1457 1456 1381 + 9 1416 1417 1458 1457 1382 + 9 1417 1418 1459 1458 1383 + 9 1418 1419 1460 1459 1384 + 9 1419 1420 1461 1460 1385 + 9 1420 1421 1462 1461 1386 + 9 1421 1422 1463 1462 1387 + 9 1422 1423 1464 1463 1388 + 9 1423 1424 1465 1464 1389 + 9 1424 1425 1466 1465 1390 + 9 1425 1426 1467 1466 1391 + 9 1426 1427 1468 1467 1392 + 9 1427 1428 1469 1468 1393 + 9 1428 1429 1470 1469 1394 + 9 1429 1430 1471 1470 1395 + 9 1430 1431 1472 1471 1396 + 9 1431 1432 1473 1472 1397 + 9 1432 1433 1474 1473 1398 + 9 1433 1434 1475 1474 1399 + 9 1435 1436 1477 1476 1400 + 9 1436 1437 1478 1477 1401 + 9 1437 1438 1479 1478 1402 + 9 1438 1439 1480 1479 1403 + 9 1439 1440 1481 1480 1404 + 9 1440 1441 1482 1481 1405 + 9 1441 1442 1483 1482 1406 + 9 1442 1443 1484 1483 1407 + 9 1443 1444 1485 1484 1408 + 9 1444 1445 1486 1485 1409 + 9 1445 1446 1487 1486 1410 + 9 1446 1447 1488 1487 1411 + 9 1447 1448 1489 1488 1412 + 9 1448 1449 1490 1489 1413 + 9 1449 1450 1491 1490 1414 + 9 1450 1451 1492 1491 1415 + 9 1451 1452 1493 1492 1416 + 9 1452 1453 1494 1493 1417 + 9 1453 1454 1495 1494 1418 + 9 1454 1455 1496 1495 1419 + 9 1455 1456 1497 1496 1420 + 9 1456 1457 1498 1497 1421 + 9 1457 1458 1499 1498 1422 + 9 1458 1459 1500 1499 1423 + 9 1459 1460 1501 1500 1424 + 9 1460 1461 1502 1501 1425 + 9 1461 1462 1503 1502 1426 + 9 1462 1463 1504 1503 1427 + 9 1463 1464 1505 1504 1428 + 9 1464 1465 1506 1505 1429 + 9 1465 1466 1507 1506 1430 + 9 1466 1467 1508 1507 1431 + 9 1467 1468 1509 1508 1432 + 9 1468 1469 1510 1509 1433 + 9 1469 1470 1511 1510 1434 + 9 1470 1471 1512 1511 1435 + 9 1471 1472 1513 1512 1436 + 9 1472 1473 1514 1513 1437 + 9 1473 1474 1515 1514 1438 + 9 1474 1475 1516 1515 1439 + 9 1476 1477 1518 1517 1440 + 9 1477 1478 1519 1518 1441 + 9 1478 1479 1520 1519 1442 + 9 1479 1480 1521 1520 1443 + 9 1480 1481 1522 1521 1444 + 9 1481 1482 1523 1522 1445 + 9 1482 1483 1524 1523 1446 + 9 1483 1484 1525 1524 1447 + 9 1484 1485 1526 1525 1448 + 9 1485 1486 1527 1526 1449 + 9 1486 1487 1528 1527 1450 + 9 1487 1488 1529 1528 1451 + 9 1488 1489 1530 1529 1452 + 9 1489 1490 1531 1530 1453 + 9 1490 1491 1532 1531 1454 + 9 1491 1492 1533 1532 1455 + 9 1492 1493 1534 1533 1456 + 9 1493 1494 1535 1534 1457 + 9 1494 1495 1536 1535 1458 + 9 1495 1496 1537 1536 1459 + 9 1496 1497 1538 1537 1460 + 9 1497 1498 1539 1538 1461 + 9 1498 1499 1540 1539 1462 + 9 1499 1500 1541 1540 1463 + 9 1500 1501 1542 1541 1464 + 9 1501 1502 1543 1542 1465 + 9 1502 1503 1544 1543 1466 + 9 1503 1504 1545 1544 1467 + 9 1504 1505 1546 1545 1468 + 9 1505 1506 1547 1546 1469 + 9 1506 1507 1548 1547 1470 + 9 1507 1508 1549 1548 1471 + 9 1508 1509 1550 1549 1472 + 9 1509 1510 1551 1550 1473 + 9 1510 1511 1552 1551 1474 + 9 1511 1512 1553 1552 1475 + 9 1512 1513 1554 1553 1476 + 9 1513 1514 1555 1554 1477 + 9 1514 1515 1556 1555 1478 + 9 1515 1516 1557 1556 1479 + 9 1517 1518 1559 1558 1480 + 9 1518 1519 1560 1559 1481 + 9 1519 1520 1561 1560 1482 + 9 1520 1521 1562 1561 1483 + 9 1521 1522 1563 1562 1484 + 9 1522 1523 1564 1563 1485 + 9 1523 1524 1565 1564 1486 + 9 1524 1525 1566 1565 1487 + 9 1525 1526 1567 1566 1488 + 9 1526 1527 1568 1567 1489 + 9 1527 1528 1569 1568 1490 + 9 1528 1529 1570 1569 1491 + 9 1529 1530 1571 1570 1492 + 9 1530 1531 1572 1571 1493 + 9 1531 1532 1573 1572 1494 + 9 1532 1533 1574 1573 1495 + 9 1533 1534 1575 1574 1496 + 9 1534 1535 1576 1575 1497 + 9 1535 1536 1577 1576 1498 + 9 1536 1537 1578 1577 1499 + 9 1537 1538 1579 1578 1500 + 9 1538 1539 1580 1579 1501 + 9 1539 1540 1581 1580 1502 + 9 1540 1541 1582 1581 1503 + 9 1541 1542 1583 1582 1504 + 9 1542 1543 1584 1583 1505 + 9 1543 1544 1585 1584 1506 + 9 1544 1545 1586 1585 1507 + 9 1545 1546 1587 1586 1508 + 9 1546 1547 1588 1587 1509 + 9 1547 1548 1589 1588 1510 + 9 1548 1549 1590 1589 1511 + 9 1549 1550 1591 1590 1512 + 9 1550 1551 1592 1591 1513 + 9 1551 1552 1593 1592 1514 + 9 1552 1553 1594 1593 1515 + 9 1553 1554 1595 1594 1516 + 9 1554 1555 1596 1595 1517 + 9 1555 1556 1597 1596 1518 + 9 1556 1557 1598 1597 1519 + 9 1558 1559 1600 1599 1520 + 9 1559 1560 1601 1600 1521 + 9 1560 1561 1602 1601 1522 + 9 1561 1562 1603 1602 1523 + 9 1562 1563 1604 1603 1524 + 9 1563 1564 1605 1604 1525 + 9 1564 1565 1606 1605 1526 + 9 1565 1566 1607 1606 1527 + 9 1566 1567 1608 1607 1528 + 9 1567 1568 1609 1608 1529 + 9 1568 1569 1610 1609 1530 + 9 1569 1570 1611 1610 1531 + 9 1570 1571 1612 1611 1532 + 9 1571 1572 1613 1612 1533 + 9 1572 1573 1614 1613 1534 + 9 1573 1574 1615 1614 1535 + 9 1574 1575 1616 1615 1536 + 9 1575 1576 1617 1616 1537 + 9 1576 1577 1618 1617 1538 + 9 1577 1578 1619 1618 1539 + 9 1578 1579 1620 1619 1540 + 9 1579 1580 1621 1620 1541 + 9 1580 1581 1622 1621 1542 + 9 1581 1582 1623 1622 1543 + 9 1582 1583 1624 1623 1544 + 9 1583 1584 1625 1624 1545 + 9 1584 1585 1626 1625 1546 + 9 1585 1586 1627 1626 1547 + 9 1586 1587 1628 1627 1548 + 9 1587 1588 1629 1628 1549 + 9 1588 1589 1630 1629 1550 + 9 1589 1590 1631 1630 1551 + 9 1590 1591 1632 1631 1552 + 9 1591 1592 1633 1632 1553 + 9 1592 1593 1634 1633 1554 + 9 1593 1594 1635 1634 1555 + 9 1594 1595 1636 1635 1556 + 9 1595 1596 1637 1636 1557 + 9 1596 1597 1638 1637 1558 + 9 1597 1598 1639 1638 1559 + 9 1599 1600 1641 1640 1560 + 9 1600 1601 1642 1641 1561 + 9 1601 1602 1643 1642 1562 + 9 1602 1603 1644 1643 1563 + 9 1603 1604 1645 1644 1564 + 9 1604 1605 1646 1645 1565 + 9 1605 1606 1647 1646 1566 + 9 1606 1607 1648 1647 1567 + 9 1607 1608 1649 1648 1568 + 9 1608 1609 1650 1649 1569 + 9 1609 1610 1651 1650 1570 + 9 1610 1611 1652 1651 1571 + 9 1611 1612 1653 1652 1572 + 9 1612 1613 1654 1653 1573 + 9 1613 1614 1655 1654 1574 + 9 1614 1615 1656 1655 1575 + 9 1615 1616 1657 1656 1576 + 9 1616 1617 1658 1657 1577 + 9 1617 1618 1659 1658 1578 + 9 1618 1619 1660 1659 1579 + 9 1619 1620 1661 1660 1580 + 9 1620 1621 1662 1661 1581 + 9 1621 1622 1663 1662 1582 + 9 1622 1623 1664 1663 1583 + 9 1623 1624 1665 1664 1584 + 9 1624 1625 1666 1665 1585 + 9 1625 1626 1667 1666 1586 + 9 1626 1627 1668 1667 1587 + 9 1627 1628 1669 1668 1588 + 9 1628 1629 1670 1669 1589 + 9 1629 1630 1671 1670 1590 + 9 1630 1631 1672 1671 1591 + 9 1631 1632 1673 1672 1592 + 9 1632 1633 1674 1673 1593 + 9 1633 1634 1675 1674 1594 + 9 1634 1635 1676 1675 1595 + 9 1635 1636 1677 1676 1596 + 9 1636 1637 1678 1677 1597 + 9 1637 1638 1679 1678 1598 + 9 1638 1639 1680 1679 1599 + 9 1640 1641 1682 1681 1600 + 9 1641 1642 1683 1682 1601 + 9 1642 1643 1684 1683 1602 + 9 1643 1644 1685 1684 1603 + 9 1644 1645 1686 1685 1604 + 9 1645 1646 1687 1686 1605 + 9 1646 1647 1688 1687 1606 + 9 1647 1648 1689 1688 1607 + 9 1648 1649 1690 1689 1608 + 9 1649 1650 1691 1690 1609 + 9 1650 1651 1692 1691 1610 + 9 1651 1652 1693 1692 1611 + 9 1652 1653 1694 1693 1612 + 9 1653 1654 1695 1694 1613 + 9 1654 1655 1696 1695 1614 + 9 1655 1656 1697 1696 1615 + 9 1656 1657 1698 1697 1616 + 9 1657 1658 1699 1698 1617 + 9 1658 1659 1700 1699 1618 + 9 1659 1660 1701 1700 1619 + 9 1660 1661 1702 1701 1620 + 9 1661 1662 1703 1702 1621 + 9 1662 1663 1704 1703 1622 + 9 1663 1664 1705 1704 1623 + 9 1664 1665 1706 1705 1624 + 9 1665 1666 1707 1706 1625 + 9 1666 1667 1708 1707 1626 + 9 1667 1668 1709 1708 1627 + 9 1668 1669 1710 1709 1628 + 9 1669 1670 1711 1710 1629 + 9 1670 1671 1712 1711 1630 + 9 1671 1672 1713 1712 1631 + 9 1672 1673 1714 1713 1632 + 9 1673 1674 1715 1714 1633 + 9 1674 1675 1716 1715 1634 + 9 1675 1676 1717 1716 1635 + 9 1676 1677 1718 1717 1636 + 9 1677 1678 1719 1718 1637 + 9 1678 1679 1720 1719 1638 + 9 1679 1680 1721 1720 1639 + 9 1681 1682 1723 1722 1640 + 9 1682 1683 1724 1723 1641 + 9 1683 1684 1725 1724 1642 + 9 1684 1685 1726 1725 1643 + 9 1685 1686 1727 1726 1644 + 9 1686 1687 1728 1727 1645 + 9 1687 1688 1729 1728 1646 + 9 1688 1689 1730 1729 1647 + 9 1689 1690 1731 1730 1648 + 9 1690 1691 1732 1731 1649 + 9 1691 1692 1733 1732 1650 + 9 1692 1693 1734 1733 1651 + 9 1693 1694 1735 1734 1652 + 9 1694 1695 1736 1735 1653 + 9 1695 1696 1737 1736 1654 + 9 1696 1697 1738 1737 1655 + 9 1697 1698 1739 1738 1656 + 9 1698 1699 1740 1739 1657 + 9 1699 1700 1741 1740 1658 + 9 1700 1701 1742 1741 1659 + 9 1701 1702 1743 1742 1660 + 9 1702 1703 1744 1743 1661 + 9 1703 1704 1745 1744 1662 + 9 1704 1705 1746 1745 1663 + 9 1705 1706 1747 1746 1664 + 9 1706 1707 1748 1747 1665 + 9 1707 1708 1749 1748 1666 + 9 1708 1709 1750 1749 1667 + 9 1709 1710 1751 1750 1668 + 9 1710 1711 1752 1751 1669 + 9 1711 1712 1753 1752 1670 + 9 1712 1713 1754 1753 1671 + 9 1713 1714 1755 1754 1672 + 9 1714 1715 1756 1755 1673 + 9 1715 1716 1757 1756 1674 + 9 1716 1717 1758 1757 1675 + 9 1717 1718 1759 1758 1676 + 9 1718 1719 1760 1759 1677 + 9 1719 1720 1761 1760 1678 + 9 1720 1721 1762 1761 1679 + 9 1722 1723 1764 1763 1680 + 9 1723 1724 1765 1764 1681 + 9 1724 1725 1766 1765 1682 + 9 1725 1726 1767 1766 1683 + 9 1726 1727 1768 1767 1684 + 9 1727 1728 1769 1768 1685 + 9 1728 1729 1770 1769 1686 + 9 1729 1730 1771 1770 1687 + 9 1730 1731 1772 1771 1688 + 9 1731 1732 1773 1772 1689 + 9 1732 1733 1774 1773 1690 + 9 1733 1734 1775 1774 1691 + 9 1734 1735 1776 1775 1692 + 9 1735 1736 1777 1776 1693 + 9 1736 1737 1778 1777 1694 + 9 1737 1738 1779 1778 1695 + 9 1738 1739 1780 1779 1696 + 9 1739 1740 1781 1780 1697 + 9 1740 1741 1782 1781 1698 + 9 1741 1742 1783 1782 1699 + 9 1742 1743 1784 1783 1700 + 9 1743 1744 1785 1784 1701 + 9 1744 1745 1786 1785 1702 + 9 1745 1746 1787 1786 1703 + 9 1746 1747 1788 1787 1704 + 9 1747 1748 1789 1788 1705 + 9 1748 1749 1790 1789 1706 + 9 1749 1750 1791 1790 1707 + 9 1750 1751 1792 1791 1708 + 9 1751 1752 1793 1792 1709 + 9 1752 1753 1794 1793 1710 + 9 1753 1754 1795 1794 1711 + 9 1754 1755 1796 1795 1712 + 9 1755 1756 1797 1796 1713 + 9 1756 1757 1798 1797 1714 + 9 1757 1758 1799 1798 1715 + 9 1758 1759 1800 1799 1716 + 9 1759 1760 1801 1800 1717 + 9 1760 1761 1802 1801 1718 + 9 1761 1762 1803 1802 1719 + 9 1763 1764 1805 1804 1720 + 9 1764 1765 1806 1805 1721 + 9 1765 1766 1807 1806 1722 + 9 1766 1767 1808 1807 1723 + 9 1767 1768 1809 1808 1724 + 9 1768 1769 1810 1809 1725 + 9 1769 1770 1811 1810 1726 + 9 1770 1771 1812 1811 1727 + 9 1771 1772 1813 1812 1728 + 9 1772 1773 1814 1813 1729 + 9 1773 1774 1815 1814 1730 + 9 1774 1775 1816 1815 1731 + 9 1775 1776 1817 1816 1732 + 9 1776 1777 1818 1817 1733 + 9 1777 1778 1819 1818 1734 + 9 1778 1779 1820 1819 1735 + 9 1779 1780 1821 1820 1736 + 9 1780 1781 1822 1821 1737 + 9 1781 1782 1823 1822 1738 + 9 1782 1783 1824 1823 1739 + 9 1783 1784 1825 1824 1740 + 9 1784 1785 1826 1825 1741 + 9 1785 1786 1827 1826 1742 + 9 1786 1787 1828 1827 1743 + 9 1787 1788 1829 1828 1744 + 9 1788 1789 1830 1829 1745 + 9 1789 1790 1831 1830 1746 + 9 1790 1791 1832 1831 1747 + 9 1791 1792 1833 1832 1748 + 9 1792 1793 1834 1833 1749 + 9 1793 1794 1835 1834 1750 + 9 1794 1795 1836 1835 1751 + 9 1795 1796 1837 1836 1752 + 9 1796 1797 1838 1837 1753 + 9 1797 1798 1839 1838 1754 + 9 1798 1799 1840 1839 1755 + 9 1799 1800 1841 1840 1756 + 9 1800 1801 1842 1841 1757 + 9 1801 1802 1843 1842 1758 + 9 1802 1803 1844 1843 1759 + 9 1804 1805 1846 1845 1760 + 9 1805 1806 1847 1846 1761 + 9 1806 1807 1848 1847 1762 + 9 1807 1808 1849 1848 1763 + 9 1808 1809 1850 1849 1764 + 9 1809 1810 1851 1850 1765 + 9 1810 1811 1852 1851 1766 + 9 1811 1812 1853 1852 1767 + 9 1812 1813 1854 1853 1768 + 9 1813 1814 1855 1854 1769 + 9 1814 1815 1856 1855 1770 + 9 1815 1816 1857 1856 1771 + 9 1816 1817 1858 1857 1772 + 9 1817 1818 1859 1858 1773 + 9 1818 1819 1860 1859 1774 + 9 1819 1820 1861 1860 1775 + 9 1820 1821 1862 1861 1776 + 9 1821 1822 1863 1862 1777 + 9 1822 1823 1864 1863 1778 + 9 1823 1824 1865 1864 1779 + 9 1824 1825 1866 1865 1780 + 9 1825 1826 1867 1866 1781 + 9 1826 1827 1868 1867 1782 + 9 1827 1828 1869 1868 1783 + 9 1828 1829 1870 1869 1784 + 9 1829 1830 1871 1870 1785 + 9 1830 1831 1872 1871 1786 + 9 1831 1832 1873 1872 1787 + 9 1832 1833 1874 1873 1788 + 9 1833 1834 1875 1874 1789 + 9 1834 1835 1876 1875 1790 + 9 1835 1836 1877 1876 1791 + 9 1836 1837 1878 1877 1792 + 9 1837 1838 1879 1878 1793 + 9 1838 1839 1880 1879 1794 + 9 1839 1840 1881 1880 1795 + 9 1840 1841 1882 1881 1796 + 9 1841 1842 1883 1882 1797 + 9 1842 1843 1884 1883 1798 + 9 1843 1844 1885 1884 1799 + 9 1845 1846 1887 1886 1800 + 9 1846 1847 1888 1887 1801 + 9 1847 1848 1889 1888 1802 + 9 1848 1849 1890 1889 1803 + 9 1849 1850 1891 1890 1804 + 9 1850 1851 1892 1891 1805 + 9 1851 1852 1893 1892 1806 + 9 1852 1853 1894 1893 1807 + 9 1853 1854 1895 1894 1808 + 9 1854 1855 1896 1895 1809 + 9 1855 1856 1897 1896 1810 + 9 1856 1857 1898 1897 1811 + 9 1857 1858 1899 1898 1812 + 9 1858 1859 1900 1899 1813 + 9 1859 1860 1901 1900 1814 + 9 1860 1861 1902 1901 1815 + 9 1861 1862 1903 1902 1816 + 9 1862 1863 1904 1903 1817 + 9 1863 1864 1905 1904 1818 + 9 1864 1865 1906 1905 1819 + 9 1865 1866 1907 1906 1820 + 9 1866 1867 1908 1907 1821 + 9 1867 1868 1909 1908 1822 + 9 1868 1869 1910 1909 1823 + 9 1869 1870 1911 1910 1824 + 9 1870 1871 1912 1911 1825 + 9 1871 1872 1913 1912 1826 + 9 1872 1873 1914 1913 1827 + 9 1873 1874 1915 1914 1828 + 9 1874 1875 1916 1915 1829 + 9 1875 1876 1917 1916 1830 + 9 1876 1877 1918 1917 1831 + 9 1877 1878 1919 1918 1832 + 9 1878 1879 1920 1919 1833 + 9 1879 1880 1921 1920 1834 + 9 1880 1881 1922 1921 1835 + 9 1881 1882 1923 1922 1836 + 9 1882 1883 1924 1923 1837 + 9 1883 1884 1925 1924 1838 + 9 1884 1885 1926 1925 1839 + 9 1886 1887 1928 1927 1840 + 9 1887 1888 1929 1928 1841 + 9 1888 1889 1930 1929 1842 + 9 1889 1890 1931 1930 1843 + 9 1890 1891 1932 1931 1844 + 9 1891 1892 1933 1932 1845 + 9 1892 1893 1934 1933 1846 + 9 1893 1894 1935 1934 1847 + 9 1894 1895 1936 1935 1848 + 9 1895 1896 1937 1936 1849 + 9 1896 1897 1938 1937 1850 + 9 1897 1898 1939 1938 1851 + 9 1898 1899 1940 1939 1852 + 9 1899 1900 1941 1940 1853 + 9 1900 1901 1942 1941 1854 + 9 1901 1902 1943 1942 1855 + 9 1902 1903 1944 1943 1856 + 9 1903 1904 1945 1944 1857 + 9 1904 1905 1946 1945 1858 + 9 1905 1906 1947 1946 1859 + 9 1906 1907 1948 1947 1860 + 9 1907 1908 1949 1948 1861 + 9 1908 1909 1950 1949 1862 + 9 1909 1910 1951 1950 1863 + 9 1910 1911 1952 1951 1864 + 9 1911 1912 1953 1952 1865 + 9 1912 1913 1954 1953 1866 + 9 1913 1914 1955 1954 1867 + 9 1914 1915 1956 1955 1868 + 9 1915 1916 1957 1956 1869 + 9 1916 1917 1958 1957 1870 + 9 1917 1918 1959 1958 1871 + 9 1918 1919 1960 1959 1872 + 9 1919 1920 1961 1960 1873 + 9 1920 1921 1962 1961 1874 + 9 1921 1922 1963 1962 1875 + 9 1922 1923 1964 1963 1876 + 9 1923 1924 1965 1964 1877 + 9 1924 1925 1966 1965 1878 + 9 1925 1926 1967 1966 1879 + 9 1927 1928 1969 1968 1880 + 9 1928 1929 1970 1969 1881 + 9 1929 1930 1971 1970 1882 + 9 1930 1931 1972 1971 1883 + 9 1931 1932 1973 1972 1884 + 9 1932 1933 1974 1973 1885 + 9 1933 1934 1975 1974 1886 + 9 1934 1935 1976 1975 1887 + 9 1935 1936 1977 1976 1888 + 9 1936 1937 1978 1977 1889 + 9 1937 1938 1979 1978 1890 + 9 1938 1939 1980 1979 1891 + 9 1939 1940 1981 1980 1892 + 9 1940 1941 1982 1981 1893 + 9 1941 1942 1983 1982 1894 + 9 1942 1943 1984 1983 1895 + 9 1943 1944 1985 1984 1896 + 9 1944 1945 1986 1985 1897 + 9 1945 1946 1987 1986 1898 + 9 1946 1947 1988 1987 1899 + 9 1947 1948 1989 1988 1900 + 9 1948 1949 1990 1989 1901 + 9 1949 1950 1991 1990 1902 + 9 1950 1951 1992 1991 1903 + 9 1951 1952 1993 1992 1904 + 9 1952 1953 1994 1993 1905 + 9 1953 1954 1995 1994 1906 + 9 1954 1955 1996 1995 1907 + 9 1955 1956 1997 1996 1908 + 9 1956 1957 1998 1997 1909 + 9 1957 1958 1999 1998 1910 + 9 1958 1959 2000 1999 1911 + 9 1959 1960 2001 2000 1912 + 9 1960 1961 2002 2001 1913 + 9 1961 1962 2003 2002 1914 + 9 1962 1963 2004 2003 1915 + 9 1963 1964 2005 2004 1916 + 9 1964 1965 2006 2005 1917 + 9 1965 1966 2007 2006 1918 + 9 1966 1967 2008 2007 1919 + 9 1968 1969 2010 2009 1920 + 9 1969 1970 2011 2010 1921 + 9 1970 1971 2012 2011 1922 + 9 1971 1972 2013 2012 1923 + 9 1972 1973 2014 2013 1924 + 9 1973 1974 2015 2014 1925 + 9 1974 1975 2016 2015 1926 + 9 1975 1976 2017 2016 1927 + 9 1976 1977 2018 2017 1928 + 9 1977 1978 2019 2018 1929 + 9 1978 1979 2020 2019 1930 + 9 1979 1980 2021 2020 1931 + 9 1980 1981 2022 2021 1932 + 9 1981 1982 2023 2022 1933 + 9 1982 1983 2024 2023 1934 + 9 1983 1984 2025 2024 1935 + 9 1984 1985 2026 2025 1936 + 9 1985 1986 2027 2026 1937 + 9 1986 1987 2028 2027 1938 + 9 1987 1988 2029 2028 1939 + 9 1988 1989 2030 2029 1940 + 9 1989 1990 2031 2030 1941 + 9 1990 1991 2032 2031 1942 + 9 1991 1992 2033 2032 1943 + 9 1992 1993 2034 2033 1944 + 9 1993 1994 2035 2034 1945 + 9 1994 1995 2036 2035 1946 + 9 1995 1996 2037 2036 1947 + 9 1996 1997 2038 2037 1948 + 9 1997 1998 2039 2038 1949 + 9 1998 1999 2040 2039 1950 + 9 1999 2000 2041 2040 1951 + 9 2000 2001 2042 2041 1952 + 9 2001 2002 2043 2042 1953 + 9 2002 2003 2044 2043 1954 + 9 2003 2004 2045 2044 1955 + 9 2004 2005 2046 2045 1956 + 9 2005 2006 2047 2046 1957 + 9 2006 2007 2048 2047 1958 + 9 2007 2008 2049 2048 1959 + 9 2009 2010 2051 2050 1960 + 9 2010 2011 2052 2051 1961 + 9 2011 2012 2053 2052 1962 + 9 2012 2013 2054 2053 1963 + 9 2013 2014 2055 2054 1964 + 9 2014 2015 2056 2055 1965 + 9 2015 2016 2057 2056 1966 + 9 2016 2017 2058 2057 1967 + 9 2017 2018 2059 2058 1968 + 9 2018 2019 2060 2059 1969 + 9 2019 2020 2061 2060 1970 + 9 2020 2021 2062 2061 1971 + 9 2021 2022 2063 2062 1972 + 9 2022 2023 2064 2063 1973 + 9 2023 2024 2065 2064 1974 + 9 2024 2025 2066 2065 1975 + 9 2025 2026 2067 2066 1976 + 9 2026 2027 2068 2067 1977 + 9 2027 2028 2069 2068 1978 + 9 2028 2029 2070 2069 1979 + 9 2029 2030 2071 2070 1980 + 9 2030 2031 2072 2071 1981 + 9 2031 2032 2073 2072 1982 + 9 2032 2033 2074 2073 1983 + 9 2033 2034 2075 2074 1984 + 9 2034 2035 2076 2075 1985 + 9 2035 2036 2077 2076 1986 + 9 2036 2037 2078 2077 1987 + 9 2037 2038 2079 2078 1988 + 9 2038 2039 2080 2079 1989 + 9 2039 2040 2081 2080 1990 + 9 2040 2041 2082 2081 1991 + 9 2041 2042 2083 2082 1992 + 9 2042 2043 2084 2083 1993 + 9 2043 2044 2085 2084 1994 + 9 2044 2045 2086 2085 1995 + 9 2045 2046 2087 2086 1996 + 9 2046 2047 2088 2087 1997 + 9 2047 2048 2089 2088 1998 + 9 2048 2049 2090 2089 1999 + 9 2050 2051 2092 2091 2000 + 9 2051 2052 2093 2092 2001 + 9 2052 2053 2094 2093 2002 + 9 2053 2054 2095 2094 2003 + 9 2054 2055 2096 2095 2004 + 9 2055 2056 2097 2096 2005 + 9 2056 2057 2098 2097 2006 + 9 2057 2058 2099 2098 2007 + 9 2058 2059 2100 2099 2008 + 9 2059 2060 2101 2100 2009 + 9 2060 2061 2102 2101 2010 + 9 2061 2062 2103 2102 2011 + 9 2062 2063 2104 2103 2012 + 9 2063 2064 2105 2104 2013 + 9 2064 2065 2106 2105 2014 + 9 2065 2066 2107 2106 2015 + 9 2066 2067 2108 2107 2016 + 9 2067 2068 2109 2108 2017 + 9 2068 2069 2110 2109 2018 + 9 2069 2070 2111 2110 2019 + 9 2070 2071 2112 2111 2020 + 9 2071 2072 2113 2112 2021 + 9 2072 2073 2114 2113 2022 + 9 2073 2074 2115 2114 2023 + 9 2074 2075 2116 2115 2024 + 9 2075 2076 2117 2116 2025 + 9 2076 2077 2118 2117 2026 + 9 2077 2078 2119 2118 2027 + 9 2078 2079 2120 2119 2028 + 9 2079 2080 2121 2120 2029 + 9 2080 2081 2122 2121 2030 + 9 2081 2082 2123 2122 2031 + 9 2082 2083 2124 2123 2032 + 9 2083 2084 2125 2124 2033 + 9 2084 2085 2126 2125 2034 + 9 2085 2086 2127 2126 2035 + 9 2086 2087 2128 2127 2036 + 9 2087 2088 2129 2128 2037 + 9 2088 2089 2130 2129 2038 + 9 2089 2090 2131 2130 2039 + 9 2091 2092 2133 2132 2040 + 9 2092 2093 2134 2133 2041 + 9 2093 2094 2135 2134 2042 + 9 2094 2095 2136 2135 2043 + 9 2095 2096 2137 2136 2044 + 9 2096 2097 2138 2137 2045 + 9 2097 2098 2139 2138 2046 + 9 2098 2099 2140 2139 2047 + 9 2099 2100 2141 2140 2048 + 9 2100 2101 2142 2141 2049 + 9 2101 2102 2143 2142 2050 + 9 2102 2103 2144 2143 2051 + 9 2103 2104 2145 2144 2052 + 9 2104 2105 2146 2145 2053 + 9 2105 2106 2147 2146 2054 + 9 2106 2107 2148 2147 2055 + 9 2107 2108 2149 2148 2056 + 9 2108 2109 2150 2149 2057 + 9 2109 2110 2151 2150 2058 + 9 2110 2111 2152 2151 2059 + 9 2111 2112 2153 2152 2060 + 9 2112 2113 2154 2153 2061 + 9 2113 2114 2155 2154 2062 + 9 2114 2115 2156 2155 2063 + 9 2115 2116 2157 2156 2064 + 9 2116 2117 2158 2157 2065 + 9 2117 2118 2159 2158 2066 + 9 2118 2119 2160 2159 2067 + 9 2119 2120 2161 2160 2068 + 9 2120 2121 2162 2161 2069 + 9 2121 2122 2163 2162 2070 + 9 2122 2123 2164 2163 2071 + 9 2123 2124 2165 2164 2072 + 9 2124 2125 2166 2165 2073 + 9 2125 2126 2167 2166 2074 + 9 2126 2127 2168 2167 2075 + 9 2127 2128 2169 2168 2076 + 9 2128 2129 2170 2169 2077 + 9 2129 2130 2171 2170 2078 + 9 2130 2131 2172 2171 2079 + 9 2132 2133 2174 2173 2080 + 9 2133 2134 2175 2174 2081 + 9 2134 2135 2176 2175 2082 + 9 2135 2136 2177 2176 2083 + 9 2136 2137 2178 2177 2084 + 9 2137 2138 2179 2178 2085 + 9 2138 2139 2180 2179 2086 + 9 2139 2140 2181 2180 2087 + 9 2140 2141 2182 2181 2088 + 9 2141 2142 2183 2182 2089 + 9 2142 2143 2184 2183 2090 + 9 2143 2144 2185 2184 2091 + 9 2144 2145 2186 2185 2092 + 9 2145 2146 2187 2186 2093 + 9 2146 2147 2188 2187 2094 + 9 2147 2148 2189 2188 2095 + 9 2148 2149 2190 2189 2096 + 9 2149 2150 2191 2190 2097 + 9 2150 2151 2192 2191 2098 + 9 2151 2152 2193 2192 2099 + 9 2152 2153 2194 2193 2100 + 9 2153 2154 2195 2194 2101 + 9 2154 2155 2196 2195 2102 + 9 2155 2156 2197 2196 2103 + 9 2156 2157 2198 2197 2104 + 9 2157 2158 2199 2198 2105 + 9 2158 2159 2200 2199 2106 + 9 2159 2160 2201 2200 2107 + 9 2160 2161 2202 2201 2108 + 9 2161 2162 2203 2202 2109 + 9 2162 2163 2204 2203 2110 + 9 2163 2164 2205 2204 2111 + 9 2164 2165 2206 2205 2112 + 9 2165 2166 2207 2206 2113 + 9 2166 2167 2208 2207 2114 + 9 2167 2168 2209 2208 2115 + 9 2168 2169 2210 2209 2116 + 9 2169 2170 2211 2210 2117 + 9 2170 2171 2212 2211 2118 + 9 2171 2172 2213 2212 2119 + 9 2173 2174 2215 2214 2120 + 9 2174 2175 2216 2215 2121 + 9 2175 2176 2217 2216 2122 + 9 2176 2177 2218 2217 2123 + 9 2177 2178 2219 2218 2124 + 9 2178 2179 2220 2219 2125 + 9 2179 2180 2221 2220 2126 + 9 2180 2181 2222 2221 2127 + 9 2181 2182 2223 2222 2128 + 9 2182 2183 2224 2223 2129 + 9 2183 2184 2225 2224 2130 + 9 2184 2185 2226 2225 2131 + 9 2185 2186 2227 2226 2132 + 9 2186 2187 2228 2227 2133 + 9 2187 2188 2229 2228 2134 + 9 2188 2189 2230 2229 2135 + 9 2189 2190 2231 2230 2136 + 9 2190 2191 2232 2231 2137 + 9 2191 2192 2233 2232 2138 + 9 2192 2193 2234 2233 2139 + 9 2193 2194 2235 2234 2140 + 9 2194 2195 2236 2235 2141 + 9 2195 2196 2237 2236 2142 + 9 2196 2197 2238 2237 2143 + 9 2197 2198 2239 2238 2144 + 9 2198 2199 2240 2239 2145 + 9 2199 2200 2241 2240 2146 + 9 2200 2201 2242 2241 2147 + 9 2201 2202 2243 2242 2148 + 9 2202 2203 2244 2243 2149 + 9 2203 2204 2245 2244 2150 + 9 2204 2205 2246 2245 2151 + 9 2205 2206 2247 2246 2152 + 9 2206 2207 2248 2247 2153 + 9 2207 2208 2249 2248 2154 + 9 2208 2209 2250 2249 2155 + 9 2209 2210 2251 2250 2156 + 9 2210 2211 2252 2251 2157 + 9 2211 2212 2253 2252 2158 + 9 2212 2213 2254 2253 2159 + 9 2214 2215 2256 2255 2160 + 9 2215 2216 2257 2256 2161 + 9 2216 2217 2258 2257 2162 + 9 2217 2218 2259 2258 2163 + 9 2218 2219 2260 2259 2164 + 9 2219 2220 2261 2260 2165 + 9 2220 2221 2262 2261 2166 + 9 2221 2222 2263 2262 2167 + 9 2222 2223 2264 2263 2168 + 9 2223 2224 2265 2264 2169 + 9 2224 2225 2266 2265 2170 + 9 2225 2226 2267 2266 2171 + 9 2226 2227 2268 2267 2172 + 9 2227 2228 2269 2268 2173 + 9 2228 2229 2270 2269 2174 + 9 2229 2230 2271 2270 2175 + 9 2230 2231 2272 2271 2176 + 9 2231 2232 2273 2272 2177 + 9 2232 2233 2274 2273 2178 + 9 2233 2234 2275 2274 2179 + 9 2234 2235 2276 2275 2180 + 9 2235 2236 2277 2276 2181 + 9 2236 2237 2278 2277 2182 + 9 2237 2238 2279 2278 2183 + 9 2238 2239 2280 2279 2184 + 9 2239 2240 2281 2280 2185 + 9 2240 2241 2282 2281 2186 + 9 2241 2242 2283 2282 2187 + 9 2242 2243 2284 2283 2188 + 9 2243 2244 2285 2284 2189 + 9 2244 2245 2286 2285 2190 + 9 2245 2246 2287 2286 2191 + 9 2246 2247 2288 2287 2192 + 9 2247 2248 2289 2288 2193 + 9 2248 2249 2290 2289 2194 + 9 2249 2250 2291 2290 2195 + 9 2250 2251 2292 2291 2196 + 9 2251 2252 2293 2292 2197 + 9 2252 2253 2294 2293 2198 + 9 2253 2254 2295 2294 2199 + 9 2255 2256 2297 2296 2200 + 9 2256 2257 2298 2297 2201 + 9 2257 2258 2299 2298 2202 + 9 2258 2259 2300 2299 2203 + 9 2259 2260 2301 2300 2204 + 9 2260 2261 2302 2301 2205 + 9 2261 2262 2303 2302 2206 + 9 2262 2263 2304 2303 2207 + 9 2263 2264 2305 2304 2208 + 9 2264 2265 2306 2305 2209 + 9 2265 2266 2307 2306 2210 + 9 2266 2267 2308 2307 2211 + 9 2267 2268 2309 2308 2212 + 9 2268 2269 2310 2309 2213 + 9 2269 2270 2311 2310 2214 + 9 2270 2271 2312 2311 2215 + 9 2271 2272 2313 2312 2216 + 9 2272 2273 2314 2313 2217 + 9 2273 2274 2315 2314 2218 + 9 2274 2275 2316 2315 2219 + 9 2275 2276 2317 2316 2220 + 9 2276 2277 2318 2317 2221 + 9 2277 2278 2319 2318 2222 + 9 2278 2279 2320 2319 2223 + 9 2279 2280 2321 2320 2224 + 9 2280 2281 2322 2321 2225 + 9 2281 2282 2323 2322 2226 + 9 2282 2283 2324 2323 2227 + 9 2283 2284 2325 2324 2228 + 9 2284 2285 2326 2325 2229 + 9 2285 2286 2327 2326 2230 + 9 2286 2287 2328 2327 2231 + 9 2287 2288 2329 2328 2232 + 9 2288 2289 2330 2329 2233 + 9 2289 2290 2331 2330 2234 + 9 2290 2291 2332 2331 2235 + 9 2291 2292 2333 2332 2236 + 9 2292 2293 2334 2333 2237 + 9 2293 2294 2335 2334 2238 + 9 2294 2295 2336 2335 2239 + 9 2296 2297 2338 2337 2240 + 9 2297 2298 2339 2338 2241 + 9 2298 2299 2340 2339 2242 + 9 2299 2300 2341 2340 2243 + 9 2300 2301 2342 2341 2244 + 9 2301 2302 2343 2342 2245 + 9 2302 2303 2344 2343 2246 + 9 2303 2304 2345 2344 2247 + 9 2304 2305 2346 2345 2248 + 9 2305 2306 2347 2346 2249 + 9 2306 2307 2348 2347 2250 + 9 2307 2308 2349 2348 2251 + 9 2308 2309 2350 2349 2252 + 9 2309 2310 2351 2350 2253 + 9 2310 2311 2352 2351 2254 + 9 2311 2312 2353 2352 2255 + 9 2312 2313 2354 2353 2256 + 9 2313 2314 2355 2354 2257 + 9 2314 2315 2356 2355 2258 + 9 2315 2316 2357 2356 2259 + 9 2316 2317 2358 2357 2260 + 9 2317 2318 2359 2358 2261 + 9 2318 2319 2360 2359 2262 + 9 2319 2320 2361 2360 2263 + 9 2320 2321 2362 2361 2264 + 9 2321 2322 2363 2362 2265 + 9 2322 2323 2364 2363 2266 + 9 2323 2324 2365 2364 2267 + 9 2324 2325 2366 2365 2268 + 9 2325 2326 2367 2366 2269 + 9 2326 2327 2368 2367 2270 + 9 2327 2328 2369 2368 2271 + 9 2328 2329 2370 2369 2272 + 9 2329 2330 2371 2370 2273 + 9 2330 2331 2372 2371 2274 + 9 2331 2332 2373 2372 2275 + 9 2332 2333 2374 2373 2276 + 9 2333 2334 2375 2374 2277 + 9 2334 2335 2376 2375 2278 + 9 2335 2336 2377 2376 2279 + 9 2337 2338 2379 2378 2280 + 9 2338 2339 2380 2379 2281 + 9 2339 2340 2381 2380 2282 + 9 2340 2341 2382 2381 2283 + 9 2341 2342 2383 2382 2284 + 9 2342 2343 2384 2383 2285 + 9 2343 2344 2385 2384 2286 + 9 2344 2345 2386 2385 2287 + 9 2345 2346 2387 2386 2288 + 9 2346 2347 2388 2387 2289 + 9 2347 2348 2389 2388 2290 + 9 2348 2349 2390 2389 2291 + 9 2349 2350 2391 2390 2292 + 9 2350 2351 2392 2391 2293 + 9 2351 2352 2393 2392 2294 + 9 2352 2353 2394 2393 2295 + 9 2353 2354 2395 2394 2296 + 9 2354 2355 2396 2395 2297 + 9 2355 2356 2397 2396 2298 + 9 2356 2357 2398 2397 2299 + 9 2357 2358 2399 2398 2300 + 9 2358 2359 2400 2399 2301 + 9 2359 2360 2401 2400 2302 + 9 2360 2361 2402 2401 2303 + 9 2361 2362 2403 2402 2304 + 9 2362 2363 2404 2403 2305 + 9 2363 2364 2405 2404 2306 + 9 2364 2365 2406 2405 2307 + 9 2365 2366 2407 2406 2308 + 9 2366 2367 2408 2407 2309 + 9 2367 2368 2409 2408 2310 + 9 2368 2369 2410 2409 2311 + 9 2369 2370 2411 2410 2312 + 9 2370 2371 2412 2411 2313 + 9 2371 2372 2413 2412 2314 + 9 2372 2373 2414 2413 2315 + 9 2373 2374 2415 2414 2316 + 9 2374 2375 2416 2415 2317 + 9 2375 2376 2417 2416 2318 + 9 2376 2377 2418 2417 2319 + 9 2378 2379 2420 2419 2320 + 9 2379 2380 2421 2420 2321 + 9 2380 2381 2422 2421 2322 + 9 2381 2382 2423 2422 2323 + 9 2382 2383 2424 2423 2324 + 9 2383 2384 2425 2424 2325 + 9 2384 2385 2426 2425 2326 + 9 2385 2386 2427 2426 2327 + 9 2386 2387 2428 2427 2328 + 9 2387 2388 2429 2428 2329 + 9 2388 2389 2430 2429 2330 + 9 2389 2390 2431 2430 2331 + 9 2390 2391 2432 2431 2332 + 9 2391 2392 2433 2432 2333 + 9 2392 2393 2434 2433 2334 + 9 2393 2394 2435 2434 2335 + 9 2394 2395 2436 2435 2336 + 9 2395 2396 2437 2436 2337 + 9 2396 2397 2438 2437 2338 + 9 2397 2398 2439 2438 2339 + 9 2398 2399 2440 2439 2340 + 9 2399 2400 2441 2440 2341 + 9 2400 2401 2442 2441 2342 + 9 2401 2402 2443 2442 2343 + 9 2402 2403 2444 2443 2344 + 9 2403 2404 2445 2444 2345 + 9 2404 2405 2446 2445 2346 + 9 2405 2406 2447 2446 2347 + 9 2406 2407 2448 2447 2348 + 9 2407 2408 2449 2448 2349 + 9 2408 2409 2450 2449 2350 + 9 2409 2410 2451 2450 2351 + 9 2410 2411 2452 2451 2352 + 9 2411 2412 2453 2452 2353 + 9 2412 2413 2454 2453 2354 + 9 2413 2414 2455 2454 2355 + 9 2414 2415 2456 2455 2356 + 9 2415 2416 2457 2456 2357 + 9 2416 2417 2458 2457 2358 + 9 2417 2418 2459 2458 2359 + 9 2419 2420 2461 2460 2360 + 9 2420 2421 2462 2461 2361 + 9 2421 2422 2463 2462 2362 + 9 2422 2423 2464 2463 2363 + 9 2423 2424 2465 2464 2364 + 9 2424 2425 2466 2465 2365 + 9 2425 2426 2467 2466 2366 + 9 2426 2427 2468 2467 2367 + 9 2427 2428 2469 2468 2368 + 9 2428 2429 2470 2469 2369 + 9 2429 2430 2471 2470 2370 + 9 2430 2431 2472 2471 2371 + 9 2431 2432 2473 2472 2372 + 9 2432 2433 2474 2473 2373 + 9 2433 2434 2475 2474 2374 + 9 2434 2435 2476 2475 2375 + 9 2435 2436 2477 2476 2376 + 9 2436 2437 2478 2477 2377 + 9 2437 2438 2479 2478 2378 + 9 2438 2439 2480 2479 2379 + 9 2439 2440 2481 2480 2380 + 9 2440 2441 2482 2481 2381 + 9 2441 2442 2483 2482 2382 + 9 2442 2443 2484 2483 2383 + 9 2443 2444 2485 2484 2384 + 9 2444 2445 2486 2485 2385 + 9 2445 2446 2487 2486 2386 + 9 2446 2447 2488 2487 2387 + 9 2447 2448 2489 2488 2388 + 9 2448 2449 2490 2489 2389 + 9 2449 2450 2491 2490 2390 + 9 2450 2451 2492 2491 2391 + 9 2451 2452 2493 2492 2392 + 9 2452 2453 2494 2493 2393 + 9 2453 2454 2495 2494 2394 + 9 2454 2455 2496 2495 2395 + 9 2455 2456 2497 2496 2396 + 9 2456 2457 2498 2497 2397 + 9 2457 2458 2499 2498 2398 + 9 2458 2459 2500 2499 2399 + 9 2460 2461 2502 2501 2400 + 9 2461 2462 2503 2502 2401 + 9 2462 2463 2504 2503 2402 + 9 2463 2464 2505 2504 2403 + 9 2464 2465 2506 2505 2404 + 9 2465 2466 2507 2506 2405 + 9 2466 2467 2508 2507 2406 + 9 2467 2468 2509 2508 2407 + 9 2468 2469 2510 2509 2408 + 9 2469 2470 2511 2510 2409 + 9 2470 2471 2512 2511 2410 + 9 2471 2472 2513 2512 2411 + 9 2472 2473 2514 2513 2412 + 9 2473 2474 2515 2514 2413 + 9 2474 2475 2516 2515 2414 + 9 2475 2476 2517 2516 2415 + 9 2476 2477 2518 2517 2416 + 9 2477 2478 2519 2518 2417 + 9 2478 2479 2520 2519 2418 + 9 2479 2480 2521 2520 2419 + 9 2480 2481 2522 2521 2420 + 9 2481 2482 2523 2522 2421 + 9 2482 2483 2524 2523 2422 + 9 2483 2484 2525 2524 2423 + 9 2484 2485 2526 2525 2424 + 9 2485 2486 2527 2526 2425 + 9 2486 2487 2528 2527 2426 + 9 2487 2488 2529 2528 2427 + 9 2488 2489 2530 2529 2428 + 9 2489 2490 2531 2530 2429 + 9 2490 2491 2532 2531 2430 + 9 2491 2492 2533 2532 2431 + 9 2492 2493 2534 2533 2432 + 9 2493 2494 2535 2534 2433 + 9 2494 2495 2536 2535 2434 + 9 2495 2496 2537 2536 2435 + 9 2496 2497 2538 2537 2436 + 9 2497 2498 2539 2538 2437 + 9 2498 2499 2540 2539 2438 + 9 2499 2500 2541 2540 2439 + 9 2501 2502 2543 2542 2440 + 9 2502 2503 2544 2543 2441 + 9 2503 2504 2545 2544 2442 + 9 2504 2505 2546 2545 2443 + 9 2505 2506 2547 2546 2444 + 9 2506 2507 2548 2547 2445 + 9 2507 2508 2549 2548 2446 + 9 2508 2509 2550 2549 2447 + 9 2509 2510 2551 2550 2448 + 9 2510 2511 2552 2551 2449 + 9 2511 2512 2553 2552 2450 + 9 2512 2513 2554 2553 2451 + 9 2513 2514 2555 2554 2452 + 9 2514 2515 2556 2555 2453 + 9 2515 2516 2557 2556 2454 + 9 2516 2517 2558 2557 2455 + 9 2517 2518 2559 2558 2456 + 9 2518 2519 2560 2559 2457 + 9 2519 2520 2561 2560 2458 + 9 2520 2521 2562 2561 2459 + 9 2521 2522 2563 2562 2460 + 9 2522 2523 2564 2563 2461 + 9 2523 2524 2565 2564 2462 + 9 2524 2525 2566 2565 2463 + 9 2525 2526 2567 2566 2464 + 9 2526 2527 2568 2567 2465 + 9 2527 2528 2569 2568 2466 + 9 2528 2529 2570 2569 2467 + 9 2529 2530 2571 2570 2468 + 9 2530 2531 2572 2571 2469 + 9 2531 2532 2573 2572 2470 + 9 2532 2533 2574 2573 2471 + 9 2533 2534 2575 2574 2472 + 9 2534 2535 2576 2575 2473 + 9 2535 2536 2577 2576 2474 + 9 2536 2537 2578 2577 2475 + 9 2537 2538 2579 2578 2476 + 9 2538 2539 2580 2579 2477 + 9 2539 2540 2581 2580 2478 + 9 2540 2541 2582 2581 2479 + 9 2542 2543 2584 2583 2480 + 9 2543 2544 2585 2584 2481 + 9 2544 2545 2586 2585 2482 + 9 2545 2546 2587 2586 2483 + 9 2546 2547 2588 2587 2484 + 9 2547 2548 2589 2588 2485 + 9 2548 2549 2590 2589 2486 + 9 2549 2550 2591 2590 2487 + 9 2550 2551 2592 2591 2488 + 9 2551 2552 2593 2592 2489 + 9 2552 2553 2594 2593 2490 + 9 2553 2554 2595 2594 2491 + 9 2554 2555 2596 2595 2492 + 9 2555 2556 2597 2596 2493 + 9 2556 2557 2598 2597 2494 + 9 2557 2558 2599 2598 2495 + 9 2558 2559 2600 2599 2496 + 9 2559 2560 2601 2600 2497 + 9 2560 2561 2602 2601 2498 + 9 2561 2562 2603 2602 2499 + 9 2562 2563 2604 2603 2500 + 9 2563 2564 2605 2604 2501 + 9 2564 2565 2606 2605 2502 + 9 2565 2566 2607 2606 2503 + 9 2566 2567 2608 2607 2504 + 9 2567 2568 2609 2608 2505 + 9 2568 2569 2610 2609 2506 + 9 2569 2570 2611 2610 2507 + 9 2570 2571 2612 2611 2508 + 9 2571 2572 2613 2612 2509 + 9 2572 2573 2614 2613 2510 + 9 2573 2574 2615 2614 2511 + 9 2574 2575 2616 2615 2512 + 9 2575 2576 2617 2616 2513 + 9 2576 2577 2618 2617 2514 + 9 2577 2578 2619 2618 2515 + 9 2578 2579 2620 2619 2516 + 9 2579 2580 2621 2620 2517 + 9 2580 2581 2622 2621 2518 + 9 2581 2582 2623 2622 2519 + 9 2583 2584 2625 2624 2520 + 9 2584 2585 2626 2625 2521 + 9 2585 2586 2627 2626 2522 + 9 2586 2587 2628 2627 2523 + 9 2587 2588 2629 2628 2524 + 9 2588 2589 2630 2629 2525 + 9 2589 2590 2631 2630 2526 + 9 2590 2591 2632 2631 2527 + 9 2591 2592 2633 2632 2528 + 9 2592 2593 2634 2633 2529 + 9 2593 2594 2635 2634 2530 + 9 2594 2595 2636 2635 2531 + 9 2595 2596 2637 2636 2532 + 9 2596 2597 2638 2637 2533 + 9 2597 2598 2639 2638 2534 + 9 2598 2599 2640 2639 2535 + 9 2599 2600 2641 2640 2536 + 9 2600 2601 2642 2641 2537 + 9 2601 2602 2643 2642 2538 + 9 2602 2603 2644 2643 2539 + 9 2603 2604 2645 2644 2540 + 9 2604 2605 2646 2645 2541 + 9 2605 2606 2647 2646 2542 + 9 2606 2607 2648 2647 2543 + 9 2607 2608 2649 2648 2544 + 9 2608 2609 2650 2649 2545 + 9 2609 2610 2651 2650 2546 + 9 2610 2611 2652 2651 2547 + 9 2611 2612 2653 2652 2548 + 9 2612 2613 2654 2653 2549 + 9 2613 2614 2655 2654 2550 + 9 2614 2615 2656 2655 2551 + 9 2615 2616 2657 2656 2552 + 9 2616 2617 2658 2657 2553 + 9 2617 2618 2659 2658 2554 + 9 2618 2619 2660 2659 2555 + 9 2619 2620 2661 2660 2556 + 9 2620 2621 2662 2661 2557 + 9 2621 2622 2663 2662 2558 + 9 2622 2623 2664 2663 2559 + 9 2624 2625 2666 2665 2560 + 9 2625 2626 2667 2666 2561 + 9 2626 2627 2668 2667 2562 + 9 2627 2628 2669 2668 2563 + 9 2628 2629 2670 2669 2564 + 9 2629 2630 2671 2670 2565 + 9 2630 2631 2672 2671 2566 + 9 2631 2632 2673 2672 2567 + 9 2632 2633 2674 2673 2568 + 9 2633 2634 2675 2674 2569 + 9 2634 2635 2676 2675 2570 + 9 2635 2636 2677 2676 2571 + 9 2636 2637 2678 2677 2572 + 9 2637 2638 2679 2678 2573 + 9 2638 2639 2680 2679 2574 + 9 2639 2640 2681 2680 2575 + 9 2640 2641 2682 2681 2576 + 9 2641 2642 2683 2682 2577 + 9 2642 2643 2684 2683 2578 + 9 2643 2644 2685 2684 2579 + 9 2644 2645 2686 2685 2580 + 9 2645 2646 2687 2686 2581 + 9 2646 2647 2688 2687 2582 + 9 2647 2648 2689 2688 2583 + 9 2648 2649 2690 2689 2584 + 9 2649 2650 2691 2690 2585 + 9 2650 2651 2692 2691 2586 + 9 2651 2652 2693 2692 2587 + 9 2652 2653 2694 2693 2588 + 9 2653 2654 2695 2694 2589 + 9 2654 2655 2696 2695 2590 + 9 2655 2656 2697 2696 2591 + 9 2656 2657 2698 2697 2592 + 9 2657 2658 2699 2698 2593 + 9 2658 2659 2700 2699 2594 + 9 2659 2660 2701 2700 2595 + 9 2660 2661 2702 2701 2596 + 9 2661 2662 2703 2702 2597 + 9 2662 2663 2704 2703 2598 + 9 2663 2664 2705 2704 2599 + 9 2665 2666 2707 2706 2600 + 9 2666 2667 2708 2707 2601 + 9 2667 2668 2709 2708 2602 + 9 2668 2669 2710 2709 2603 + 9 2669 2670 2711 2710 2604 + 9 2670 2671 2712 2711 2605 + 9 2671 2672 2713 2712 2606 + 9 2672 2673 2714 2713 2607 + 9 2673 2674 2715 2714 2608 + 9 2674 2675 2716 2715 2609 + 9 2675 2676 2717 2716 2610 + 9 2676 2677 2718 2717 2611 + 9 2677 2678 2719 2718 2612 + 9 2678 2679 2720 2719 2613 + 9 2679 2680 2721 2720 2614 + 9 2680 2681 2722 2721 2615 + 9 2681 2682 2723 2722 2616 + 9 2682 2683 2724 2723 2617 + 9 2683 2684 2725 2724 2618 + 9 2684 2685 2726 2725 2619 + 9 2685 2686 2727 2726 2620 + 9 2686 2687 2728 2727 2621 + 9 2687 2688 2729 2728 2622 + 9 2688 2689 2730 2729 2623 + 9 2689 2690 2731 2730 2624 + 9 2690 2691 2732 2731 2625 + 9 2691 2692 2733 2732 2626 + 9 2692 2693 2734 2733 2627 + 9 2693 2694 2735 2734 2628 + 9 2694 2695 2736 2735 2629 + 9 2695 2696 2737 2736 2630 + 9 2696 2697 2738 2737 2631 + 9 2697 2698 2739 2738 2632 + 9 2698 2699 2740 2739 2633 + 9 2699 2700 2741 2740 2634 + 9 2700 2701 2742 2741 2635 + 9 2701 2702 2743 2742 2636 + 9 2702 2703 2744 2743 2637 + 9 2703 2704 2745 2744 2638 + 9 2704 2705 2746 2745 2639 + 9 2706 2707 2748 2747 2640 + 9 2707 2708 2749 2748 2641 + 9 2708 2709 2750 2749 2642 + 9 2709 2710 2751 2750 2643 + 9 2710 2711 2752 2751 2644 + 9 2711 2712 2753 2752 2645 + 9 2712 2713 2754 2753 2646 + 9 2713 2714 2755 2754 2647 + 9 2714 2715 2756 2755 2648 + 9 2715 2716 2757 2756 2649 + 9 2716 2717 2758 2757 2650 + 9 2717 2718 2759 2758 2651 + 9 2718 2719 2760 2759 2652 + 9 2719 2720 2761 2760 2653 + 9 2720 2721 2762 2761 2654 + 9 2721 2722 2763 2762 2655 + 9 2722 2723 2764 2763 2656 + 9 2723 2724 2765 2764 2657 + 9 2724 2725 2766 2765 2658 + 9 2725 2726 2767 2766 2659 + 9 2726 2727 2768 2767 2660 + 9 2727 2728 2769 2768 2661 + 9 2728 2729 2770 2769 2662 + 9 2729 2730 2771 2770 2663 + 9 2730 2731 2772 2771 2664 + 9 2731 2732 2773 2772 2665 + 9 2732 2733 2774 2773 2666 + 9 2733 2734 2775 2774 2667 + 9 2734 2735 2776 2775 2668 + 9 2735 2736 2777 2776 2669 + 9 2736 2737 2778 2777 2670 + 9 2737 2738 2779 2778 2671 + 9 2738 2739 2780 2779 2672 + 9 2739 2740 2781 2780 2673 + 9 2740 2741 2782 2781 2674 + 9 2741 2742 2783 2782 2675 + 9 2742 2743 2784 2783 2676 + 9 2743 2744 2785 2784 2677 + 9 2744 2745 2786 2785 2678 + 9 2745 2746 2787 2786 2679 + 9 2747 2748 2789 2788 2680 + 9 2748 2749 2790 2789 2681 + 9 2749 2750 2791 2790 2682 + 9 2750 2751 2792 2791 2683 + 9 2751 2752 2793 2792 2684 + 9 2752 2753 2794 2793 2685 + 9 2753 2754 2795 2794 2686 + 9 2754 2755 2796 2795 2687 + 9 2755 2756 2797 2796 2688 + 9 2756 2757 2798 2797 2689 + 9 2757 2758 2799 2798 2690 + 9 2758 2759 2800 2799 2691 + 9 2759 2760 2801 2800 2692 + 9 2760 2761 2802 2801 2693 + 9 2761 2762 2803 2802 2694 + 9 2762 2763 2804 2803 2695 + 9 2763 2764 2805 2804 2696 + 9 2764 2765 2806 2805 2697 + 9 2765 2766 2807 2806 2698 + 9 2766 2767 2808 2807 2699 + 9 2767 2768 2809 2808 2700 + 9 2768 2769 2810 2809 2701 + 9 2769 2770 2811 2810 2702 + 9 2770 2771 2812 2811 2703 + 9 2771 2772 2813 2812 2704 + 9 2772 2773 2814 2813 2705 + 9 2773 2774 2815 2814 2706 + 9 2774 2775 2816 2815 2707 + 9 2775 2776 2817 2816 2708 + 9 2776 2777 2818 2817 2709 + 9 2777 2778 2819 2818 2710 + 9 2778 2779 2820 2819 2711 + 9 2779 2780 2821 2820 2712 + 9 2780 2781 2822 2821 2713 + 9 2781 2782 2823 2822 2714 + 9 2782 2783 2824 2823 2715 + 9 2783 2784 2825 2824 2716 + 9 2784 2785 2826 2825 2717 + 9 2785 2786 2827 2826 2718 + 9 2786 2787 2828 2827 2719 + 9 2788 2789 2830 2829 2720 + 9 2789 2790 2831 2830 2721 + 9 2790 2791 2832 2831 2722 + 9 2791 2792 2833 2832 2723 + 9 2792 2793 2834 2833 2724 + 9 2793 2794 2835 2834 2725 + 9 2794 2795 2836 2835 2726 + 9 2795 2796 2837 2836 2727 + 9 2796 2797 2838 2837 2728 + 9 2797 2798 2839 2838 2729 + 9 2798 2799 2840 2839 2730 + 9 2799 2800 2841 2840 2731 + 9 2800 2801 2842 2841 2732 + 9 2801 2802 2843 2842 2733 + 9 2802 2803 2844 2843 2734 + 9 2803 2804 2845 2844 2735 + 9 2804 2805 2846 2845 2736 + 9 2805 2806 2847 2846 2737 + 9 2806 2807 2848 2847 2738 + 9 2807 2808 2849 2848 2739 + 9 2808 2809 2850 2849 2740 + 9 2809 2810 2851 2850 2741 + 9 2810 2811 2852 2851 2742 + 9 2811 2812 2853 2852 2743 + 9 2812 2813 2854 2853 2744 + 9 2813 2814 2855 2854 2745 + 9 2814 2815 2856 2855 2746 + 9 2815 2816 2857 2856 2747 + 9 2816 2817 2858 2857 2748 + 9 2817 2818 2859 2858 2749 + 9 2818 2819 2860 2859 2750 + 9 2819 2820 2861 2860 2751 + 9 2820 2821 2862 2861 2752 + 9 2821 2822 2863 2862 2753 + 9 2822 2823 2864 2863 2754 + 9 2823 2824 2865 2864 2755 + 9 2824 2825 2866 2865 2756 + 9 2825 2826 2867 2866 2757 + 9 2826 2827 2868 2867 2758 + 9 2827 2828 2869 2868 2759 + 9 2829 2830 2871 2870 2760 + 9 2830 2831 2872 2871 2761 + 9 2831 2832 2873 2872 2762 + 9 2832 2833 2874 2873 2763 + 9 2833 2834 2875 2874 2764 + 9 2834 2835 2876 2875 2765 + 9 2835 2836 2877 2876 2766 + 9 2836 2837 2878 2877 2767 + 9 2837 2838 2879 2878 2768 + 9 2838 2839 2880 2879 2769 + 9 2839 2840 2881 2880 2770 + 9 2840 2841 2882 2881 2771 + 9 2841 2842 2883 2882 2772 + 9 2842 2843 2884 2883 2773 + 9 2843 2844 2885 2884 2774 + 9 2844 2845 2886 2885 2775 + 9 2845 2846 2887 2886 2776 + 9 2846 2847 2888 2887 2777 + 9 2847 2848 2889 2888 2778 + 9 2848 2849 2890 2889 2779 + 9 2849 2850 2891 2890 2780 + 9 2850 2851 2892 2891 2781 + 9 2851 2852 2893 2892 2782 + 9 2852 2853 2894 2893 2783 + 9 2853 2854 2895 2894 2784 + 9 2854 2855 2896 2895 2785 + 9 2855 2856 2897 2896 2786 + 9 2856 2857 2898 2897 2787 + 9 2857 2858 2899 2898 2788 + 9 2858 2859 2900 2899 2789 + 9 2859 2860 2901 2900 2790 + 9 2860 2861 2902 2901 2791 + 9 2861 2862 2903 2902 2792 + 9 2862 2863 2904 2903 2793 + 9 2863 2864 2905 2904 2794 + 9 2864 2865 2906 2905 2795 + 9 2865 2866 2907 2906 2796 + 9 2866 2867 2908 2907 2797 + 9 2867 2868 2909 2908 2798 + 9 2868 2869 2910 2909 2799 + 9 2870 2871 2912 2911 2800 + 9 2871 2872 2913 2912 2801 + 9 2872 2873 2914 2913 2802 + 9 2873 2874 2915 2914 2803 + 9 2874 2875 2916 2915 2804 + 9 2875 2876 2917 2916 2805 + 9 2876 2877 2918 2917 2806 + 9 2877 2878 2919 2918 2807 + 9 2878 2879 2920 2919 2808 + 9 2879 2880 2921 2920 2809 + 9 2880 2881 2922 2921 2810 + 9 2881 2882 2923 2922 2811 + 9 2882 2883 2924 2923 2812 + 9 2883 2884 2925 2924 2813 + 9 2884 2885 2926 2925 2814 + 9 2885 2886 2927 2926 2815 + 9 2886 2887 2928 2927 2816 + 9 2887 2888 2929 2928 2817 + 9 2888 2889 2930 2929 2818 + 9 2889 2890 2931 2930 2819 + 9 2890 2891 2932 2931 2820 + 9 2891 2892 2933 2932 2821 + 9 2892 2893 2934 2933 2822 + 9 2893 2894 2935 2934 2823 + 9 2894 2895 2936 2935 2824 + 9 2895 2896 2937 2936 2825 + 9 2896 2897 2938 2937 2826 + 9 2897 2898 2939 2938 2827 + 9 2898 2899 2940 2939 2828 + 9 2899 2900 2941 2940 2829 + 9 2900 2901 2942 2941 2830 + 9 2901 2902 2943 2942 2831 + 9 2902 2903 2944 2943 2832 + 9 2903 2904 2945 2944 2833 + 9 2904 2905 2946 2945 2834 + 9 2905 2906 2947 2946 2835 + 9 2906 2907 2948 2947 2836 + 9 2907 2908 2949 2948 2837 + 9 2908 2909 2950 2949 2838 + 9 2909 2910 2951 2950 2839 + 9 2911 2912 2953 2952 2840 + 9 2912 2913 2954 2953 2841 + 9 2913 2914 2955 2954 2842 + 9 2914 2915 2956 2955 2843 + 9 2915 2916 2957 2956 2844 + 9 2916 2917 2958 2957 2845 + 9 2917 2918 2959 2958 2846 + 9 2918 2919 2960 2959 2847 + 9 2919 2920 2961 2960 2848 + 9 2920 2921 2962 2961 2849 + 9 2921 2922 2963 2962 2850 + 9 2922 2923 2964 2963 2851 + 9 2923 2924 2965 2964 2852 + 9 2924 2925 2966 2965 2853 + 9 2925 2926 2967 2966 2854 + 9 2926 2927 2968 2967 2855 + 9 2927 2928 2969 2968 2856 + 9 2928 2929 2970 2969 2857 + 9 2929 2930 2971 2970 2858 + 9 2930 2931 2972 2971 2859 + 9 2931 2932 2973 2972 2860 + 9 2932 2933 2974 2973 2861 + 9 2933 2934 2975 2974 2862 + 9 2934 2935 2976 2975 2863 + 9 2935 2936 2977 2976 2864 + 9 2936 2937 2978 2977 2865 + 9 2937 2938 2979 2978 2866 + 9 2938 2939 2980 2979 2867 + 9 2939 2940 2981 2980 2868 + 9 2940 2941 2982 2981 2869 + 9 2941 2942 2983 2982 2870 + 9 2942 2943 2984 2983 2871 + 9 2943 2944 2985 2984 2872 + 9 2944 2945 2986 2985 2873 + 9 2945 2946 2987 2986 2874 + 9 2946 2947 2988 2987 2875 + 9 2947 2948 2989 2988 2876 + 9 2948 2949 2990 2989 2877 + 9 2949 2950 2991 2990 2878 + 9 2950 2951 2992 2991 2879 + 9 2952 2953 2994 2993 2880 + 9 2953 2954 2995 2994 2881 + 9 2954 2955 2996 2995 2882 + 9 2955 2956 2997 2996 2883 + 9 2956 2957 2998 2997 2884 + 9 2957 2958 2999 2998 2885 + 9 2958 2959 3000 2999 2886 + 9 2959 2960 3001 3000 2887 + 9 2960 2961 3002 3001 2888 + 9 2961 2962 3003 3002 2889 + 9 2962 2963 3004 3003 2890 + 9 2963 2964 3005 3004 2891 + 9 2964 2965 3006 3005 2892 + 9 2965 2966 3007 3006 2893 + 9 2966 2967 3008 3007 2894 + 9 2967 2968 3009 3008 2895 + 9 2968 2969 3010 3009 2896 + 9 2969 2970 3011 3010 2897 + 9 2970 2971 3012 3011 2898 + 9 2971 2972 3013 3012 2899 + 9 2972 2973 3014 3013 2900 + 9 2973 2974 3015 3014 2901 + 9 2974 2975 3016 3015 2902 + 9 2975 2976 3017 3016 2903 + 9 2976 2977 3018 3017 2904 + 9 2977 2978 3019 3018 2905 + 9 2978 2979 3020 3019 2906 + 9 2979 2980 3021 3020 2907 + 9 2980 2981 3022 3021 2908 + 9 2981 2982 3023 3022 2909 + 9 2982 2983 3024 3023 2910 + 9 2983 2984 3025 3024 2911 + 9 2984 2985 3026 3025 2912 + 9 2985 2986 3027 3026 2913 + 9 2986 2987 3028 3027 2914 + 9 2987 2988 3029 3028 2915 + 9 2988 2989 3030 3029 2916 + 9 2989 2990 3031 3030 2917 + 9 2990 2991 3032 3031 2918 + 9 2991 2992 3033 3032 2919 + 9 2993 2994 3035 3034 2920 + 9 2994 2995 3036 3035 2921 + 9 2995 2996 3037 3036 2922 + 9 2996 2997 3038 3037 2923 + 9 2997 2998 3039 3038 2924 + 9 2998 2999 3040 3039 2925 + 9 2999 3000 3041 3040 2926 + 9 3000 3001 3042 3041 2927 + 9 3001 3002 3043 3042 2928 + 9 3002 3003 3044 3043 2929 + 9 3003 3004 3045 3044 2930 + 9 3004 3005 3046 3045 2931 + 9 3005 3006 3047 3046 2932 + 9 3006 3007 3048 3047 2933 + 9 3007 3008 3049 3048 2934 + 9 3008 3009 3050 3049 2935 + 9 3009 3010 3051 3050 2936 + 9 3010 3011 3052 3051 2937 + 9 3011 3012 3053 3052 2938 + 9 3012 3013 3054 3053 2939 + 9 3013 3014 3055 3054 2940 + 9 3014 3015 3056 3055 2941 + 9 3015 3016 3057 3056 2942 + 9 3016 3017 3058 3057 2943 + 9 3017 3018 3059 3058 2944 + 9 3018 3019 3060 3059 2945 + 9 3019 3020 3061 3060 2946 + 9 3020 3021 3062 3061 2947 + 9 3021 3022 3063 3062 2948 + 9 3022 3023 3064 3063 2949 + 9 3023 3024 3065 3064 2950 + 9 3024 3025 3066 3065 2951 + 9 3025 3026 3067 3066 2952 + 9 3026 3027 3068 3067 2953 + 9 3027 3028 3069 3068 2954 + 9 3028 3029 3070 3069 2955 + 9 3029 3030 3071 3070 2956 + 9 3030 3031 3072 3071 2957 + 9 3031 3032 3073 3072 2958 + 9 3032 3033 3074 3073 2959 + 9 3034 3035 3076 3075 2960 + 9 3035 3036 3077 3076 2961 + 9 3036 3037 3078 3077 2962 + 9 3037 3038 3079 3078 2963 + 9 3038 3039 3080 3079 2964 + 9 3039 3040 3081 3080 2965 + 9 3040 3041 3082 3081 2966 + 9 3041 3042 3083 3082 2967 + 9 3042 3043 3084 3083 2968 + 9 3043 3044 3085 3084 2969 + 9 3044 3045 3086 3085 2970 + 9 3045 3046 3087 3086 2971 + 9 3046 3047 3088 3087 2972 + 9 3047 3048 3089 3088 2973 + 9 3048 3049 3090 3089 2974 + 9 3049 3050 3091 3090 2975 + 9 3050 3051 3092 3091 2976 + 9 3051 3052 3093 3092 2977 + 9 3052 3053 3094 3093 2978 + 9 3053 3054 3095 3094 2979 + 9 3054 3055 3096 3095 2980 + 9 3055 3056 3097 3096 2981 + 9 3056 3057 3098 3097 2982 + 9 3057 3058 3099 3098 2983 + 9 3058 3059 3100 3099 2984 + 9 3059 3060 3101 3100 2985 + 9 3060 3061 3102 3101 2986 + 9 3061 3062 3103 3102 2987 + 9 3062 3063 3104 3103 2988 + 9 3063 3064 3105 3104 2989 + 9 3064 3065 3106 3105 2990 + 9 3065 3066 3107 3106 2991 + 9 3066 3067 3108 3107 2992 + 9 3067 3068 3109 3108 2993 + 9 3068 3069 3110 3109 2994 + 9 3069 3070 3111 3110 2995 + 9 3070 3071 3112 3111 2996 + 9 3071 3072 3113 3112 2997 + 9 3072 3073 3114 3113 2998 + 9 3073 3074 3115 3114 2999 + 9 3075 3076 3117 3116 3000 + 9 3076 3077 3118 3117 3001 + 9 3077 3078 3119 3118 3002 + 9 3078 3079 3120 3119 3003 + 9 3079 3080 3121 3120 3004 + 9 3080 3081 3122 3121 3005 + 9 3081 3082 3123 3122 3006 + 9 3082 3083 3124 3123 3007 + 9 3083 3084 3125 3124 3008 + 9 3084 3085 3126 3125 3009 + 9 3085 3086 3127 3126 3010 + 9 3086 3087 3128 3127 3011 + 9 3087 3088 3129 3128 3012 + 9 3088 3089 3130 3129 3013 + 9 3089 3090 3131 3130 3014 + 9 3090 3091 3132 3131 3015 + 9 3091 3092 3133 3132 3016 + 9 3092 3093 3134 3133 3017 + 9 3093 3094 3135 3134 3018 + 9 3094 3095 3136 3135 3019 + 9 3095 3096 3137 3136 3020 + 9 3096 3097 3138 3137 3021 + 9 3097 3098 3139 3138 3022 + 9 3098 3099 3140 3139 3023 + 9 3099 3100 3141 3140 3024 + 9 3100 3101 3142 3141 3025 + 9 3101 3102 3143 3142 3026 + 9 3102 3103 3144 3143 3027 + 9 3103 3104 3145 3144 3028 + 9 3104 3105 3146 3145 3029 + 9 3105 3106 3147 3146 3030 + 9 3106 3107 3148 3147 3031 + 9 3107 3108 3149 3148 3032 + 9 3108 3109 3150 3149 3033 + 9 3109 3110 3151 3150 3034 + 9 3110 3111 3152 3151 3035 + 9 3111 3112 3153 3152 3036 + 9 3112 3113 3154 3153 3037 + 9 3113 3114 3155 3154 3038 + 9 3114 3115 3156 3155 3039 + 9 3116 3117 3158 3157 3040 + 9 3117 3118 3159 3158 3041 + 9 3118 3119 3160 3159 3042 + 9 3119 3120 3161 3160 3043 + 9 3120 3121 3162 3161 3044 + 9 3121 3122 3163 3162 3045 + 9 3122 3123 3164 3163 3046 + 9 3123 3124 3165 3164 3047 + 9 3124 3125 3166 3165 3048 + 9 3125 3126 3167 3166 3049 + 9 3126 3127 3168 3167 3050 + 9 3127 3128 3169 3168 3051 + 9 3128 3129 3170 3169 3052 + 9 3129 3130 3171 3170 3053 + 9 3130 3131 3172 3171 3054 + 9 3131 3132 3173 3172 3055 + 9 3132 3133 3174 3173 3056 + 9 3133 3134 3175 3174 3057 + 9 3134 3135 3176 3175 3058 + 9 3135 3136 3177 3176 3059 + 9 3136 3137 3178 3177 3060 + 9 3137 3138 3179 3178 3061 + 9 3138 3139 3180 3179 3062 + 9 3139 3140 3181 3180 3063 + 9 3140 3141 3182 3181 3064 + 9 3141 3142 3183 3182 3065 + 9 3142 3143 3184 3183 3066 + 9 3143 3144 3185 3184 3067 + 9 3144 3145 3186 3185 3068 + 9 3145 3146 3187 3186 3069 + 9 3146 3147 3188 3187 3070 + 9 3147 3148 3189 3188 3071 + 9 3148 3149 3190 3189 3072 + 9 3149 3150 3191 3190 3073 + 9 3150 3151 3192 3191 3074 + 9 3151 3152 3193 3192 3075 + 9 3152 3153 3194 3193 3076 + 9 3153 3154 3195 3194 3077 + 9 3154 3155 3196 3195 3078 + 9 3155 3156 3197 3196 3079 + 9 3157 3158 3199 3198 3080 + 9 3158 3159 3200 3199 3081 + 9 3159 3160 3201 3200 3082 + 9 3160 3161 3202 3201 3083 + 9 3161 3162 3203 3202 3084 + 9 3162 3163 3204 3203 3085 + 9 3163 3164 3205 3204 3086 + 9 3164 3165 3206 3205 3087 + 9 3165 3166 3207 3206 3088 + 9 3166 3167 3208 3207 3089 + 9 3167 3168 3209 3208 3090 + 9 3168 3169 3210 3209 3091 + 9 3169 3170 3211 3210 3092 + 9 3170 3171 3212 3211 3093 + 9 3171 3172 3213 3212 3094 + 9 3172 3173 3214 3213 3095 + 9 3173 3174 3215 3214 3096 + 9 3174 3175 3216 3215 3097 + 9 3175 3176 3217 3216 3098 + 9 3176 3177 3218 3217 3099 + 9 3177 3178 3219 3218 3100 + 9 3178 3179 3220 3219 3101 + 9 3179 3180 3221 3220 3102 + 9 3180 3181 3222 3221 3103 + 9 3181 3182 3223 3222 3104 + 9 3182 3183 3224 3223 3105 + 9 3183 3184 3225 3224 3106 + 9 3184 3185 3226 3225 3107 + 9 3185 3186 3227 3226 3108 + 9 3186 3187 3228 3227 3109 + 9 3187 3188 3229 3228 3110 + 9 3188 3189 3230 3229 3111 + 9 3189 3190 3231 3230 3112 + 9 3190 3191 3232 3231 3113 + 9 3191 3192 3233 3232 3114 + 9 3192 3193 3234 3233 3115 + 9 3193 3194 3235 3234 3116 + 9 3194 3195 3236 3235 3117 + 9 3195 3196 3237 3236 3118 + 9 3196 3197 3238 3237 3119 + 9 3198 3199 3240 3239 3120 + 9 3199 3200 3241 3240 3121 + 9 3200 3201 3242 3241 3122 + 9 3201 3202 3243 3242 3123 + 9 3202 3203 3244 3243 3124 + 9 3203 3204 3245 3244 3125 + 9 3204 3205 3246 3245 3126 + 9 3205 3206 3247 3246 3127 + 9 3206 3207 3248 3247 3128 + 9 3207 3208 3249 3248 3129 + 9 3208 3209 3250 3249 3130 + 9 3209 3210 3251 3250 3131 + 9 3210 3211 3252 3251 3132 + 9 3211 3212 3253 3252 3133 + 9 3212 3213 3254 3253 3134 + 9 3213 3214 3255 3254 3135 + 9 3214 3215 3256 3255 3136 + 9 3215 3216 3257 3256 3137 + 9 3216 3217 3258 3257 3138 + 9 3217 3218 3259 3258 3139 + 9 3218 3219 3260 3259 3140 + 9 3219 3220 3261 3260 3141 + 9 3220 3221 3262 3261 3142 + 9 3221 3222 3263 3262 3143 + 9 3222 3223 3264 3263 3144 + 9 3223 3224 3265 3264 3145 + 9 3224 3225 3266 3265 3146 + 9 3225 3226 3267 3266 3147 + 9 3226 3227 3268 3267 3148 + 9 3227 3228 3269 3268 3149 + 9 3228 3229 3270 3269 3150 + 9 3229 3230 3271 3270 3151 + 9 3230 3231 3272 3271 3152 + 9 3231 3232 3273 3272 3153 + 9 3232 3233 3274 3273 3154 + 9 3233 3234 3275 3274 3155 + 9 3234 3235 3276 3275 3156 + 9 3235 3236 3277 3276 3157 + 9 3236 3237 3278 3277 3158 + 9 3237 3238 3279 3278 3159 + 9 3239 3240 3281 3280 3160 + 9 3240 3241 3282 3281 3161 + 9 3241 3242 3283 3282 3162 + 9 3242 3243 3284 3283 3163 + 9 3243 3244 3285 3284 3164 + 9 3244 3245 3286 3285 3165 + 9 3245 3246 3287 3286 3166 + 9 3246 3247 3288 3287 3167 + 9 3247 3248 3289 3288 3168 + 9 3248 3249 3290 3289 3169 + 9 3249 3250 3291 3290 3170 + 9 3250 3251 3292 3291 3171 + 9 3251 3252 3293 3292 3172 + 9 3252 3253 3294 3293 3173 + 9 3253 3254 3295 3294 3174 + 9 3254 3255 3296 3295 3175 + 9 3255 3256 3297 3296 3176 + 9 3256 3257 3298 3297 3177 + 9 3257 3258 3299 3298 3178 + 9 3258 3259 3300 3299 3179 + 9 3259 3260 3301 3300 3180 + 9 3260 3261 3302 3301 3181 + 9 3261 3262 3303 3302 3182 + 9 3262 3263 3304 3303 3183 + 9 3263 3264 3305 3304 3184 + 9 3264 3265 3306 3305 3185 + 9 3265 3266 3307 3306 3186 + 9 3266 3267 3308 3307 3187 + 9 3267 3268 3309 3308 3188 + 9 3268 3269 3310 3309 3189 + 9 3269 3270 3311 3310 3190 + 9 3270 3271 3312 3311 3191 + 9 3271 3272 3313 3312 3192 + 9 3272 3273 3314 3313 3193 + 9 3273 3274 3315 3314 3194 + 9 3274 3275 3316 3315 3195 + 9 3275 3276 3317 3316 3196 + 9 3276 3277 3318 3317 3197 + 9 3277 3278 3319 3318 3198 + 9 3278 3279 3320 3319 3199 + 9 3280 3281 3322 3321 3200 + 9 3281 3282 3323 3322 3201 + 9 3282 3283 3324 3323 3202 + 9 3283 3284 3325 3324 3203 + 9 3284 3285 3326 3325 3204 + 9 3285 3286 3327 3326 3205 + 9 3286 3287 3328 3327 3206 + 9 3287 3288 3329 3328 3207 + 9 3288 3289 3330 3329 3208 + 9 3289 3290 3331 3330 3209 + 9 3290 3291 3332 3331 3210 + 9 3291 3292 3333 3332 3211 + 9 3292 3293 3334 3333 3212 + 9 3293 3294 3335 3334 3213 + 9 3294 3295 3336 3335 3214 + 9 3295 3296 3337 3336 3215 + 9 3296 3297 3338 3337 3216 + 9 3297 3298 3339 3338 3217 + 9 3298 3299 3340 3339 3218 + 9 3299 3300 3341 3340 3219 + 9 3300 3301 3342 3341 3220 + 9 3301 3302 3343 3342 3221 + 9 3302 3303 3344 3343 3222 + 9 3303 3304 3345 3344 3223 + 9 3304 3305 3346 3345 3224 + 9 3305 3306 3347 3346 3225 + 9 3306 3307 3348 3347 3226 + 9 3307 3308 3349 3348 3227 + 9 3308 3309 3350 3349 3228 + 9 3309 3310 3351 3350 3229 + 9 3310 3311 3352 3351 3230 + 9 3311 3312 3353 3352 3231 + 9 3312 3313 3354 3353 3232 + 9 3313 3314 3355 3354 3233 + 9 3314 3315 3356 3355 3234 + 9 3315 3316 3357 3356 3235 + 9 3316 3317 3358 3357 3236 + 9 3317 3318 3359 3358 3237 + 9 3318 3319 3360 3359 3238 + 9 3319 3320 3361 3360 3239 + 9 3321 3322 3363 3362 3240 + 9 3322 3323 3364 3363 3241 + 9 3323 3324 3365 3364 3242 + 9 3324 3325 3366 3365 3243 + 9 3325 3326 3367 3366 3244 + 9 3326 3327 3368 3367 3245 + 9 3327 3328 3369 3368 3246 + 9 3328 3329 3370 3369 3247 + 9 3329 3330 3371 3370 3248 + 9 3330 3331 3372 3371 3249 + 9 3331 3332 3373 3372 3250 + 9 3332 3333 3374 3373 3251 + 9 3333 3334 3375 3374 3252 + 9 3334 3335 3376 3375 3253 + 9 3335 3336 3377 3376 3254 + 9 3336 3337 3378 3377 3255 + 9 3337 3338 3379 3378 3256 + 9 3338 3339 3380 3379 3257 + 9 3339 3340 3381 3380 3258 + 9 3340 3341 3382 3381 3259 + 9 3341 3342 3383 3382 3260 + 9 3342 3343 3384 3383 3261 + 9 3343 3344 3385 3384 3262 + 9 3344 3345 3386 3385 3263 + 9 3345 3346 3387 3386 3264 + 9 3346 3347 3388 3387 3265 + 9 3347 3348 3389 3388 3266 + 9 3348 3349 3390 3389 3267 + 9 3349 3350 3391 3390 3268 + 9 3350 3351 3392 3391 3269 + 9 3351 3352 3393 3392 3270 + 9 3352 3353 3394 3393 3271 + 9 3353 3354 3395 3394 3272 + 9 3354 3355 3396 3395 3273 + 9 3355 3356 3397 3396 3274 + 9 3356 3357 3398 3397 3275 + 9 3357 3358 3399 3398 3276 + 9 3358 3359 3400 3399 3277 + 9 3359 3360 3401 3400 3278 + 9 3360 3361 3402 3401 3279 + 9 3362 3363 3404 3403 3280 + 9 3363 3364 3405 3404 3281 + 9 3364 3365 3406 3405 3282 + 9 3365 3366 3407 3406 3283 + 9 3366 3367 3408 3407 3284 + 9 3367 3368 3409 3408 3285 + 9 3368 3369 3410 3409 3286 + 9 3369 3370 3411 3410 3287 + 9 3370 3371 3412 3411 3288 + 9 3371 3372 3413 3412 3289 + 9 3372 3373 3414 3413 3290 + 9 3373 3374 3415 3414 3291 + 9 3374 3375 3416 3415 3292 + 9 3375 3376 3417 3416 3293 + 9 3376 3377 3418 3417 3294 + 9 3377 3378 3419 3418 3295 + 9 3378 3379 3420 3419 3296 + 9 3379 3380 3421 3420 3297 + 9 3380 3381 3422 3421 3298 + 9 3381 3382 3423 3422 3299 + 9 3382 3383 3424 3423 3300 + 9 3383 3384 3425 3424 3301 + 9 3384 3385 3426 3425 3302 + 9 3385 3386 3427 3426 3303 + 9 3386 3387 3428 3427 3304 + 9 3387 3388 3429 3428 3305 + 9 3388 3389 3430 3429 3306 + 9 3389 3390 3431 3430 3307 + 9 3390 3391 3432 3431 3308 + 9 3391 3392 3433 3432 3309 + 9 3392 3393 3434 3433 3310 + 9 3393 3394 3435 3434 3311 + 9 3394 3395 3436 3435 3312 + 9 3395 3396 3437 3436 3313 + 9 3396 3397 3438 3437 3314 + 9 3397 3398 3439 3438 3315 + 9 3398 3399 3440 3439 3316 + 9 3399 3400 3441 3440 3317 + 9 3400 3401 3442 3441 3318 + 9 3401 3402 3443 3442 3319 + 9 3403 3404 3445 3444 3320 + 9 3404 3405 3446 3445 3321 + 9 3405 3406 3447 3446 3322 + 9 3406 3407 3448 3447 3323 + 9 3407 3408 3449 3448 3324 + 9 3408 3409 3450 3449 3325 + 9 3409 3410 3451 3450 3326 + 9 3410 3411 3452 3451 3327 + 9 3411 3412 3453 3452 3328 + 9 3412 3413 3454 3453 3329 + 9 3413 3414 3455 3454 3330 + 9 3414 3415 3456 3455 3331 + 9 3415 3416 3457 3456 3332 + 9 3416 3417 3458 3457 3333 + 9 3417 3418 3459 3458 3334 + 9 3418 3419 3460 3459 3335 + 9 3419 3420 3461 3460 3336 + 9 3420 3421 3462 3461 3337 + 9 3421 3422 3463 3462 3338 + 9 3422 3423 3464 3463 3339 + 9 3423 3424 3465 3464 3340 + 9 3424 3425 3466 3465 3341 + 9 3425 3426 3467 3466 3342 + 9 3426 3427 3468 3467 3343 + 9 3427 3428 3469 3468 3344 + 9 3428 3429 3470 3469 3345 + 9 3429 3430 3471 3470 3346 + 9 3430 3431 3472 3471 3347 + 9 3431 3432 3473 3472 3348 + 9 3432 3433 3474 3473 3349 + 9 3433 3434 3475 3474 3350 + 9 3434 3435 3476 3475 3351 + 9 3435 3436 3477 3476 3352 + 9 3436 3437 3478 3477 3353 + 9 3437 3438 3479 3478 3354 + 9 3438 3439 3480 3479 3355 + 9 3439 3440 3481 3480 3356 + 9 3440 3441 3482 3481 3357 + 9 3441 3442 3483 3482 3358 + 9 3442 3443 3484 3483 3359 + 9 3444 3445 3486 3485 3360 + 9 3445 3446 3487 3486 3361 + 9 3446 3447 3488 3487 3362 + 9 3447 3448 3489 3488 3363 + 9 3448 3449 3490 3489 3364 + 9 3449 3450 3491 3490 3365 + 9 3450 3451 3492 3491 3366 + 9 3451 3452 3493 3492 3367 + 9 3452 3453 3494 3493 3368 + 9 3453 3454 3495 3494 3369 + 9 3454 3455 3496 3495 3370 + 9 3455 3456 3497 3496 3371 + 9 3456 3457 3498 3497 3372 + 9 3457 3458 3499 3498 3373 + 9 3458 3459 3500 3499 3374 + 9 3459 3460 3501 3500 3375 + 9 3460 3461 3502 3501 3376 + 9 3461 3462 3503 3502 3377 + 9 3462 3463 3504 3503 3378 + 9 3463 3464 3505 3504 3379 + 9 3464 3465 3506 3505 3380 + 9 3465 3466 3507 3506 3381 + 9 3466 3467 3508 3507 3382 + 9 3467 3468 3509 3508 3383 + 9 3468 3469 3510 3509 3384 + 9 3469 3470 3511 3510 3385 + 9 3470 3471 3512 3511 3386 + 9 3471 3472 3513 3512 3387 + 9 3472 3473 3514 3513 3388 + 9 3473 3474 3515 3514 3389 + 9 3474 3475 3516 3515 3390 + 9 3475 3476 3517 3516 3391 + 9 3476 3477 3518 3517 3392 + 9 3477 3478 3519 3518 3393 + 9 3478 3479 3520 3519 3394 + 9 3479 3480 3521 3520 3395 + 9 3480 3481 3522 3521 3396 + 9 3481 3482 3523 3522 3397 + 9 3482 3483 3524 3523 3398 + 9 3483 3484 3525 3524 3399 + 9 3485 3486 3527 3526 3400 + 9 3486 3487 3528 3527 3401 + 9 3487 3488 3529 3528 3402 + 9 3488 3489 3530 3529 3403 + 9 3489 3490 3531 3530 3404 + 9 3490 3491 3532 3531 3405 + 9 3491 3492 3533 3532 3406 + 9 3492 3493 3534 3533 3407 + 9 3493 3494 3535 3534 3408 + 9 3494 3495 3536 3535 3409 + 9 3495 3496 3537 3536 3410 + 9 3496 3497 3538 3537 3411 + 9 3497 3498 3539 3538 3412 + 9 3498 3499 3540 3539 3413 + 9 3499 3500 3541 3540 3414 + 9 3500 3501 3542 3541 3415 + 9 3501 3502 3543 3542 3416 + 9 3502 3503 3544 3543 3417 + 9 3503 3504 3545 3544 3418 + 9 3504 3505 3546 3545 3419 + 9 3505 3506 3547 3546 3420 + 9 3506 3507 3548 3547 3421 + 9 3507 3508 3549 3548 3422 + 9 3508 3509 3550 3549 3423 + 9 3509 3510 3551 3550 3424 + 9 3510 3511 3552 3551 3425 + 9 3511 3512 3553 3552 3426 + 9 3512 3513 3554 3553 3427 + 9 3513 3514 3555 3554 3428 + 9 3514 3515 3556 3555 3429 + 9 3515 3516 3557 3556 3430 + 9 3516 3517 3558 3557 3431 + 9 3517 3518 3559 3558 3432 + 9 3518 3519 3560 3559 3433 + 9 3519 3520 3561 3560 3434 + 9 3520 3521 3562 3561 3435 + 9 3521 3522 3563 3562 3436 + 9 3522 3523 3564 3563 3437 + 9 3523 3524 3565 3564 3438 + 9 3524 3525 3566 3565 3439 + 9 3526 3527 3568 3567 3440 + 9 3527 3528 3569 3568 3441 + 9 3528 3529 3570 3569 3442 + 9 3529 3530 3571 3570 3443 + 9 3530 3531 3572 3571 3444 + 9 3531 3532 3573 3572 3445 + 9 3532 3533 3574 3573 3446 + 9 3533 3534 3575 3574 3447 + 9 3534 3535 3576 3575 3448 + 9 3535 3536 3577 3576 3449 + 9 3536 3537 3578 3577 3450 + 9 3537 3538 3579 3578 3451 + 9 3538 3539 3580 3579 3452 + 9 3539 3540 3581 3580 3453 + 9 3540 3541 3582 3581 3454 + 9 3541 3542 3583 3582 3455 + 9 3542 3543 3584 3583 3456 + 9 3543 3544 3585 3584 3457 + 9 3544 3545 3586 3585 3458 + 9 3545 3546 3587 3586 3459 + 9 3546 3547 3588 3587 3460 + 9 3547 3548 3589 3588 3461 + 9 3548 3549 3590 3589 3462 + 9 3549 3550 3591 3590 3463 + 9 3550 3551 3592 3591 3464 + 9 3551 3552 3593 3592 3465 + 9 3552 3553 3594 3593 3466 + 9 3553 3554 3595 3594 3467 + 9 3554 3555 3596 3595 3468 + 9 3555 3556 3597 3596 3469 + 9 3556 3557 3598 3597 3470 + 9 3557 3558 3599 3598 3471 + 9 3558 3559 3600 3599 3472 + 9 3559 3560 3601 3600 3473 + 9 3560 3561 3602 3601 3474 + 9 3561 3562 3603 3602 3475 + 9 3562 3563 3604 3603 3476 + 9 3563 3564 3605 3604 3477 + 9 3564 3565 3606 3605 3478 + 9 3565 3566 3607 3606 3479 + 9 3567 3568 3609 3608 3480 + 9 3568 3569 3610 3609 3481 + 9 3569 3570 3611 3610 3482 + 9 3570 3571 3612 3611 3483 + 9 3571 3572 3613 3612 3484 + 9 3572 3573 3614 3613 3485 + 9 3573 3574 3615 3614 3486 + 9 3574 3575 3616 3615 3487 + 9 3575 3576 3617 3616 3488 + 9 3576 3577 3618 3617 3489 + 9 3577 3578 3619 3618 3490 + 9 3578 3579 3620 3619 3491 + 9 3579 3580 3621 3620 3492 + 9 3580 3581 3622 3621 3493 + 9 3581 3582 3623 3622 3494 + 9 3582 3583 3624 3623 3495 + 9 3583 3584 3625 3624 3496 + 9 3584 3585 3626 3625 3497 + 9 3585 3586 3627 3626 3498 + 9 3586 3587 3628 3627 3499 + 9 3587 3588 3629 3628 3500 + 9 3588 3589 3630 3629 3501 + 9 3589 3590 3631 3630 3502 + 9 3590 3591 3632 3631 3503 + 9 3591 3592 3633 3632 3504 + 9 3592 3593 3634 3633 3505 + 9 3593 3594 3635 3634 3506 + 9 3594 3595 3636 3635 3507 + 9 3595 3596 3637 3636 3508 + 9 3596 3597 3638 3637 3509 + 9 3597 3598 3639 3638 3510 + 9 3598 3599 3640 3639 3511 + 9 3599 3600 3641 3640 3512 + 9 3600 3601 3642 3641 3513 + 9 3601 3602 3643 3642 3514 + 9 3602 3603 3644 3643 3515 + 9 3603 3604 3645 3644 3516 + 9 3604 3605 3646 3645 3517 + 9 3605 3606 3647 3646 3518 + 9 3606 3607 3648 3647 3519 + 9 3608 3609 3650 3649 3520 + 9 3609 3610 3651 3650 3521 + 9 3610 3611 3652 3651 3522 + 9 3611 3612 3653 3652 3523 + 9 3612 3613 3654 3653 3524 + 9 3613 3614 3655 3654 3525 + 9 3614 3615 3656 3655 3526 + 9 3615 3616 3657 3656 3527 + 9 3616 3617 3658 3657 3528 + 9 3617 3618 3659 3658 3529 + 9 3618 3619 3660 3659 3530 + 9 3619 3620 3661 3660 3531 + 9 3620 3621 3662 3661 3532 + 9 3621 3622 3663 3662 3533 + 9 3622 3623 3664 3663 3534 + 9 3623 3624 3665 3664 3535 + 9 3624 3625 3666 3665 3536 + 9 3625 3626 3667 3666 3537 + 9 3626 3627 3668 3667 3538 + 9 3627 3628 3669 3668 3539 + 9 3628 3629 3670 3669 3540 + 9 3629 3630 3671 3670 3541 + 9 3630 3631 3672 3671 3542 + 9 3631 3632 3673 3672 3543 + 9 3632 3633 3674 3673 3544 + 9 3633 3634 3675 3674 3545 + 9 3634 3635 3676 3675 3546 + 9 3635 3636 3677 3676 3547 + 9 3636 3637 3678 3677 3548 + 9 3637 3638 3679 3678 3549 + 9 3638 3639 3680 3679 3550 + 9 3639 3640 3681 3680 3551 + 9 3640 3641 3682 3681 3552 + 9 3641 3642 3683 3682 3553 + 9 3642 3643 3684 3683 3554 + 9 3643 3644 3685 3684 3555 + 9 3644 3645 3686 3685 3556 + 9 3645 3646 3687 3686 3557 + 9 3646 3647 3688 3687 3558 + 9 3647 3648 3689 3688 3559 + 9 3649 3650 3691 3690 3560 + 9 3650 3651 3692 3691 3561 + 9 3651 3652 3693 3692 3562 + 9 3652 3653 3694 3693 3563 + 9 3653 3654 3695 3694 3564 + 9 3654 3655 3696 3695 3565 + 9 3655 3656 3697 3696 3566 + 9 3656 3657 3698 3697 3567 + 9 3657 3658 3699 3698 3568 + 9 3658 3659 3700 3699 3569 + 9 3659 3660 3701 3700 3570 + 9 3660 3661 3702 3701 3571 + 9 3661 3662 3703 3702 3572 + 9 3662 3663 3704 3703 3573 + 9 3663 3664 3705 3704 3574 + 9 3664 3665 3706 3705 3575 + 9 3665 3666 3707 3706 3576 + 9 3666 3667 3708 3707 3577 + 9 3667 3668 3709 3708 3578 + 9 3668 3669 3710 3709 3579 + 9 3669 3670 3711 3710 3580 + 9 3670 3671 3712 3711 3581 + 9 3671 3672 3713 3712 3582 + 9 3672 3673 3714 3713 3583 + 9 3673 3674 3715 3714 3584 + 9 3674 3675 3716 3715 3585 + 9 3675 3676 3717 3716 3586 + 9 3676 3677 3718 3717 3587 + 9 3677 3678 3719 3718 3588 + 9 3678 3679 3720 3719 3589 + 9 3679 3680 3721 3720 3590 + 9 3680 3681 3722 3721 3591 + 9 3681 3682 3723 3722 3592 + 9 3682 3683 3724 3723 3593 + 9 3683 3684 3725 3724 3594 + 9 3684 3685 3726 3725 3595 + 9 3685 3686 3727 3726 3596 + 9 3686 3687 3728 3727 3597 + 9 3687 3688 3729 3728 3598 + 9 3688 3689 3730 3729 3599 + 9 3690 3691 3732 3731 3600 + 9 3691 3692 3733 3732 3601 + 9 3692 3693 3734 3733 3602 + 9 3693 3694 3735 3734 3603 + 9 3694 3695 3736 3735 3604 + 9 3695 3696 3737 3736 3605 + 9 3696 3697 3738 3737 3606 + 9 3697 3698 3739 3738 3607 + 9 3698 3699 3740 3739 3608 + 9 3699 3700 3741 3740 3609 + 9 3700 3701 3742 3741 3610 + 9 3701 3702 3743 3742 3611 + 9 3702 3703 3744 3743 3612 + 9 3703 3704 3745 3744 3613 + 9 3704 3705 3746 3745 3614 + 9 3705 3706 3747 3746 3615 + 9 3706 3707 3748 3747 3616 + 9 3707 3708 3749 3748 3617 + 9 3708 3709 3750 3749 3618 + 9 3709 3710 3751 3750 3619 + 9 3710 3711 3752 3751 3620 + 9 3711 3712 3753 3752 3621 + 9 3712 3713 3754 3753 3622 + 9 3713 3714 3755 3754 3623 + 9 3714 3715 3756 3755 3624 + 9 3715 3716 3757 3756 3625 + 9 3716 3717 3758 3757 3626 + 9 3717 3718 3759 3758 3627 + 9 3718 3719 3760 3759 3628 + 9 3719 3720 3761 3760 3629 + 9 3720 3721 3762 3761 3630 + 9 3721 3722 3763 3762 3631 + 9 3722 3723 3764 3763 3632 + 9 3723 3724 3765 3764 3633 + 9 3724 3725 3766 3765 3634 + 9 3725 3726 3767 3766 3635 + 9 3726 3727 3768 3767 3636 + 9 3727 3728 3769 3768 3637 + 9 3728 3729 3770 3769 3638 + 9 3729 3730 3771 3770 3639 + 9 3731 3732 3773 3772 3640 + 9 3732 3733 3774 3773 3641 + 9 3733 3734 3775 3774 3642 + 9 3734 3735 3776 3775 3643 + 9 3735 3736 3777 3776 3644 + 9 3736 3737 3778 3777 3645 + 9 3737 3738 3779 3778 3646 + 9 3738 3739 3780 3779 3647 + 9 3739 3740 3781 3780 3648 + 9 3740 3741 3782 3781 3649 + 9 3741 3742 3783 3782 3650 + 9 3742 3743 3784 3783 3651 + 9 3743 3744 3785 3784 3652 + 9 3744 3745 3786 3785 3653 + 9 3745 3746 3787 3786 3654 + 9 3746 3747 3788 3787 3655 + 9 3747 3748 3789 3788 3656 + 9 3748 3749 3790 3789 3657 + 9 3749 3750 3791 3790 3658 + 9 3750 3751 3792 3791 3659 + 9 3751 3752 3793 3792 3660 + 9 3752 3753 3794 3793 3661 + 9 3753 3754 3795 3794 3662 + 9 3754 3755 3796 3795 3663 + 9 3755 3756 3797 3796 3664 + 9 3756 3757 3798 3797 3665 + 9 3757 3758 3799 3798 3666 + 9 3758 3759 3800 3799 3667 + 9 3759 3760 3801 3800 3668 + 9 3760 3761 3802 3801 3669 + 9 3761 3762 3803 3802 3670 + 9 3762 3763 3804 3803 3671 + 9 3763 3764 3805 3804 3672 + 9 3764 3765 3806 3805 3673 + 9 3765 3766 3807 3806 3674 + 9 3766 3767 3808 3807 3675 + 9 3767 3768 3809 3808 3676 + 9 3768 3769 3810 3809 3677 + 9 3769 3770 3811 3810 3678 + 9 3770 3771 3812 3811 3679 + 9 3772 3773 3814 3813 3680 + 9 3773 3774 3815 3814 3681 + 9 3774 3775 3816 3815 3682 + 9 3775 3776 3817 3816 3683 + 9 3776 3777 3818 3817 3684 + 9 3777 3778 3819 3818 3685 + 9 3778 3779 3820 3819 3686 + 9 3779 3780 3821 3820 3687 + 9 3780 3781 3822 3821 3688 + 9 3781 3782 3823 3822 3689 + 9 3782 3783 3824 3823 3690 + 9 3783 3784 3825 3824 3691 + 9 3784 3785 3826 3825 3692 + 9 3785 3786 3827 3826 3693 + 9 3786 3787 3828 3827 3694 + 9 3787 3788 3829 3828 3695 + 9 3788 3789 3830 3829 3696 + 9 3789 3790 3831 3830 3697 + 9 3790 3791 3832 3831 3698 + 9 3791 3792 3833 3832 3699 + 9 3792 3793 3834 3833 3700 + 9 3793 3794 3835 3834 3701 + 9 3794 3795 3836 3835 3702 + 9 3795 3796 3837 3836 3703 + 9 3796 3797 3838 3837 3704 + 9 3797 3798 3839 3838 3705 + 9 3798 3799 3840 3839 3706 + 9 3799 3800 3841 3840 3707 + 9 3800 3801 3842 3841 3708 + 9 3801 3802 3843 3842 3709 + 9 3802 3803 3844 3843 3710 + 9 3803 3804 3845 3844 3711 + 9 3804 3805 3846 3845 3712 + 9 3805 3806 3847 3846 3713 + 9 3806 3807 3848 3847 3714 + 9 3807 3808 3849 3848 3715 + 9 3808 3809 3850 3849 3716 + 9 3809 3810 3851 3850 3717 + 9 3810 3811 3852 3851 3718 + 9 3811 3812 3853 3852 3719 + 9 3813 3814 3855 3854 3720 + 9 3814 3815 3856 3855 3721 + 9 3815 3816 3857 3856 3722 + 9 3816 3817 3858 3857 3723 + 9 3817 3818 3859 3858 3724 + 9 3818 3819 3860 3859 3725 + 9 3819 3820 3861 3860 3726 + 9 3820 3821 3862 3861 3727 + 9 3821 3822 3863 3862 3728 + 9 3822 3823 3864 3863 3729 + 9 3823 3824 3865 3864 3730 + 9 3824 3825 3866 3865 3731 + 9 3825 3826 3867 3866 3732 + 9 3826 3827 3868 3867 3733 + 9 3827 3828 3869 3868 3734 + 9 3828 3829 3870 3869 3735 + 9 3829 3830 3871 3870 3736 + 9 3830 3831 3872 3871 3737 + 9 3831 3832 3873 3872 3738 + 9 3832 3833 3874 3873 3739 + 9 3833 3834 3875 3874 3740 + 9 3834 3835 3876 3875 3741 + 9 3835 3836 3877 3876 3742 + 9 3836 3837 3878 3877 3743 + 9 3837 3838 3879 3878 3744 + 9 3838 3839 3880 3879 3745 + 9 3839 3840 3881 3880 3746 + 9 3840 3841 3882 3881 3747 + 9 3841 3842 3883 3882 3748 + 9 3842 3843 3884 3883 3749 + 9 3843 3844 3885 3884 3750 + 9 3844 3845 3886 3885 3751 + 9 3845 3846 3887 3886 3752 + 9 3846 3847 3888 3887 3753 + 9 3847 3848 3889 3888 3754 + 9 3848 3849 3890 3889 3755 + 9 3849 3850 3891 3890 3756 + 9 3850 3851 3892 3891 3757 + 9 3851 3852 3893 3892 3758 + 9 3852 3853 3894 3893 3759 + 9 3854 3855 3896 3895 3760 + 9 3855 3856 3897 3896 3761 + 9 3856 3857 3898 3897 3762 + 9 3857 3858 3899 3898 3763 + 9 3858 3859 3900 3899 3764 + 9 3859 3860 3901 3900 3765 + 9 3860 3861 3902 3901 3766 + 9 3861 3862 3903 3902 3767 + 9 3862 3863 3904 3903 3768 + 9 3863 3864 3905 3904 3769 + 9 3864 3865 3906 3905 3770 + 9 3865 3866 3907 3906 3771 + 9 3866 3867 3908 3907 3772 + 9 3867 3868 3909 3908 3773 + 9 3868 3869 3910 3909 3774 + 9 3869 3870 3911 3910 3775 + 9 3870 3871 3912 3911 3776 + 9 3871 3872 3913 3912 3777 + 9 3872 3873 3914 3913 3778 + 9 3873 3874 3915 3914 3779 + 9 3874 3875 3916 3915 3780 + 9 3875 3876 3917 3916 3781 + 9 3876 3877 3918 3917 3782 + 9 3877 3878 3919 3918 3783 + 9 3878 3879 3920 3919 3784 + 9 3879 3880 3921 3920 3785 + 9 3880 3881 3922 3921 3786 + 9 3881 3882 3923 3922 3787 + 9 3882 3883 3924 3923 3788 + 9 3883 3884 3925 3924 3789 + 9 3884 3885 3926 3925 3790 + 9 3885 3886 3927 3926 3791 + 9 3886 3887 3928 3927 3792 + 9 3887 3888 3929 3928 3793 + 9 3888 3889 3930 3929 3794 + 9 3889 3890 3931 3930 3795 + 9 3890 3891 3932 3931 3796 + 9 3891 3892 3933 3932 3797 + 9 3892 3893 3934 3933 3798 + 9 3893 3894 3935 3934 3799 + 9 3895 3896 3937 3936 3800 + 9 3896 3897 3938 3937 3801 + 9 3897 3898 3939 3938 3802 + 9 3898 3899 3940 3939 3803 + 9 3899 3900 3941 3940 3804 + 9 3900 3901 3942 3941 3805 + 9 3901 3902 3943 3942 3806 + 9 3902 3903 3944 3943 3807 + 9 3903 3904 3945 3944 3808 + 9 3904 3905 3946 3945 3809 + 9 3905 3906 3947 3946 3810 + 9 3906 3907 3948 3947 3811 + 9 3907 3908 3949 3948 3812 + 9 3908 3909 3950 3949 3813 + 9 3909 3910 3951 3950 3814 + 9 3910 3911 3952 3951 3815 + 9 3911 3912 3953 3952 3816 + 9 3912 3913 3954 3953 3817 + 9 3913 3914 3955 3954 3818 + 9 3914 3915 3956 3955 3819 + 9 3915 3916 3957 3956 3820 + 9 3916 3917 3958 3957 3821 + 9 3917 3918 3959 3958 3822 + 9 3918 3919 3960 3959 3823 + 9 3919 3920 3961 3960 3824 + 9 3920 3921 3962 3961 3825 + 9 3921 3922 3963 3962 3826 + 9 3922 3923 3964 3963 3827 + 9 3923 3924 3965 3964 3828 + 9 3924 3925 3966 3965 3829 + 9 3925 3926 3967 3966 3830 + 9 3926 3927 3968 3967 3831 + 9 3927 3928 3969 3968 3832 + 9 3928 3929 3970 3969 3833 + 9 3929 3930 3971 3970 3834 + 9 3930 3931 3972 3971 3835 + 9 3931 3932 3973 3972 3836 + 9 3932 3933 3974 3973 3837 + 9 3933 3934 3975 3974 3838 + 9 3934 3935 3976 3975 3839 + 9 3936 3937 3978 3977 3840 + 9 3937 3938 3979 3978 3841 + 9 3938 3939 3980 3979 3842 + 9 3939 3940 3981 3980 3843 + 9 3940 3941 3982 3981 3844 + 9 3941 3942 3983 3982 3845 + 9 3942 3943 3984 3983 3846 + 9 3943 3944 3985 3984 3847 + 9 3944 3945 3986 3985 3848 + 9 3945 3946 3987 3986 3849 + 9 3946 3947 3988 3987 3850 + 9 3947 3948 3989 3988 3851 + 9 3948 3949 3990 3989 3852 + 9 3949 3950 3991 3990 3853 + 9 3950 3951 3992 3991 3854 + 9 3951 3952 3993 3992 3855 + 9 3952 3953 3994 3993 3856 + 9 3953 3954 3995 3994 3857 + 9 3954 3955 3996 3995 3858 + 9 3955 3956 3997 3996 3859 + 9 3956 3957 3998 3997 3860 + 9 3957 3958 3999 3998 3861 + 9 3958 3959 4000 3999 3862 + 9 3959 3960 4001 4000 3863 + 9 3960 3961 4002 4001 3864 + 9 3961 3962 4003 4002 3865 + 9 3962 3963 4004 4003 3866 + 9 3963 3964 4005 4004 3867 + 9 3964 3965 4006 4005 3868 + 9 3965 3966 4007 4006 3869 + 9 3966 3967 4008 4007 3870 + 9 3967 3968 4009 4008 3871 + 9 3968 3969 4010 4009 3872 + 9 3969 3970 4011 4010 3873 + 9 3970 3971 4012 4011 3874 + 9 3971 3972 4013 4012 3875 + 9 3972 3973 4014 4013 3876 + 9 3973 3974 4015 4014 3877 + 9 3974 3975 4016 4015 3878 + 9 3975 3976 4017 4016 3879 + 9 3977 3978 4019 4018 3880 + 9 3978 3979 4020 4019 3881 + 9 3979 3980 4021 4020 3882 + 9 3980 3981 4022 4021 3883 + 9 3981 3982 4023 4022 3884 + 9 3982 3983 4024 4023 3885 + 9 3983 3984 4025 4024 3886 + 9 3984 3985 4026 4025 3887 + 9 3985 3986 4027 4026 3888 + 9 3986 3987 4028 4027 3889 + 9 3987 3988 4029 4028 3890 + 9 3988 3989 4030 4029 3891 + 9 3989 3990 4031 4030 3892 + 9 3990 3991 4032 4031 3893 + 9 3991 3992 4033 4032 3894 + 9 3992 3993 4034 4033 3895 + 9 3993 3994 4035 4034 3896 + 9 3994 3995 4036 4035 3897 + 9 3995 3996 4037 4036 3898 + 9 3996 3997 4038 4037 3899 + 9 3997 3998 4039 4038 3900 + 9 3998 3999 4040 4039 3901 + 9 3999 4000 4041 4040 3902 + 9 4000 4001 4042 4041 3903 + 9 4001 4002 4043 4042 3904 + 9 4002 4003 4044 4043 3905 + 9 4003 4004 4045 4044 3906 + 9 4004 4005 4046 4045 3907 + 9 4005 4006 4047 4046 3908 + 9 4006 4007 4048 4047 3909 + 9 4007 4008 4049 4048 3910 + 9 4008 4009 4050 4049 3911 + 9 4009 4010 4051 4050 3912 + 9 4010 4011 4052 4051 3913 + 9 4011 4012 4053 4052 3914 + 9 4012 4013 4054 4053 3915 + 9 4013 4014 4055 4054 3916 + 9 4014 4015 4056 4055 3917 + 9 4015 4016 4057 4056 3918 + 9 4016 4017 4058 4057 3919 + 9 4018 4019 4060 4059 3920 + 9 4019 4020 4061 4060 3921 + 9 4020 4021 4062 4061 3922 + 9 4021 4022 4063 4062 3923 + 9 4022 4023 4064 4063 3924 + 9 4023 4024 4065 4064 3925 + 9 4024 4025 4066 4065 3926 + 9 4025 4026 4067 4066 3927 + 9 4026 4027 4068 4067 3928 + 9 4027 4028 4069 4068 3929 + 9 4028 4029 4070 4069 3930 + 9 4029 4030 4071 4070 3931 + 9 4030 4031 4072 4071 3932 + 9 4031 4032 4073 4072 3933 + 9 4032 4033 4074 4073 3934 + 9 4033 4034 4075 4074 3935 + 9 4034 4035 4076 4075 3936 + 9 4035 4036 4077 4076 3937 + 9 4036 4037 4078 4077 3938 + 9 4037 4038 4079 4078 3939 + 9 4038 4039 4080 4079 3940 + 9 4039 4040 4081 4080 3941 + 9 4040 4041 4082 4081 3942 + 9 4041 4042 4083 4082 3943 + 9 4042 4043 4084 4083 3944 + 9 4043 4044 4085 4084 3945 + 9 4044 4045 4086 4085 3946 + 9 4045 4046 4087 4086 3947 + 9 4046 4047 4088 4087 3948 + 9 4047 4048 4089 4088 3949 + 9 4048 4049 4090 4089 3950 + 9 4049 4050 4091 4090 3951 + 9 4050 4051 4092 4091 3952 + 9 4051 4052 4093 4092 3953 + 9 4052 4053 4094 4093 3954 + 9 4053 4054 4095 4094 3955 + 9 4054 4055 4096 4095 3956 + 9 4055 4056 4097 4096 3957 + 9 4056 4057 4098 4097 3958 + 9 4057 4058 4099 4098 3959 + 9 4059 4060 4101 4100 3960 + 9 4060 4061 4102 4101 3961 + 9 4061 4062 4103 4102 3962 + 9 4062 4063 4104 4103 3963 + 9 4063 4064 4105 4104 3964 + 9 4064 4065 4106 4105 3965 + 9 4065 4066 4107 4106 3966 + 9 4066 4067 4108 4107 3967 + 9 4067 4068 4109 4108 3968 + 9 4068 4069 4110 4109 3969 + 9 4069 4070 4111 4110 3970 + 9 4070 4071 4112 4111 3971 + 9 4071 4072 4113 4112 3972 + 9 4072 4073 4114 4113 3973 + 9 4073 4074 4115 4114 3974 + 9 4074 4075 4116 4115 3975 + 9 4075 4076 4117 4116 3976 + 9 4076 4077 4118 4117 3977 + 9 4077 4078 4119 4118 3978 + 9 4078 4079 4120 4119 3979 + 9 4079 4080 4121 4120 3980 + 9 4080 4081 4122 4121 3981 + 9 4081 4082 4123 4122 3982 + 9 4082 4083 4124 4123 3983 + 9 4083 4084 4125 4124 3984 + 9 4084 4085 4126 4125 3985 + 9 4085 4086 4127 4126 3986 + 9 4086 4087 4128 4127 3987 + 9 4087 4088 4129 4128 3988 + 9 4088 4089 4130 4129 3989 + 9 4089 4090 4131 4130 3990 + 9 4090 4091 4132 4131 3991 + 9 4091 4092 4133 4132 3992 + 9 4092 4093 4134 4133 3993 + 9 4093 4094 4135 4134 3994 + 9 4094 4095 4136 4135 3995 + 9 4095 4096 4137 4136 3996 + 9 4096 4097 4138 4137 3997 + 9 4097 4098 4139 4138 3998 + 9 4098 4099 4140 4139 3999 + 9 4100 4101 4142 4141 4000 + 9 4101 4102 4143 4142 4001 + 9 4102 4103 4144 4143 4002 + 9 4103 4104 4145 4144 4003 + 9 4104 4105 4146 4145 4004 + 9 4105 4106 4147 4146 4005 + 9 4106 4107 4148 4147 4006 + 9 4107 4108 4149 4148 4007 + 9 4108 4109 4150 4149 4008 + 9 4109 4110 4151 4150 4009 + 9 4110 4111 4152 4151 4010 + 9 4111 4112 4153 4152 4011 + 9 4112 4113 4154 4153 4012 + 9 4113 4114 4155 4154 4013 + 9 4114 4115 4156 4155 4014 + 9 4115 4116 4157 4156 4015 + 9 4116 4117 4158 4157 4016 + 9 4117 4118 4159 4158 4017 + 9 4118 4119 4160 4159 4018 + 9 4119 4120 4161 4160 4019 + 9 4120 4121 4162 4161 4020 + 9 4121 4122 4163 4162 4021 + 9 4122 4123 4164 4163 4022 + 9 4123 4124 4165 4164 4023 + 9 4124 4125 4166 4165 4024 + 9 4125 4126 4167 4166 4025 + 9 4126 4127 4168 4167 4026 + 9 4127 4128 4169 4168 4027 + 9 4128 4129 4170 4169 4028 + 9 4129 4130 4171 4170 4029 + 9 4130 4131 4172 4171 4030 + 9 4131 4132 4173 4172 4031 + 9 4132 4133 4174 4173 4032 + 9 4133 4134 4175 4174 4033 + 9 4134 4135 4176 4175 4034 + 9 4135 4136 4177 4176 4035 + 9 4136 4137 4178 4177 4036 + 9 4137 4138 4179 4178 4037 + 9 4138 4139 4180 4179 4038 + 9 4139 4140 4181 4180 4039 + 9 4141 4142 4183 4182 4040 + 9 4142 4143 4184 4183 4041 + 9 4143 4144 4185 4184 4042 + 9 4144 4145 4186 4185 4043 + 9 4145 4146 4187 4186 4044 + 9 4146 4147 4188 4187 4045 + 9 4147 4148 4189 4188 4046 + 9 4148 4149 4190 4189 4047 + 9 4149 4150 4191 4190 4048 + 9 4150 4151 4192 4191 4049 + 9 4151 4152 4193 4192 4050 + 9 4152 4153 4194 4193 4051 + 9 4153 4154 4195 4194 4052 + 9 4154 4155 4196 4195 4053 + 9 4155 4156 4197 4196 4054 + 9 4156 4157 4198 4197 4055 + 9 4157 4158 4199 4198 4056 + 9 4158 4159 4200 4199 4057 + 9 4159 4160 4201 4200 4058 + 9 4160 4161 4202 4201 4059 + 9 4161 4162 4203 4202 4060 + 9 4162 4163 4204 4203 4061 + 9 4163 4164 4205 4204 4062 + 9 4164 4165 4206 4205 4063 + 9 4165 4166 4207 4206 4064 + 9 4166 4167 4208 4207 4065 + 9 4167 4168 4209 4208 4066 + 9 4168 4169 4210 4209 4067 + 9 4169 4170 4211 4210 4068 + 9 4170 4171 4212 4211 4069 + 9 4171 4172 4213 4212 4070 + 9 4172 4173 4214 4213 4071 + 9 4173 4174 4215 4214 4072 + 9 4174 4175 4216 4215 4073 + 9 4175 4176 4217 4216 4074 + 9 4176 4177 4218 4217 4075 + 9 4177 4178 4219 4218 4076 + 9 4178 4179 4220 4219 4077 + 9 4179 4180 4221 4220 4078 + 9 4180 4181 4222 4221 4079 + 9 4182 4183 4224 4223 4080 + 9 4183 4184 4225 4224 4081 + 9 4184 4185 4226 4225 4082 + 9 4185 4186 4227 4226 4083 + 9 4186 4187 4228 4227 4084 + 9 4187 4188 4229 4228 4085 + 9 4188 4189 4230 4229 4086 + 9 4189 4190 4231 4230 4087 + 9 4190 4191 4232 4231 4088 + 9 4191 4192 4233 4232 4089 + 9 4192 4193 4234 4233 4090 + 9 4193 4194 4235 4234 4091 + 9 4194 4195 4236 4235 4092 + 9 4195 4196 4237 4236 4093 + 9 4196 4197 4238 4237 4094 + 9 4197 4198 4239 4238 4095 + 9 4198 4199 4240 4239 4096 + 9 4199 4200 4241 4240 4097 + 9 4200 4201 4242 4241 4098 + 9 4201 4202 4243 4242 4099 + 9 4202 4203 4244 4243 4100 + 9 4203 4204 4245 4244 4101 + 9 4204 4205 4246 4245 4102 + 9 4205 4206 4247 4246 4103 + 9 4206 4207 4248 4247 4104 + 9 4207 4208 4249 4248 4105 + 9 4208 4209 4250 4249 4106 + 9 4209 4210 4251 4250 4107 + 9 4210 4211 4252 4251 4108 + 9 4211 4212 4253 4252 4109 + 9 4212 4213 4254 4253 4110 + 9 4213 4214 4255 4254 4111 + 9 4214 4215 4256 4255 4112 + 9 4215 4216 4257 4256 4113 + 9 4216 4217 4258 4257 4114 + 9 4217 4218 4259 4258 4115 + 9 4218 4219 4260 4259 4116 + 9 4219 4220 4261 4260 4117 + 9 4220 4221 4262 4261 4118 + 9 4221 4222 4263 4262 4119 + 9 4223 4224 4265 4264 4120 + 9 4224 4225 4266 4265 4121 + 9 4225 4226 4267 4266 4122 + 9 4226 4227 4268 4267 4123 + 9 4227 4228 4269 4268 4124 + 9 4228 4229 4270 4269 4125 + 9 4229 4230 4271 4270 4126 + 9 4230 4231 4272 4271 4127 + 9 4231 4232 4273 4272 4128 + 9 4232 4233 4274 4273 4129 + 9 4233 4234 4275 4274 4130 + 9 4234 4235 4276 4275 4131 + 9 4235 4236 4277 4276 4132 + 9 4236 4237 4278 4277 4133 + 9 4237 4238 4279 4278 4134 + 9 4238 4239 4280 4279 4135 + 9 4239 4240 4281 4280 4136 + 9 4240 4241 4282 4281 4137 + 9 4241 4242 4283 4282 4138 + 9 4242 4243 4284 4283 4139 + 9 4243 4244 4285 4284 4140 + 9 4244 4245 4286 4285 4141 + 9 4245 4246 4287 4286 4142 + 9 4246 4247 4288 4287 4143 + 9 4247 4248 4289 4288 4144 + 9 4248 4249 4290 4289 4145 + 9 4249 4250 4291 4290 4146 + 9 4250 4251 4292 4291 4147 + 9 4251 4252 4293 4292 4148 + 9 4252 4253 4294 4293 4149 + 9 4253 4254 4295 4294 4150 + 9 4254 4255 4296 4295 4151 + 9 4255 4256 4297 4296 4152 + 9 4256 4257 4298 4297 4153 + 9 4257 4258 4299 4298 4154 + 9 4258 4259 4300 4299 4155 + 9 4259 4260 4301 4300 4156 + 9 4260 4261 4302 4301 4157 + 9 4261 4262 4303 4302 4158 + 9 4262 4263 4304 4303 4159 + 9 4264 4265 4306 4305 4160 + 9 4265 4266 4307 4306 4161 + 9 4266 4267 4308 4307 4162 + 9 4267 4268 4309 4308 4163 + 9 4268 4269 4310 4309 4164 + 9 4269 4270 4311 4310 4165 + 9 4270 4271 4312 4311 4166 + 9 4271 4272 4313 4312 4167 + 9 4272 4273 4314 4313 4168 + 9 4273 4274 4315 4314 4169 + 9 4274 4275 4316 4315 4170 + 9 4275 4276 4317 4316 4171 + 9 4276 4277 4318 4317 4172 + 9 4277 4278 4319 4318 4173 + 9 4278 4279 4320 4319 4174 + 9 4279 4280 4321 4320 4175 + 9 4280 4281 4322 4321 4176 + 9 4281 4282 4323 4322 4177 + 9 4282 4283 4324 4323 4178 + 9 4283 4284 4325 4324 4179 + 9 4284 4285 4326 4325 4180 + 9 4285 4286 4327 4326 4181 + 9 4286 4287 4328 4327 4182 + 9 4287 4288 4329 4328 4183 + 9 4288 4289 4330 4329 4184 + 9 4289 4290 4331 4330 4185 + 9 4290 4291 4332 4331 4186 + 9 4291 4292 4333 4332 4187 + 9 4292 4293 4334 4333 4188 + 9 4293 4294 4335 4334 4189 + 9 4294 4295 4336 4335 4190 + 9 4295 4296 4337 4336 4191 + 9 4296 4297 4338 4337 4192 + 9 4297 4298 4339 4338 4193 + 9 4298 4299 4340 4339 4194 + 9 4299 4300 4341 4340 4195 + 9 4300 4301 4342 4341 4196 + 9 4301 4302 4343 4342 4197 + 9 4302 4303 4344 4343 4198 + 9 4303 4304 4345 4344 4199 + 9 4305 4306 4347 4346 4200 + 9 4306 4307 4348 4347 4201 + 9 4307 4308 4349 4348 4202 + 9 4308 4309 4350 4349 4203 + 9 4309 4310 4351 4350 4204 + 9 4310 4311 4352 4351 4205 + 9 4311 4312 4353 4352 4206 + 9 4312 4313 4354 4353 4207 + 9 4313 4314 4355 4354 4208 + 9 4314 4315 4356 4355 4209 + 9 4315 4316 4357 4356 4210 + 9 4316 4317 4358 4357 4211 + 9 4317 4318 4359 4358 4212 + 9 4318 4319 4360 4359 4213 + 9 4319 4320 4361 4360 4214 + 9 4320 4321 4362 4361 4215 + 9 4321 4322 4363 4362 4216 + 9 4322 4323 4364 4363 4217 + 9 4323 4324 4365 4364 4218 + 9 4324 4325 4366 4365 4219 + 9 4325 4326 4367 4366 4220 + 9 4326 4327 4368 4367 4221 + 9 4327 4328 4369 4368 4222 + 9 4328 4329 4370 4369 4223 + 9 4329 4330 4371 4370 4224 + 9 4330 4331 4372 4371 4225 + 9 4331 4332 4373 4372 4226 + 9 4332 4333 4374 4373 4227 + 9 4333 4334 4375 4374 4228 + 9 4334 4335 4376 4375 4229 + 9 4335 4336 4377 4376 4230 + 9 4336 4337 4378 4377 4231 + 9 4337 4338 4379 4378 4232 + 9 4338 4339 4380 4379 4233 + 9 4339 4340 4381 4380 4234 + 9 4340 4341 4382 4381 4235 + 9 4341 4342 4383 4382 4236 + 9 4342 4343 4384 4383 4237 + 9 4343 4344 4385 4384 4238 + 9 4344 4345 4386 4385 4239 + 9 4346 4347 4388 4387 4240 + 9 4347 4348 4389 4388 4241 + 9 4348 4349 4390 4389 4242 + 9 4349 4350 4391 4390 4243 + 9 4350 4351 4392 4391 4244 + 9 4351 4352 4393 4392 4245 + 9 4352 4353 4394 4393 4246 + 9 4353 4354 4395 4394 4247 + 9 4354 4355 4396 4395 4248 + 9 4355 4356 4397 4396 4249 + 9 4356 4357 4398 4397 4250 + 9 4357 4358 4399 4398 4251 + 9 4358 4359 4400 4399 4252 + 9 4359 4360 4401 4400 4253 + 9 4360 4361 4402 4401 4254 + 9 4361 4362 4403 4402 4255 + 9 4362 4363 4404 4403 4256 + 9 4363 4364 4405 4404 4257 + 9 4364 4365 4406 4405 4258 + 9 4365 4366 4407 4406 4259 + 9 4366 4367 4408 4407 4260 + 9 4367 4368 4409 4408 4261 + 9 4368 4369 4410 4409 4262 + 9 4369 4370 4411 4410 4263 + 9 4370 4371 4412 4411 4264 + 9 4371 4372 4413 4412 4265 + 9 4372 4373 4414 4413 4266 + 9 4373 4374 4415 4414 4267 + 9 4374 4375 4416 4415 4268 + 9 4375 4376 4417 4416 4269 + 9 4376 4377 4418 4417 4270 + 9 4377 4378 4419 4418 4271 + 9 4378 4379 4420 4419 4272 + 9 4379 4380 4421 4420 4273 + 9 4380 4381 4422 4421 4274 + 9 4381 4382 4423 4422 4275 + 9 4382 4383 4424 4423 4276 + 9 4383 4384 4425 4424 4277 + 9 4384 4385 4426 4425 4278 + 9 4385 4386 4427 4426 4279 + 9 4387 4388 4429 4428 4280 + 9 4388 4389 4430 4429 4281 + 9 4389 4390 4431 4430 4282 + 9 4390 4391 4432 4431 4283 + 9 4391 4392 4433 4432 4284 + 9 4392 4393 4434 4433 4285 + 9 4393 4394 4435 4434 4286 + 9 4394 4395 4436 4435 4287 + 9 4395 4396 4437 4436 4288 + 9 4396 4397 4438 4437 4289 + 9 4397 4398 4439 4438 4290 + 9 4398 4399 4440 4439 4291 + 9 4399 4400 4441 4440 4292 + 9 4400 4401 4442 4441 4293 + 9 4401 4402 4443 4442 4294 + 9 4402 4403 4444 4443 4295 + 9 4403 4404 4445 4444 4296 + 9 4404 4405 4446 4445 4297 + 9 4405 4406 4447 4446 4298 + 9 4406 4407 4448 4447 4299 + 9 4407 4408 4449 4448 4300 + 9 4408 4409 4450 4449 4301 + 9 4409 4410 4451 4450 4302 + 9 4410 4411 4452 4451 4303 + 9 4411 4412 4453 4452 4304 + 9 4412 4413 4454 4453 4305 + 9 4413 4414 4455 4454 4306 + 9 4414 4415 4456 4455 4307 + 9 4415 4416 4457 4456 4308 + 9 4416 4417 4458 4457 4309 + 9 4417 4418 4459 4458 4310 + 9 4418 4419 4460 4459 4311 + 9 4419 4420 4461 4460 4312 + 9 4420 4421 4462 4461 4313 + 9 4421 4422 4463 4462 4314 + 9 4422 4423 4464 4463 4315 + 9 4423 4424 4465 4464 4316 + 9 4424 4425 4466 4465 4317 + 9 4425 4426 4467 4466 4318 + 9 4426 4427 4468 4467 4319 + 9 4428 4429 4470 4469 4320 + 9 4429 4430 4471 4470 4321 + 9 4430 4431 4472 4471 4322 + 9 4431 4432 4473 4472 4323 + 9 4432 4433 4474 4473 4324 + 9 4433 4434 4475 4474 4325 + 9 4434 4435 4476 4475 4326 + 9 4435 4436 4477 4476 4327 + 9 4436 4437 4478 4477 4328 + 9 4437 4438 4479 4478 4329 + 9 4438 4439 4480 4479 4330 + 9 4439 4440 4481 4480 4331 + 9 4440 4441 4482 4481 4332 + 9 4441 4442 4483 4482 4333 + 9 4442 4443 4484 4483 4334 + 9 4443 4444 4485 4484 4335 + 9 4444 4445 4486 4485 4336 + 9 4445 4446 4487 4486 4337 + 9 4446 4447 4488 4487 4338 + 9 4447 4448 4489 4488 4339 + 9 4448 4449 4490 4489 4340 + 9 4449 4450 4491 4490 4341 + 9 4450 4451 4492 4491 4342 + 9 4451 4452 4493 4492 4343 + 9 4452 4453 4494 4493 4344 + 9 4453 4454 4495 4494 4345 + 9 4454 4455 4496 4495 4346 + 9 4455 4456 4497 4496 4347 + 9 4456 4457 4498 4497 4348 + 9 4457 4458 4499 4498 4349 + 9 4458 4459 4500 4499 4350 + 9 4459 4460 4501 4500 4351 + 9 4460 4461 4502 4501 4352 + 9 4461 4462 4503 4502 4353 + 9 4462 4463 4504 4503 4354 + 9 4463 4464 4505 4504 4355 + 9 4464 4465 4506 4505 4356 + 9 4465 4466 4507 4506 4357 + 9 4466 4467 4508 4507 4358 + 9 4467 4468 4509 4508 4359 + 9 4469 4470 4511 4510 4360 + 9 4470 4471 4512 4511 4361 + 9 4471 4472 4513 4512 4362 + 9 4472 4473 4514 4513 4363 + 9 4473 4474 4515 4514 4364 + 9 4474 4475 4516 4515 4365 + 9 4475 4476 4517 4516 4366 + 9 4476 4477 4518 4517 4367 + 9 4477 4478 4519 4518 4368 + 9 4478 4479 4520 4519 4369 + 9 4479 4480 4521 4520 4370 + 9 4480 4481 4522 4521 4371 + 9 4481 4482 4523 4522 4372 + 9 4482 4483 4524 4523 4373 + 9 4483 4484 4525 4524 4374 + 9 4484 4485 4526 4525 4375 + 9 4485 4486 4527 4526 4376 + 9 4486 4487 4528 4527 4377 + 9 4487 4488 4529 4528 4378 + 9 4488 4489 4530 4529 4379 + 9 4489 4490 4531 4530 4380 + 9 4490 4491 4532 4531 4381 + 9 4491 4492 4533 4532 4382 + 9 4492 4493 4534 4533 4383 + 9 4493 4494 4535 4534 4384 + 9 4494 4495 4536 4535 4385 + 9 4495 4496 4537 4536 4386 + 9 4496 4497 4538 4537 4387 + 9 4497 4498 4539 4538 4388 + 9 4498 4499 4540 4539 4389 + 9 4499 4500 4541 4540 4390 + 9 4500 4501 4542 4541 4391 + 9 4501 4502 4543 4542 4392 + 9 4502 4503 4544 4543 4393 + 9 4503 4504 4545 4544 4394 + 9 4504 4505 4546 4545 4395 + 9 4505 4506 4547 4546 4396 + 9 4506 4507 4548 4547 4397 + 9 4507 4508 4549 4548 4398 + 9 4508 4509 4550 4549 4399 + 9 4510 4511 4552 4551 4400 + 9 4511 4512 4553 4552 4401 + 9 4512 4513 4554 4553 4402 + 9 4513 4514 4555 4554 4403 + 9 4514 4515 4556 4555 4404 + 9 4515 4516 4557 4556 4405 + 9 4516 4517 4558 4557 4406 + 9 4517 4518 4559 4558 4407 + 9 4518 4519 4560 4559 4408 + 9 4519 4520 4561 4560 4409 + 9 4520 4521 4562 4561 4410 + 9 4521 4522 4563 4562 4411 + 9 4522 4523 4564 4563 4412 + 9 4523 4524 4565 4564 4413 + 9 4524 4525 4566 4565 4414 + 9 4525 4526 4567 4566 4415 + 9 4526 4527 4568 4567 4416 + 9 4527 4528 4569 4568 4417 + 9 4528 4529 4570 4569 4418 + 9 4529 4530 4571 4570 4419 + 9 4530 4531 4572 4571 4420 + 9 4531 4532 4573 4572 4421 + 9 4532 4533 4574 4573 4422 + 9 4533 4534 4575 4574 4423 + 9 4534 4535 4576 4575 4424 + 9 4535 4536 4577 4576 4425 + 9 4536 4537 4578 4577 4426 + 9 4537 4538 4579 4578 4427 + 9 4538 4539 4580 4579 4428 + 9 4539 4540 4581 4580 4429 + 9 4540 4541 4582 4581 4430 + 9 4541 4542 4583 4582 4431 + 9 4542 4543 4584 4583 4432 + 9 4543 4544 4585 4584 4433 + 9 4544 4545 4586 4585 4434 + 9 4545 4546 4587 4586 4435 + 9 4546 4547 4588 4587 4436 + 9 4547 4548 4589 4588 4437 + 9 4548 4549 4590 4589 4438 + 9 4549 4550 4591 4590 4439 + 9 4551 4552 4593 4592 4440 + 9 4552 4553 4594 4593 4441 + 9 4553 4554 4595 4594 4442 + 9 4554 4555 4596 4595 4443 + 9 4555 4556 4597 4596 4444 + 9 4556 4557 4598 4597 4445 + 9 4557 4558 4599 4598 4446 + 9 4558 4559 4600 4599 4447 + 9 4559 4560 4601 4600 4448 + 9 4560 4561 4602 4601 4449 + 9 4561 4562 4603 4602 4450 + 9 4562 4563 4604 4603 4451 + 9 4563 4564 4605 4604 4452 + 9 4564 4565 4606 4605 4453 + 9 4565 4566 4607 4606 4454 + 9 4566 4567 4608 4607 4455 + 9 4567 4568 4609 4608 4456 + 9 4568 4569 4610 4609 4457 + 9 4569 4570 4611 4610 4458 + 9 4570 4571 4612 4611 4459 + 9 4571 4572 4613 4612 4460 + 9 4572 4573 4614 4613 4461 + 9 4573 4574 4615 4614 4462 + 9 4574 4575 4616 4615 4463 + 9 4575 4576 4617 4616 4464 + 9 4576 4577 4618 4617 4465 + 9 4577 4578 4619 4618 4466 + 9 4578 4579 4620 4619 4467 + 9 4579 4580 4621 4620 4468 + 9 4580 4581 4622 4621 4469 + 9 4581 4582 4623 4622 4470 + 9 4582 4583 4624 4623 4471 + 9 4583 4584 4625 4624 4472 + 9 4584 4585 4626 4625 4473 + 9 4585 4586 4627 4626 4474 + 9 4586 4587 4628 4627 4475 + 9 4587 4588 4629 4628 4476 + 9 4588 4589 4630 4629 4477 + 9 4589 4590 4631 4630 4478 + 9 4590 4591 4632 4631 4479 + 9 4592 4593 4634 4633 4480 + 9 4593 4594 4635 4634 4481 + 9 4594 4595 4636 4635 4482 + 9 4595 4596 4637 4636 4483 + 9 4596 4597 4638 4637 4484 + 9 4597 4598 4639 4638 4485 + 9 4598 4599 4640 4639 4486 + 9 4599 4600 4641 4640 4487 + 9 4600 4601 4642 4641 4488 + 9 4601 4602 4643 4642 4489 + 9 4602 4603 4644 4643 4490 + 9 4603 4604 4645 4644 4491 + 9 4604 4605 4646 4645 4492 + 9 4605 4606 4647 4646 4493 + 9 4606 4607 4648 4647 4494 + 9 4607 4608 4649 4648 4495 + 9 4608 4609 4650 4649 4496 + 9 4609 4610 4651 4650 4497 + 9 4610 4611 4652 4651 4498 + 9 4611 4612 4653 4652 4499 + 9 4612 4613 4654 4653 4500 + 9 4613 4614 4655 4654 4501 + 9 4614 4615 4656 4655 4502 + 9 4615 4616 4657 4656 4503 + 9 4616 4617 4658 4657 4504 + 9 4617 4618 4659 4658 4505 + 9 4618 4619 4660 4659 4506 + 9 4619 4620 4661 4660 4507 + 9 4620 4621 4662 4661 4508 + 9 4621 4622 4663 4662 4509 + 9 4622 4623 4664 4663 4510 + 9 4623 4624 4665 4664 4511 + 9 4624 4625 4666 4665 4512 + 9 4625 4626 4667 4666 4513 + 9 4626 4627 4668 4667 4514 + 9 4627 4628 4669 4668 4515 + 9 4628 4629 4670 4669 4516 + 9 4629 4630 4671 4670 4517 + 9 4630 4631 4672 4671 4518 + 9 4631 4632 4673 4672 4519 + 9 4633 4634 4675 4674 4520 + 9 4634 4635 4676 4675 4521 + 9 4635 4636 4677 4676 4522 + 9 4636 4637 4678 4677 4523 + 9 4637 4638 4679 4678 4524 + 9 4638 4639 4680 4679 4525 + 9 4639 4640 4681 4680 4526 + 9 4640 4641 4682 4681 4527 + 9 4641 4642 4683 4682 4528 + 9 4642 4643 4684 4683 4529 + 9 4643 4644 4685 4684 4530 + 9 4644 4645 4686 4685 4531 + 9 4645 4646 4687 4686 4532 + 9 4646 4647 4688 4687 4533 + 9 4647 4648 4689 4688 4534 + 9 4648 4649 4690 4689 4535 + 9 4649 4650 4691 4690 4536 + 9 4650 4651 4692 4691 4537 + 9 4651 4652 4693 4692 4538 + 9 4652 4653 4694 4693 4539 + 9 4653 4654 4695 4694 4540 + 9 4654 4655 4696 4695 4541 + 9 4655 4656 4697 4696 4542 + 9 4656 4657 4698 4697 4543 + 9 4657 4658 4699 4698 4544 + 9 4658 4659 4700 4699 4545 + 9 4659 4660 4701 4700 4546 + 9 4660 4661 4702 4701 4547 + 9 4661 4662 4703 4702 4548 + 9 4662 4663 4704 4703 4549 + 9 4663 4664 4705 4704 4550 + 9 4664 4665 4706 4705 4551 + 9 4665 4666 4707 4706 4552 + 9 4666 4667 4708 4707 4553 + 9 4667 4668 4709 4708 4554 + 9 4668 4669 4710 4709 4555 + 9 4669 4670 4711 4710 4556 + 9 4670 4671 4712 4711 4557 + 9 4671 4672 4713 4712 4558 + 9 4672 4673 4714 4713 4559 + 9 4674 4675 4716 4715 4560 + 9 4675 4676 4717 4716 4561 + 9 4676 4677 4718 4717 4562 + 9 4677 4678 4719 4718 4563 + 9 4678 4679 4720 4719 4564 + 9 4679 4680 4721 4720 4565 + 9 4680 4681 4722 4721 4566 + 9 4681 4682 4723 4722 4567 + 9 4682 4683 4724 4723 4568 + 9 4683 4684 4725 4724 4569 + 9 4684 4685 4726 4725 4570 + 9 4685 4686 4727 4726 4571 + 9 4686 4687 4728 4727 4572 + 9 4687 4688 4729 4728 4573 + 9 4688 4689 4730 4729 4574 + 9 4689 4690 4731 4730 4575 + 9 4690 4691 4732 4731 4576 + 9 4691 4692 4733 4732 4577 + 9 4692 4693 4734 4733 4578 + 9 4693 4694 4735 4734 4579 + 9 4694 4695 4736 4735 4580 + 9 4695 4696 4737 4736 4581 + 9 4696 4697 4738 4737 4582 + 9 4697 4698 4739 4738 4583 + 9 4698 4699 4740 4739 4584 + 9 4699 4700 4741 4740 4585 + 9 4700 4701 4742 4741 4586 + 9 4701 4702 4743 4742 4587 + 9 4702 4703 4744 4743 4588 + 9 4703 4704 4745 4744 4589 + 9 4704 4705 4746 4745 4590 + 9 4705 4706 4747 4746 4591 + 9 4706 4707 4748 4747 4592 + 9 4707 4708 4749 4748 4593 + 9 4708 4709 4750 4749 4594 + 9 4709 4710 4751 4750 4595 + 9 4710 4711 4752 4751 4596 + 9 4711 4712 4753 4752 4597 + 9 4712 4713 4754 4753 4598 + 9 4713 4714 4755 4754 4599 + 9 4715 4716 4757 4756 4600 + 9 4716 4717 4758 4757 4601 + 9 4717 4718 4759 4758 4602 + 9 4718 4719 4760 4759 4603 + 9 4719 4720 4761 4760 4604 + 9 4720 4721 4762 4761 4605 + 9 4721 4722 4763 4762 4606 + 9 4722 4723 4764 4763 4607 + 9 4723 4724 4765 4764 4608 + 9 4724 4725 4766 4765 4609 + 9 4725 4726 4767 4766 4610 + 9 4726 4727 4768 4767 4611 + 9 4727 4728 4769 4768 4612 + 9 4728 4729 4770 4769 4613 + 9 4729 4730 4771 4770 4614 + 9 4730 4731 4772 4771 4615 + 9 4731 4732 4773 4772 4616 + 9 4732 4733 4774 4773 4617 + 9 4733 4734 4775 4774 4618 + 9 4734 4735 4776 4775 4619 + 9 4735 4736 4777 4776 4620 + 9 4736 4737 4778 4777 4621 + 9 4737 4738 4779 4778 4622 + 9 4738 4739 4780 4779 4623 + 9 4739 4740 4781 4780 4624 + 9 4740 4741 4782 4781 4625 + 9 4741 4742 4783 4782 4626 + 9 4742 4743 4784 4783 4627 + 9 4743 4744 4785 4784 4628 + 9 4744 4745 4786 4785 4629 + 9 4745 4746 4787 4786 4630 + 9 4746 4747 4788 4787 4631 + 9 4747 4748 4789 4788 4632 + 9 4748 4749 4790 4789 4633 + 9 4749 4750 4791 4790 4634 + 9 4750 4751 4792 4791 4635 + 9 4751 4752 4793 4792 4636 + 9 4752 4753 4794 4793 4637 + 9 4753 4754 4795 4794 4638 + 9 4754 4755 4796 4795 4639 + 9 4756 4757 4798 4797 4640 + 9 4757 4758 4799 4798 4641 + 9 4758 4759 4800 4799 4642 + 9 4759 4760 4801 4800 4643 + 9 4760 4761 4802 4801 4644 + 9 4761 4762 4803 4802 4645 + 9 4762 4763 4804 4803 4646 + 9 4763 4764 4805 4804 4647 + 9 4764 4765 4806 4805 4648 + 9 4765 4766 4807 4806 4649 + 9 4766 4767 4808 4807 4650 + 9 4767 4768 4809 4808 4651 + 9 4768 4769 4810 4809 4652 + 9 4769 4770 4811 4810 4653 + 9 4770 4771 4812 4811 4654 + 9 4771 4772 4813 4812 4655 + 9 4772 4773 4814 4813 4656 + 9 4773 4774 4815 4814 4657 + 9 4774 4775 4816 4815 4658 + 9 4775 4776 4817 4816 4659 + 9 4776 4777 4818 4817 4660 + 9 4777 4778 4819 4818 4661 + 9 4778 4779 4820 4819 4662 + 9 4779 4780 4821 4820 4663 + 9 4780 4781 4822 4821 4664 + 9 4781 4782 4823 4822 4665 + 9 4782 4783 4824 4823 4666 + 9 4783 4784 4825 4824 4667 + 9 4784 4785 4826 4825 4668 + 9 4785 4786 4827 4826 4669 + 9 4786 4787 4828 4827 4670 + 9 4787 4788 4829 4828 4671 + 9 4788 4789 4830 4829 4672 + 9 4789 4790 4831 4830 4673 + 9 4790 4791 4832 4831 4674 + 9 4791 4792 4833 4832 4675 + 9 4792 4793 4834 4833 4676 + 9 4793 4794 4835 4834 4677 + 9 4794 4795 4836 4835 4678 + 9 4795 4796 4837 4836 4679 + 9 4797 4798 4839 4838 4680 + 9 4798 4799 4840 4839 4681 + 9 4799 4800 4841 4840 4682 + 9 4800 4801 4842 4841 4683 + 9 4801 4802 4843 4842 4684 + 9 4802 4803 4844 4843 4685 + 9 4803 4804 4845 4844 4686 + 9 4804 4805 4846 4845 4687 + 9 4805 4806 4847 4846 4688 + 9 4806 4807 4848 4847 4689 + 9 4807 4808 4849 4848 4690 + 9 4808 4809 4850 4849 4691 + 9 4809 4810 4851 4850 4692 + 9 4810 4811 4852 4851 4693 + 9 4811 4812 4853 4852 4694 + 9 4812 4813 4854 4853 4695 + 9 4813 4814 4855 4854 4696 + 9 4814 4815 4856 4855 4697 + 9 4815 4816 4857 4856 4698 + 9 4816 4817 4858 4857 4699 + 9 4817 4818 4859 4858 4700 + 9 4818 4819 4860 4859 4701 + 9 4819 4820 4861 4860 4702 + 9 4820 4821 4862 4861 4703 + 9 4821 4822 4863 4862 4704 + 9 4822 4823 4864 4863 4705 + 9 4823 4824 4865 4864 4706 + 9 4824 4825 4866 4865 4707 + 9 4825 4826 4867 4866 4708 + 9 4826 4827 4868 4867 4709 + 9 4827 4828 4869 4868 4710 + 9 4828 4829 4870 4869 4711 + 9 4829 4830 4871 4870 4712 + 9 4830 4831 4872 4871 4713 + 9 4831 4832 4873 4872 4714 + 9 4832 4833 4874 4873 4715 + 9 4833 4834 4875 4874 4716 + 9 4834 4835 4876 4875 4717 + 9 4835 4836 4877 4876 4718 + 9 4836 4837 4878 4877 4719 + 9 4838 4839 4880 4879 4720 + 9 4839 4840 4881 4880 4721 + 9 4840 4841 4882 4881 4722 + 9 4841 4842 4883 4882 4723 + 9 4842 4843 4884 4883 4724 + 9 4843 4844 4885 4884 4725 + 9 4844 4845 4886 4885 4726 + 9 4845 4846 4887 4886 4727 + 9 4846 4847 4888 4887 4728 + 9 4847 4848 4889 4888 4729 + 9 4848 4849 4890 4889 4730 + 9 4849 4850 4891 4890 4731 + 9 4850 4851 4892 4891 4732 + 9 4851 4852 4893 4892 4733 + 9 4852 4853 4894 4893 4734 + 9 4853 4854 4895 4894 4735 + 9 4854 4855 4896 4895 4736 + 9 4855 4856 4897 4896 4737 + 9 4856 4857 4898 4897 4738 + 9 4857 4858 4899 4898 4739 + 9 4858 4859 4900 4899 4740 + 9 4859 4860 4901 4900 4741 + 9 4860 4861 4902 4901 4742 + 9 4861 4862 4903 4902 4743 + 9 4862 4863 4904 4903 4744 + 9 4863 4864 4905 4904 4745 + 9 4864 4865 4906 4905 4746 + 9 4865 4866 4907 4906 4747 + 9 4866 4867 4908 4907 4748 + 9 4867 4868 4909 4908 4749 + 9 4868 4869 4910 4909 4750 + 9 4869 4870 4911 4910 4751 + 9 4870 4871 4912 4911 4752 + 9 4871 4872 4913 4912 4753 + 9 4872 4873 4914 4913 4754 + 9 4873 4874 4915 4914 4755 + 9 4874 4875 4916 4915 4756 + 9 4875 4876 4917 4916 4757 + 9 4876 4877 4918 4917 4758 + 9 4877 4878 4919 4918 4759 + 9 4879 4880 4921 4920 4760 + 9 4880 4881 4922 4921 4761 + 9 4881 4882 4923 4922 4762 + 9 4882 4883 4924 4923 4763 + 9 4883 4884 4925 4924 4764 + 9 4884 4885 4926 4925 4765 + 9 4885 4886 4927 4926 4766 + 9 4886 4887 4928 4927 4767 + 9 4887 4888 4929 4928 4768 + 9 4888 4889 4930 4929 4769 + 9 4889 4890 4931 4930 4770 + 9 4890 4891 4932 4931 4771 + 9 4891 4892 4933 4932 4772 + 9 4892 4893 4934 4933 4773 + 9 4893 4894 4935 4934 4774 + 9 4894 4895 4936 4935 4775 + 9 4895 4896 4937 4936 4776 + 9 4896 4897 4938 4937 4777 + 9 4897 4898 4939 4938 4778 + 9 4898 4899 4940 4939 4779 + 9 4899 4900 4941 4940 4780 + 9 4900 4901 4942 4941 4781 + 9 4901 4902 4943 4942 4782 + 9 4902 4903 4944 4943 4783 + 9 4903 4904 4945 4944 4784 + 9 4904 4905 4946 4945 4785 + 9 4905 4906 4947 4946 4786 + 9 4906 4907 4948 4947 4787 + 9 4907 4908 4949 4948 4788 + 9 4908 4909 4950 4949 4789 + 9 4909 4910 4951 4950 4790 + 9 4910 4911 4952 4951 4791 + 9 4911 4912 4953 4952 4792 + 9 4912 4913 4954 4953 4793 + 9 4913 4914 4955 4954 4794 + 9 4914 4915 4956 4955 4795 + 9 4915 4916 4957 4956 4796 + 9 4916 4917 4958 4957 4797 + 9 4917 4918 4959 4958 4798 + 9 4918 4919 4960 4959 4799 + 9 4920 4921 4962 4961 4800 + 9 4921 4922 4963 4962 4801 + 9 4922 4923 4964 4963 4802 + 9 4923 4924 4965 4964 4803 + 9 4924 4925 4966 4965 4804 + 9 4925 4926 4967 4966 4805 + 9 4926 4927 4968 4967 4806 + 9 4927 4928 4969 4968 4807 + 9 4928 4929 4970 4969 4808 + 9 4929 4930 4971 4970 4809 + 9 4930 4931 4972 4971 4810 + 9 4931 4932 4973 4972 4811 + 9 4932 4933 4974 4973 4812 + 9 4933 4934 4975 4974 4813 + 9 4934 4935 4976 4975 4814 + 9 4935 4936 4977 4976 4815 + 9 4936 4937 4978 4977 4816 + 9 4937 4938 4979 4978 4817 + 9 4938 4939 4980 4979 4818 + 9 4939 4940 4981 4980 4819 + 9 4940 4941 4982 4981 4820 + 9 4941 4942 4983 4982 4821 + 9 4942 4943 4984 4983 4822 + 9 4943 4944 4985 4984 4823 + 9 4944 4945 4986 4985 4824 + 9 4945 4946 4987 4986 4825 + 9 4946 4947 4988 4987 4826 + 9 4947 4948 4989 4988 4827 + 9 4948 4949 4990 4989 4828 + 9 4949 4950 4991 4990 4829 + 9 4950 4951 4992 4991 4830 + 9 4951 4952 4993 4992 4831 + 9 4952 4953 4994 4993 4832 + 9 4953 4954 4995 4994 4833 + 9 4954 4955 4996 4995 4834 + 9 4955 4956 4997 4996 4835 + 9 4956 4957 4998 4997 4836 + 9 4957 4958 4999 4998 4837 + 9 4958 4959 5000 4999 4838 + 9 4959 4960 5001 5000 4839 + 9 4961 4962 5003 5002 4840 + 9 4962 4963 5004 5003 4841 + 9 4963 4964 5005 5004 4842 + 9 4964 4965 5006 5005 4843 + 9 4965 4966 5007 5006 4844 + 9 4966 4967 5008 5007 4845 + 9 4967 4968 5009 5008 4846 + 9 4968 4969 5010 5009 4847 + 9 4969 4970 5011 5010 4848 + 9 4970 4971 5012 5011 4849 + 9 4971 4972 5013 5012 4850 + 9 4972 4973 5014 5013 4851 + 9 4973 4974 5015 5014 4852 + 9 4974 4975 5016 5015 4853 + 9 4975 4976 5017 5016 4854 + 9 4976 4977 5018 5017 4855 + 9 4977 4978 5019 5018 4856 + 9 4978 4979 5020 5019 4857 + 9 4979 4980 5021 5020 4858 + 9 4980 4981 5022 5021 4859 + 9 4981 4982 5023 5022 4860 + 9 4982 4983 5024 5023 4861 + 9 4983 4984 5025 5024 4862 + 9 4984 4985 5026 5025 4863 + 9 4985 4986 5027 5026 4864 + 9 4986 4987 5028 5027 4865 + 9 4987 4988 5029 5028 4866 + 9 4988 4989 5030 5029 4867 + 9 4989 4990 5031 5030 4868 + 9 4990 4991 5032 5031 4869 + 9 4991 4992 5033 5032 4870 + 9 4992 4993 5034 5033 4871 + 9 4993 4994 5035 5034 4872 + 9 4994 4995 5036 5035 4873 + 9 4995 4996 5037 5036 4874 + 9 4996 4997 5038 5037 4875 + 9 4997 4998 5039 5038 4876 + 9 4998 4999 5040 5039 4877 + 9 4999 5000 5041 5040 4878 + 9 5000 5001 5042 5041 4879 + 9 5002 5003 5044 5043 4880 + 9 5003 5004 5045 5044 4881 + 9 5004 5005 5046 5045 4882 + 9 5005 5006 5047 5046 4883 + 9 5006 5007 5048 5047 4884 + 9 5007 5008 5049 5048 4885 + 9 5008 5009 5050 5049 4886 + 9 5009 5010 5051 5050 4887 + 9 5010 5011 5052 5051 4888 + 9 5011 5012 5053 5052 4889 + 9 5012 5013 5054 5053 4890 + 9 5013 5014 5055 5054 4891 + 9 5014 5015 5056 5055 4892 + 9 5015 5016 5057 5056 4893 + 9 5016 5017 5058 5057 4894 + 9 5017 5018 5059 5058 4895 + 9 5018 5019 5060 5059 4896 + 9 5019 5020 5061 5060 4897 + 9 5020 5021 5062 5061 4898 + 9 5021 5022 5063 5062 4899 + 9 5022 5023 5064 5063 4900 + 9 5023 5024 5065 5064 4901 + 9 5024 5025 5066 5065 4902 + 9 5025 5026 5067 5066 4903 + 9 5026 5027 5068 5067 4904 + 9 5027 5028 5069 5068 4905 + 9 5028 5029 5070 5069 4906 + 9 5029 5030 5071 5070 4907 + 9 5030 5031 5072 5071 4908 + 9 5031 5032 5073 5072 4909 + 9 5032 5033 5074 5073 4910 + 9 5033 5034 5075 5074 4911 + 9 5034 5035 5076 5075 4912 + 9 5035 5036 5077 5076 4913 + 9 5036 5037 5078 5077 4914 + 9 5037 5038 5079 5078 4915 + 9 5038 5039 5080 5079 4916 + 9 5039 5040 5081 5080 4917 + 9 5040 5041 5082 5081 4918 + 9 5041 5042 5083 5082 4919 + 9 5043 5044 5085 5084 4920 + 9 5044 5045 5086 5085 4921 + 9 5045 5046 5087 5086 4922 + 9 5046 5047 5088 5087 4923 + 9 5047 5048 5089 5088 4924 + 9 5048 5049 5090 5089 4925 + 9 5049 5050 5091 5090 4926 + 9 5050 5051 5092 5091 4927 + 9 5051 5052 5093 5092 4928 + 9 5052 5053 5094 5093 4929 + 9 5053 5054 5095 5094 4930 + 9 5054 5055 5096 5095 4931 + 9 5055 5056 5097 5096 4932 + 9 5056 5057 5098 5097 4933 + 9 5057 5058 5099 5098 4934 + 9 5058 5059 5100 5099 4935 + 9 5059 5060 5101 5100 4936 + 9 5060 5061 5102 5101 4937 + 9 5061 5062 5103 5102 4938 + 9 5062 5063 5104 5103 4939 + 9 5063 5064 5105 5104 4940 + 9 5064 5065 5106 5105 4941 + 9 5065 5066 5107 5106 4942 + 9 5066 5067 5108 5107 4943 + 9 5067 5068 5109 5108 4944 + 9 5068 5069 5110 5109 4945 + 9 5069 5070 5111 5110 4946 + 9 5070 5071 5112 5111 4947 + 9 5071 5072 5113 5112 4948 + 9 5072 5073 5114 5113 4949 + 9 5073 5074 5115 5114 4950 + 9 5074 5075 5116 5115 4951 + 9 5075 5076 5117 5116 4952 + 9 5076 5077 5118 5117 4953 + 9 5077 5078 5119 5118 4954 + 9 5078 5079 5120 5119 4955 + 9 5079 5080 5121 5120 4956 + 9 5080 5081 5122 5121 4957 + 9 5081 5082 5123 5122 4958 + 9 5082 5083 5124 5123 4959 + 9 5084 5085 5126 5125 4960 + 9 5085 5086 5127 5126 4961 + 9 5086 5087 5128 5127 4962 + 9 5087 5088 5129 5128 4963 + 9 5088 5089 5130 5129 4964 + 9 5089 5090 5131 5130 4965 + 9 5090 5091 5132 5131 4966 + 9 5091 5092 5133 5132 4967 + 9 5092 5093 5134 5133 4968 + 9 5093 5094 5135 5134 4969 + 9 5094 5095 5136 5135 4970 + 9 5095 5096 5137 5136 4971 + 9 5096 5097 5138 5137 4972 + 9 5097 5098 5139 5138 4973 + 9 5098 5099 5140 5139 4974 + 9 5099 5100 5141 5140 4975 + 9 5100 5101 5142 5141 4976 + 9 5101 5102 5143 5142 4977 + 9 5102 5103 5144 5143 4978 + 9 5103 5104 5145 5144 4979 + 9 5104 5105 5146 5145 4980 + 9 5105 5106 5147 5146 4981 + 9 5106 5107 5148 5147 4982 + 9 5107 5108 5149 5148 4983 + 9 5108 5109 5150 5149 4984 + 9 5109 5110 5151 5150 4985 + 9 5110 5111 5152 5151 4986 + 9 5111 5112 5153 5152 4987 + 9 5112 5113 5154 5153 4988 + 9 5113 5114 5155 5154 4989 + 9 5114 5115 5156 5155 4990 + 9 5115 5116 5157 5156 4991 + 9 5116 5117 5158 5157 4992 + 9 5117 5118 5159 5158 4993 + 9 5118 5119 5160 5159 4994 + 9 5119 5120 5161 5160 4995 + 9 5120 5121 5162 5161 4996 + 9 5121 5122 5163 5162 4997 + 9 5122 5123 5164 5163 4998 + 9 5123 5124 5165 5164 4999 + 9 5125 5126 5167 5166 5000 + 9 5126 5127 5168 5167 5001 + 9 5127 5128 5169 5168 5002 + 9 5128 5129 5170 5169 5003 + 9 5129 5130 5171 5170 5004 + 9 5130 5131 5172 5171 5005 + 9 5131 5132 5173 5172 5006 + 9 5132 5133 5174 5173 5007 + 9 5133 5134 5175 5174 5008 + 9 5134 5135 5176 5175 5009 + 9 5135 5136 5177 5176 5010 + 9 5136 5137 5178 5177 5011 + 9 5137 5138 5179 5178 5012 + 9 5138 5139 5180 5179 5013 + 9 5139 5140 5181 5180 5014 + 9 5140 5141 5182 5181 5015 + 9 5141 5142 5183 5182 5016 + 9 5142 5143 5184 5183 5017 + 9 5143 5144 5185 5184 5018 + 9 5144 5145 5186 5185 5019 + 9 5145 5146 5187 5186 5020 + 9 5146 5147 5188 5187 5021 + 9 5147 5148 5189 5188 5022 + 9 5148 5149 5190 5189 5023 + 9 5149 5150 5191 5190 5024 + 9 5150 5151 5192 5191 5025 + 9 5151 5152 5193 5192 5026 + 9 5152 5153 5194 5193 5027 + 9 5153 5154 5195 5194 5028 + 9 5154 5155 5196 5195 5029 + 9 5155 5156 5197 5196 5030 + 9 5156 5157 5198 5197 5031 + 9 5157 5158 5199 5198 5032 + 9 5158 5159 5200 5199 5033 + 9 5159 5160 5201 5200 5034 + 9 5160 5161 5202 5201 5035 + 9 5161 5162 5203 5202 5036 + 9 5162 5163 5204 5203 5037 + 9 5163 5164 5205 5204 5038 + 9 5164 5165 5206 5205 5039 + 9 5166 5167 5208 5207 5040 + 9 5167 5168 5209 5208 5041 + 9 5168 5169 5210 5209 5042 + 9 5169 5170 5211 5210 5043 + 9 5170 5171 5212 5211 5044 + 9 5171 5172 5213 5212 5045 + 9 5172 5173 5214 5213 5046 + 9 5173 5174 5215 5214 5047 + 9 5174 5175 5216 5215 5048 + 9 5175 5176 5217 5216 5049 + 9 5176 5177 5218 5217 5050 + 9 5177 5178 5219 5218 5051 + 9 5178 5179 5220 5219 5052 + 9 5179 5180 5221 5220 5053 + 9 5180 5181 5222 5221 5054 + 9 5181 5182 5223 5222 5055 + 9 5182 5183 5224 5223 5056 + 9 5183 5184 5225 5224 5057 + 9 5184 5185 5226 5225 5058 + 9 5185 5186 5227 5226 5059 + 9 5186 5187 5228 5227 5060 + 9 5187 5188 5229 5228 5061 + 9 5188 5189 5230 5229 5062 + 9 5189 5190 5231 5230 5063 + 9 5190 5191 5232 5231 5064 + 9 5191 5192 5233 5232 5065 + 9 5192 5193 5234 5233 5066 + 9 5193 5194 5235 5234 5067 + 9 5194 5195 5236 5235 5068 + 9 5195 5196 5237 5236 5069 + 9 5196 5197 5238 5237 5070 + 9 5197 5198 5239 5238 5071 + 9 5198 5199 5240 5239 5072 + 9 5199 5200 5241 5240 5073 + 9 5200 5201 5242 5241 5074 + 9 5201 5202 5243 5242 5075 + 9 5202 5203 5244 5243 5076 + 9 5203 5204 5245 5244 5077 + 9 5204 5205 5246 5245 5078 + 9 5205 5206 5247 5246 5079 + 9 5207 5208 5249 5248 5080 + 9 5208 5209 5250 5249 5081 + 9 5209 5210 5251 5250 5082 + 9 5210 5211 5252 5251 5083 + 9 5211 5212 5253 5252 5084 + 9 5212 5213 5254 5253 5085 + 9 5213 5214 5255 5254 5086 + 9 5214 5215 5256 5255 5087 + 9 5215 5216 5257 5256 5088 + 9 5216 5217 5258 5257 5089 + 9 5217 5218 5259 5258 5090 + 9 5218 5219 5260 5259 5091 + 9 5219 5220 5261 5260 5092 + 9 5220 5221 5262 5261 5093 + 9 5221 5222 5263 5262 5094 + 9 5222 5223 5264 5263 5095 + 9 5223 5224 5265 5264 5096 + 9 5224 5225 5266 5265 5097 + 9 5225 5226 5267 5266 5098 + 9 5226 5227 5268 5267 5099 + 9 5227 5228 5269 5268 5100 + 9 5228 5229 5270 5269 5101 + 9 5229 5230 5271 5270 5102 + 9 5230 5231 5272 5271 5103 + 9 5231 5232 5273 5272 5104 + 9 5232 5233 5274 5273 5105 + 9 5233 5234 5275 5274 5106 + 9 5234 5235 5276 5275 5107 + 9 5235 5236 5277 5276 5108 + 9 5236 5237 5278 5277 5109 + 9 5237 5238 5279 5278 5110 + 9 5238 5239 5280 5279 5111 + 9 5239 5240 5281 5280 5112 + 9 5240 5241 5282 5281 5113 + 9 5241 5242 5283 5282 5114 + 9 5242 5243 5284 5283 5115 + 9 5243 5244 5285 5284 5116 + 9 5244 5245 5286 5285 5117 + 9 5245 5246 5287 5286 5118 + 9 5246 5247 5288 5287 5119 + 9 5248 5249 5290 5289 5120 + 9 5249 5250 5291 5290 5121 + 9 5250 5251 5292 5291 5122 + 9 5251 5252 5293 5292 5123 + 9 5252 5253 5294 5293 5124 + 9 5253 5254 5295 5294 5125 + 9 5254 5255 5296 5295 5126 + 9 5255 5256 5297 5296 5127 + 9 5256 5257 5298 5297 5128 + 9 5257 5258 5299 5298 5129 + 9 5258 5259 5300 5299 5130 + 9 5259 5260 5301 5300 5131 + 9 5260 5261 5302 5301 5132 + 9 5261 5262 5303 5302 5133 + 9 5262 5263 5304 5303 5134 + 9 5263 5264 5305 5304 5135 + 9 5264 5265 5306 5305 5136 + 9 5265 5266 5307 5306 5137 + 9 5266 5267 5308 5307 5138 + 9 5267 5268 5309 5308 5139 + 9 5268 5269 5310 5309 5140 + 9 5269 5270 5311 5310 5141 + 9 5270 5271 5312 5311 5142 + 9 5271 5272 5313 5312 5143 + 9 5272 5273 5314 5313 5144 + 9 5273 5274 5315 5314 5145 + 9 5274 5275 5316 5315 5146 + 9 5275 5276 5317 5316 5147 + 9 5276 5277 5318 5317 5148 + 9 5277 5278 5319 5318 5149 + 9 5278 5279 5320 5319 5150 + 9 5279 5280 5321 5320 5151 + 9 5280 5281 5322 5321 5152 + 9 5281 5282 5323 5322 5153 + 9 5282 5283 5324 5323 5154 + 9 5283 5284 5325 5324 5155 + 9 5284 5285 5326 5325 5156 + 9 5285 5286 5327 5326 5157 + 9 5286 5287 5328 5327 5158 + 9 5287 5288 5329 5328 5159 + 9 5289 5290 5331 5330 5160 + 9 5290 5291 5332 5331 5161 + 9 5291 5292 5333 5332 5162 + 9 5292 5293 5334 5333 5163 + 9 5293 5294 5335 5334 5164 + 9 5294 5295 5336 5335 5165 + 9 5295 5296 5337 5336 5166 + 9 5296 5297 5338 5337 5167 + 9 5297 5298 5339 5338 5168 + 9 5298 5299 5340 5339 5169 + 9 5299 5300 5341 5340 5170 + 9 5300 5301 5342 5341 5171 + 9 5301 5302 5343 5342 5172 + 9 5302 5303 5344 5343 5173 + 9 5303 5304 5345 5344 5174 + 9 5304 5305 5346 5345 5175 + 9 5305 5306 5347 5346 5176 + 9 5306 5307 5348 5347 5177 + 9 5307 5308 5349 5348 5178 + 9 5308 5309 5350 5349 5179 + 9 5309 5310 5351 5350 5180 + 9 5310 5311 5352 5351 5181 + 9 5311 5312 5353 5352 5182 + 9 5312 5313 5354 5353 5183 + 9 5313 5314 5355 5354 5184 + 9 5314 5315 5356 5355 5185 + 9 5315 5316 5357 5356 5186 + 9 5316 5317 5358 5357 5187 + 9 5317 5318 5359 5358 5188 + 9 5318 5319 5360 5359 5189 + 9 5319 5320 5361 5360 5190 + 9 5320 5321 5362 5361 5191 + 9 5321 5322 5363 5362 5192 + 9 5322 5323 5364 5363 5193 + 9 5323 5324 5365 5364 5194 + 9 5324 5325 5366 5365 5195 + 9 5325 5326 5367 5366 5196 + 9 5326 5327 5368 5367 5197 + 9 5327 5328 5369 5368 5198 + 9 5328 5329 5370 5369 5199 + 9 5330 5331 5372 5371 5200 + 9 5331 5332 5373 5372 5201 + 9 5332 5333 5374 5373 5202 + 9 5333 5334 5375 5374 5203 + 9 5334 5335 5376 5375 5204 + 9 5335 5336 5377 5376 5205 + 9 5336 5337 5378 5377 5206 + 9 5337 5338 5379 5378 5207 + 9 5338 5339 5380 5379 5208 + 9 5339 5340 5381 5380 5209 + 9 5340 5341 5382 5381 5210 + 9 5341 5342 5383 5382 5211 + 9 5342 5343 5384 5383 5212 + 9 5343 5344 5385 5384 5213 + 9 5344 5345 5386 5385 5214 + 9 5345 5346 5387 5386 5215 + 9 5346 5347 5388 5387 5216 + 9 5347 5348 5389 5388 5217 + 9 5348 5349 5390 5389 5218 + 9 5349 5350 5391 5390 5219 + 9 5350 5351 5392 5391 5220 + 9 5351 5352 5393 5392 5221 + 9 5352 5353 5394 5393 5222 + 9 5353 5354 5395 5394 5223 + 9 5354 5355 5396 5395 5224 + 9 5355 5356 5397 5396 5225 + 9 5356 5357 5398 5397 5226 + 9 5357 5358 5399 5398 5227 + 9 5358 5359 5400 5399 5228 + 9 5359 5360 5401 5400 5229 + 9 5360 5361 5402 5401 5230 + 9 5361 5362 5403 5402 5231 + 9 5362 5363 5404 5403 5232 + 9 5363 5364 5405 5404 5233 + 9 5364 5365 5406 5405 5234 + 9 5365 5366 5407 5406 5235 + 9 5366 5367 5408 5407 5236 + 9 5367 5368 5409 5408 5237 + 9 5368 5369 5410 5409 5238 + 9 5369 5370 5411 5410 5239 + 9 5371 5372 5413 5412 5240 + 9 5372 5373 5414 5413 5241 + 9 5373 5374 5415 5414 5242 + 9 5374 5375 5416 5415 5243 + 9 5375 5376 5417 5416 5244 + 9 5376 5377 5418 5417 5245 + 9 5377 5378 5419 5418 5246 + 9 5378 5379 5420 5419 5247 + 9 5379 5380 5421 5420 5248 + 9 5380 5381 5422 5421 5249 + 9 5381 5382 5423 5422 5250 + 9 5382 5383 5424 5423 5251 + 9 5383 5384 5425 5424 5252 + 9 5384 5385 5426 5425 5253 + 9 5385 5386 5427 5426 5254 + 9 5386 5387 5428 5427 5255 + 9 5387 5388 5429 5428 5256 + 9 5388 5389 5430 5429 5257 + 9 5389 5390 5431 5430 5258 + 9 5390 5391 5432 5431 5259 + 9 5391 5392 5433 5432 5260 + 9 5392 5393 5434 5433 5261 + 9 5393 5394 5435 5434 5262 + 9 5394 5395 5436 5435 5263 + 9 5395 5396 5437 5436 5264 + 9 5396 5397 5438 5437 5265 + 9 5397 5398 5439 5438 5266 + 9 5398 5399 5440 5439 5267 + 9 5399 5400 5441 5440 5268 + 9 5400 5401 5442 5441 5269 + 9 5401 5402 5443 5442 5270 + 9 5402 5403 5444 5443 5271 + 9 5403 5404 5445 5444 5272 + 9 5404 5405 5446 5445 5273 + 9 5405 5406 5447 5446 5274 + 9 5406 5407 5448 5447 5275 + 9 5407 5408 5449 5448 5276 + 9 5408 5409 5450 5449 5277 + 9 5409 5410 5451 5450 5278 + 9 5410 5411 5452 5451 5279 + 9 5412 5413 5454 5453 5280 + 9 5413 5414 5455 5454 5281 + 9 5414 5415 5456 5455 5282 + 9 5415 5416 5457 5456 5283 + 9 5416 5417 5458 5457 5284 + 9 5417 5418 5459 5458 5285 + 9 5418 5419 5460 5459 5286 + 9 5419 5420 5461 5460 5287 + 9 5420 5421 5462 5461 5288 + 9 5421 5422 5463 5462 5289 + 9 5422 5423 5464 5463 5290 + 9 5423 5424 5465 5464 5291 + 9 5424 5425 5466 5465 5292 + 9 5425 5426 5467 5466 5293 + 9 5426 5427 5468 5467 5294 + 9 5427 5428 5469 5468 5295 + 9 5428 5429 5470 5469 5296 + 9 5429 5430 5471 5470 5297 + 9 5430 5431 5472 5471 5298 + 9 5431 5432 5473 5472 5299 + 9 5432 5433 5474 5473 5300 + 9 5433 5434 5475 5474 5301 + 9 5434 5435 5476 5475 5302 + 9 5435 5436 5477 5476 5303 + 9 5436 5437 5478 5477 5304 + 9 5437 5438 5479 5478 5305 + 9 5438 5439 5480 5479 5306 + 9 5439 5440 5481 5480 5307 + 9 5440 5441 5482 5481 5308 + 9 5441 5442 5483 5482 5309 + 9 5442 5443 5484 5483 5310 + 9 5443 5444 5485 5484 5311 + 9 5444 5445 5486 5485 5312 + 9 5445 5446 5487 5486 5313 + 9 5446 5447 5488 5487 5314 + 9 5447 5448 5489 5488 5315 + 9 5448 5449 5490 5489 5316 + 9 5449 5450 5491 5490 5317 + 9 5450 5451 5492 5491 5318 + 9 5451 5452 5493 5492 5319 + 9 5453 5454 5495 5494 5320 + 9 5454 5455 5496 5495 5321 + 9 5455 5456 5497 5496 5322 + 9 5456 5457 5498 5497 5323 + 9 5457 5458 5499 5498 5324 + 9 5458 5459 5500 5499 5325 + 9 5459 5460 5501 5500 5326 + 9 5460 5461 5502 5501 5327 + 9 5461 5462 5503 5502 5328 + 9 5462 5463 5504 5503 5329 + 9 5463 5464 5505 5504 5330 + 9 5464 5465 5506 5505 5331 + 9 5465 5466 5507 5506 5332 + 9 5466 5467 5508 5507 5333 + 9 5467 5468 5509 5508 5334 + 9 5468 5469 5510 5509 5335 + 9 5469 5470 5511 5510 5336 + 9 5470 5471 5512 5511 5337 + 9 5471 5472 5513 5512 5338 + 9 5472 5473 5514 5513 5339 + 9 5473 5474 5515 5514 5340 + 9 5474 5475 5516 5515 5341 + 9 5475 5476 5517 5516 5342 + 9 5476 5477 5518 5517 5343 + 9 5477 5478 5519 5518 5344 + 9 5478 5479 5520 5519 5345 + 9 5479 5480 5521 5520 5346 + 9 5480 5481 5522 5521 5347 + 9 5481 5482 5523 5522 5348 + 9 5482 5483 5524 5523 5349 + 9 5483 5484 5525 5524 5350 + 9 5484 5485 5526 5525 5351 + 9 5485 5486 5527 5526 5352 + 9 5486 5487 5528 5527 5353 + 9 5487 5488 5529 5528 5354 + 9 5488 5489 5530 5529 5355 + 9 5489 5490 5531 5530 5356 + 9 5490 5491 5532 5531 5357 + 9 5491 5492 5533 5532 5358 + 9 5492 5493 5534 5533 5359 + 9 5494 5495 5536 5535 5360 + 9 5495 5496 5537 5536 5361 + 9 5496 5497 5538 5537 5362 + 9 5497 5498 5539 5538 5363 + 9 5498 5499 5540 5539 5364 + 9 5499 5500 5541 5540 5365 + 9 5500 5501 5542 5541 5366 + 9 5501 5502 5543 5542 5367 + 9 5502 5503 5544 5543 5368 + 9 5503 5504 5545 5544 5369 + 9 5504 5505 5546 5545 5370 + 9 5505 5506 5547 5546 5371 + 9 5506 5507 5548 5547 5372 + 9 5507 5508 5549 5548 5373 + 9 5508 5509 5550 5549 5374 + 9 5509 5510 5551 5550 5375 + 9 5510 5511 5552 5551 5376 + 9 5511 5512 5553 5552 5377 + 9 5512 5513 5554 5553 5378 + 9 5513 5514 5555 5554 5379 + 9 5514 5515 5556 5555 5380 + 9 5515 5516 5557 5556 5381 + 9 5516 5517 5558 5557 5382 + 9 5517 5518 5559 5558 5383 + 9 5518 5519 5560 5559 5384 + 9 5519 5520 5561 5560 5385 + 9 5520 5521 5562 5561 5386 + 9 5521 5522 5563 5562 5387 + 9 5522 5523 5564 5563 5388 + 9 5523 5524 5565 5564 5389 + 9 5524 5525 5566 5565 5390 + 9 5525 5526 5567 5566 5391 + 9 5526 5527 5568 5567 5392 + 9 5527 5528 5569 5568 5393 + 9 5528 5529 5570 5569 5394 + 9 5529 5530 5571 5570 5395 + 9 5530 5531 5572 5571 5396 + 9 5531 5532 5573 5572 5397 + 9 5532 5533 5574 5573 5398 + 9 5533 5534 5575 5574 5399 + 9 5535 5536 5577 5576 5400 + 9 5536 5537 5578 5577 5401 + 9 5537 5538 5579 5578 5402 + 9 5538 5539 5580 5579 5403 + 9 5539 5540 5581 5580 5404 + 9 5540 5541 5582 5581 5405 + 9 5541 5542 5583 5582 5406 + 9 5542 5543 5584 5583 5407 + 9 5543 5544 5585 5584 5408 + 9 5544 5545 5586 5585 5409 + 9 5545 5546 5587 5586 5410 + 9 5546 5547 5588 5587 5411 + 9 5547 5548 5589 5588 5412 + 9 5548 5549 5590 5589 5413 + 9 5549 5550 5591 5590 5414 + 9 5550 5551 5592 5591 5415 + 9 5551 5552 5593 5592 5416 + 9 5552 5553 5594 5593 5417 + 9 5553 5554 5595 5594 5418 + 9 5554 5555 5596 5595 5419 + 9 5555 5556 5597 5596 5420 + 9 5556 5557 5598 5597 5421 + 9 5557 5558 5599 5598 5422 + 9 5558 5559 5600 5599 5423 + 9 5559 5560 5601 5600 5424 + 9 5560 5561 5602 5601 5425 + 9 5561 5562 5603 5602 5426 + 9 5562 5563 5604 5603 5427 + 9 5563 5564 5605 5604 5428 + 9 5564 5565 5606 5605 5429 + 9 5565 5566 5607 5606 5430 + 9 5566 5567 5608 5607 5431 + 9 5567 5568 5609 5608 5432 + 9 5568 5569 5610 5609 5433 + 9 5569 5570 5611 5610 5434 + 9 5570 5571 5612 5611 5435 + 9 5571 5572 5613 5612 5436 + 9 5572 5573 5614 5613 5437 + 9 5573 5574 5615 5614 5438 + 9 5574 5575 5616 5615 5439 + 9 5576 5577 5618 5617 5440 + 9 5577 5578 5619 5618 5441 + 9 5578 5579 5620 5619 5442 + 9 5579 5580 5621 5620 5443 + 9 5580 5581 5622 5621 5444 + 9 5581 5582 5623 5622 5445 + 9 5582 5583 5624 5623 5446 + 9 5583 5584 5625 5624 5447 + 9 5584 5585 5626 5625 5448 + 9 5585 5586 5627 5626 5449 + 9 5586 5587 5628 5627 5450 + 9 5587 5588 5629 5628 5451 + 9 5588 5589 5630 5629 5452 + 9 5589 5590 5631 5630 5453 + 9 5590 5591 5632 5631 5454 + 9 5591 5592 5633 5632 5455 + 9 5592 5593 5634 5633 5456 + 9 5593 5594 5635 5634 5457 + 9 5594 5595 5636 5635 5458 + 9 5595 5596 5637 5636 5459 + 9 5596 5597 5638 5637 5460 + 9 5597 5598 5639 5638 5461 + 9 5598 5599 5640 5639 5462 + 9 5599 5600 5641 5640 5463 + 9 5600 5601 5642 5641 5464 + 9 5601 5602 5643 5642 5465 + 9 5602 5603 5644 5643 5466 + 9 5603 5604 5645 5644 5467 + 9 5604 5605 5646 5645 5468 + 9 5605 5606 5647 5646 5469 + 9 5606 5607 5648 5647 5470 + 9 5607 5608 5649 5648 5471 + 9 5608 5609 5650 5649 5472 + 9 5609 5610 5651 5650 5473 + 9 5610 5611 5652 5651 5474 + 9 5611 5612 5653 5652 5475 + 9 5612 5613 5654 5653 5476 + 9 5613 5614 5655 5654 5477 + 9 5614 5615 5656 5655 5478 + 9 5615 5616 5657 5656 5479 + 9 5617 5618 5659 5658 5480 + 9 5618 5619 5660 5659 5481 + 9 5619 5620 5661 5660 5482 + 9 5620 5621 5662 5661 5483 + 9 5621 5622 5663 5662 5484 + 9 5622 5623 5664 5663 5485 + 9 5623 5624 5665 5664 5486 + 9 5624 5625 5666 5665 5487 + 9 5625 5626 5667 5666 5488 + 9 5626 5627 5668 5667 5489 + 9 5627 5628 5669 5668 5490 + 9 5628 5629 5670 5669 5491 + 9 5629 5630 5671 5670 5492 + 9 5630 5631 5672 5671 5493 + 9 5631 5632 5673 5672 5494 + 9 5632 5633 5674 5673 5495 + 9 5633 5634 5675 5674 5496 + 9 5634 5635 5676 5675 5497 + 9 5635 5636 5677 5676 5498 + 9 5636 5637 5678 5677 5499 + 9 5637 5638 5679 5678 5500 + 9 5638 5639 5680 5679 5501 + 9 5639 5640 5681 5680 5502 + 9 5640 5641 5682 5681 5503 + 9 5641 5642 5683 5682 5504 + 9 5642 5643 5684 5683 5505 + 9 5643 5644 5685 5684 5506 + 9 5644 5645 5686 5685 5507 + 9 5645 5646 5687 5686 5508 + 9 5646 5647 5688 5687 5509 + 9 5647 5648 5689 5688 5510 + 9 5648 5649 5690 5689 5511 + 9 5649 5650 5691 5690 5512 + 9 5650 5651 5692 5691 5513 + 9 5651 5652 5693 5692 5514 + 9 5652 5653 5694 5693 5515 + 9 5653 5654 5695 5694 5516 + 9 5654 5655 5696 5695 5517 + 9 5655 5656 5697 5696 5518 + 9 5656 5657 5698 5697 5519 + 9 5658 5659 5700 5699 5520 + 9 5659 5660 5701 5700 5521 + 9 5660 5661 5702 5701 5522 + 9 5661 5662 5703 5702 5523 + 9 5662 5663 5704 5703 5524 + 9 5663 5664 5705 5704 5525 + 9 5664 5665 5706 5705 5526 + 9 5665 5666 5707 5706 5527 + 9 5666 5667 5708 5707 5528 + 9 5667 5668 5709 5708 5529 + 9 5668 5669 5710 5709 5530 + 9 5669 5670 5711 5710 5531 + 9 5670 5671 5712 5711 5532 + 9 5671 5672 5713 5712 5533 + 9 5672 5673 5714 5713 5534 + 9 5673 5674 5715 5714 5535 + 9 5674 5675 5716 5715 5536 + 9 5675 5676 5717 5716 5537 + 9 5676 5677 5718 5717 5538 + 9 5677 5678 5719 5718 5539 + 9 5678 5679 5720 5719 5540 + 9 5679 5680 5721 5720 5541 + 9 5680 5681 5722 5721 5542 + 9 5681 5682 5723 5722 5543 + 9 5682 5683 5724 5723 5544 + 9 5683 5684 5725 5724 5545 + 9 5684 5685 5726 5725 5546 + 9 5685 5686 5727 5726 5547 + 9 5686 5687 5728 5727 5548 + 9 5687 5688 5729 5728 5549 + 9 5688 5689 5730 5729 5550 + 9 5689 5690 5731 5730 5551 + 9 5690 5691 5732 5731 5552 + 9 5691 5692 5733 5732 5553 + 9 5692 5693 5734 5733 5554 + 9 5693 5694 5735 5734 5555 + 9 5694 5695 5736 5735 5556 + 9 5695 5696 5737 5736 5557 + 9 5696 5697 5738 5737 5558 + 9 5697 5698 5739 5738 5559 + 9 5699 5700 5741 5740 5560 + 9 5700 5701 5742 5741 5561 + 9 5701 5702 5743 5742 5562 + 9 5702 5703 5744 5743 5563 + 9 5703 5704 5745 5744 5564 + 9 5704 5705 5746 5745 5565 + 9 5705 5706 5747 5746 5566 + 9 5706 5707 5748 5747 5567 + 9 5707 5708 5749 5748 5568 + 9 5708 5709 5750 5749 5569 + 9 5709 5710 5751 5750 5570 + 9 5710 5711 5752 5751 5571 + 9 5711 5712 5753 5752 5572 + 9 5712 5713 5754 5753 5573 + 9 5713 5714 5755 5754 5574 + 9 5714 5715 5756 5755 5575 + 9 5715 5716 5757 5756 5576 + 9 5716 5717 5758 5757 5577 + 9 5717 5718 5759 5758 5578 + 9 5718 5719 5760 5759 5579 + 9 5719 5720 5761 5760 5580 + 9 5720 5721 5762 5761 5581 + 9 5721 5722 5763 5762 5582 + 9 5722 5723 5764 5763 5583 + 9 5723 5724 5765 5764 5584 + 9 5724 5725 5766 5765 5585 + 9 5725 5726 5767 5766 5586 + 9 5726 5727 5768 5767 5587 + 9 5727 5728 5769 5768 5588 + 9 5728 5729 5770 5769 5589 + 9 5729 5730 5771 5770 5590 + 9 5730 5731 5772 5771 5591 + 9 5731 5732 5773 5772 5592 + 9 5732 5733 5774 5773 5593 + 9 5733 5734 5775 5774 5594 + 9 5734 5735 5776 5775 5595 + 9 5735 5736 5777 5776 5596 + 9 5736 5737 5778 5777 5597 + 9 5737 5738 5779 5778 5598 + 9 5738 5739 5780 5779 5599 + 9 5740 5741 5782 5781 5600 + 9 5741 5742 5783 5782 5601 + 9 5742 5743 5784 5783 5602 + 9 5743 5744 5785 5784 5603 + 9 5744 5745 5786 5785 5604 + 9 5745 5746 5787 5786 5605 + 9 5746 5747 5788 5787 5606 + 9 5747 5748 5789 5788 5607 + 9 5748 5749 5790 5789 5608 + 9 5749 5750 5791 5790 5609 + 9 5750 5751 5792 5791 5610 + 9 5751 5752 5793 5792 5611 + 9 5752 5753 5794 5793 5612 + 9 5753 5754 5795 5794 5613 + 9 5754 5755 5796 5795 5614 + 9 5755 5756 5797 5796 5615 + 9 5756 5757 5798 5797 5616 + 9 5757 5758 5799 5798 5617 + 9 5758 5759 5800 5799 5618 + 9 5759 5760 5801 5800 5619 + 9 5760 5761 5802 5801 5620 + 9 5761 5762 5803 5802 5621 + 9 5762 5763 5804 5803 5622 + 9 5763 5764 5805 5804 5623 + 9 5764 5765 5806 5805 5624 + 9 5765 5766 5807 5806 5625 + 9 5766 5767 5808 5807 5626 + 9 5767 5768 5809 5808 5627 + 9 5768 5769 5810 5809 5628 + 9 5769 5770 5811 5810 5629 + 9 5770 5771 5812 5811 5630 + 9 5771 5772 5813 5812 5631 + 9 5772 5773 5814 5813 5632 + 9 5773 5774 5815 5814 5633 + 9 5774 5775 5816 5815 5634 + 9 5775 5776 5817 5816 5635 + 9 5776 5777 5818 5817 5636 + 9 5777 5778 5819 5818 5637 + 9 5778 5779 5820 5819 5638 + 9 5779 5780 5821 5820 5639 + 9 5781 5782 5823 5822 5640 + 9 5782 5783 5824 5823 5641 + 9 5783 5784 5825 5824 5642 + 9 5784 5785 5826 5825 5643 + 9 5785 5786 5827 5826 5644 + 9 5786 5787 5828 5827 5645 + 9 5787 5788 5829 5828 5646 + 9 5788 5789 5830 5829 5647 + 9 5789 5790 5831 5830 5648 + 9 5790 5791 5832 5831 5649 + 9 5791 5792 5833 5832 5650 + 9 5792 5793 5834 5833 5651 + 9 5793 5794 5835 5834 5652 + 9 5794 5795 5836 5835 5653 + 9 5795 5796 5837 5836 5654 + 9 5796 5797 5838 5837 5655 + 9 5797 5798 5839 5838 5656 + 9 5798 5799 5840 5839 5657 + 9 5799 5800 5841 5840 5658 + 9 5800 5801 5842 5841 5659 + 9 5801 5802 5843 5842 5660 + 9 5802 5803 5844 5843 5661 + 9 5803 5804 5845 5844 5662 + 9 5804 5805 5846 5845 5663 + 9 5805 5806 5847 5846 5664 + 9 5806 5807 5848 5847 5665 + 9 5807 5808 5849 5848 5666 + 9 5808 5809 5850 5849 5667 + 9 5809 5810 5851 5850 5668 + 9 5810 5811 5852 5851 5669 + 9 5811 5812 5853 5852 5670 + 9 5812 5813 5854 5853 5671 + 9 5813 5814 5855 5854 5672 + 9 5814 5815 5856 5855 5673 + 9 5815 5816 5857 5856 5674 + 9 5816 5817 5858 5857 5675 + 9 5817 5818 5859 5858 5676 + 9 5818 5819 5860 5859 5677 + 9 5819 5820 5861 5860 5678 + 9 5820 5821 5862 5861 5679 + 9 5822 5823 5864 5863 5680 + 9 5823 5824 5865 5864 5681 + 9 5824 5825 5866 5865 5682 + 9 5825 5826 5867 5866 5683 + 9 5826 5827 5868 5867 5684 + 9 5827 5828 5869 5868 5685 + 9 5828 5829 5870 5869 5686 + 9 5829 5830 5871 5870 5687 + 9 5830 5831 5872 5871 5688 + 9 5831 5832 5873 5872 5689 + 9 5832 5833 5874 5873 5690 + 9 5833 5834 5875 5874 5691 + 9 5834 5835 5876 5875 5692 + 9 5835 5836 5877 5876 5693 + 9 5836 5837 5878 5877 5694 + 9 5837 5838 5879 5878 5695 + 9 5838 5839 5880 5879 5696 + 9 5839 5840 5881 5880 5697 + 9 5840 5841 5882 5881 5698 + 9 5841 5842 5883 5882 5699 + 9 5842 5843 5884 5883 5700 + 9 5843 5844 5885 5884 5701 + 9 5844 5845 5886 5885 5702 + 9 5845 5846 5887 5886 5703 + 9 5846 5847 5888 5887 5704 + 9 5847 5848 5889 5888 5705 + 9 5848 5849 5890 5889 5706 + 9 5849 5850 5891 5890 5707 + 9 5850 5851 5892 5891 5708 + 9 5851 5852 5893 5892 5709 + 9 5852 5853 5894 5893 5710 + 9 5853 5854 5895 5894 5711 + 9 5854 5855 5896 5895 5712 + 9 5855 5856 5897 5896 5713 + 9 5856 5857 5898 5897 5714 + 9 5857 5858 5899 5898 5715 + 9 5858 5859 5900 5899 5716 + 9 5859 5860 5901 5900 5717 + 9 5860 5861 5902 5901 5718 + 9 5861 5862 5903 5902 5719 + 9 5863 5864 5905 5904 5720 + 9 5864 5865 5906 5905 5721 + 9 5865 5866 5907 5906 5722 + 9 5866 5867 5908 5907 5723 + 9 5867 5868 5909 5908 5724 + 9 5868 5869 5910 5909 5725 + 9 5869 5870 5911 5910 5726 + 9 5870 5871 5912 5911 5727 + 9 5871 5872 5913 5912 5728 + 9 5872 5873 5914 5913 5729 + 9 5873 5874 5915 5914 5730 + 9 5874 5875 5916 5915 5731 + 9 5875 5876 5917 5916 5732 + 9 5876 5877 5918 5917 5733 + 9 5877 5878 5919 5918 5734 + 9 5878 5879 5920 5919 5735 + 9 5879 5880 5921 5920 5736 + 9 5880 5881 5922 5921 5737 + 9 5881 5882 5923 5922 5738 + 9 5882 5883 5924 5923 5739 + 9 5883 5884 5925 5924 5740 + 9 5884 5885 5926 5925 5741 + 9 5885 5886 5927 5926 5742 + 9 5886 5887 5928 5927 5743 + 9 5887 5888 5929 5928 5744 + 9 5888 5889 5930 5929 5745 + 9 5889 5890 5931 5930 5746 + 9 5890 5891 5932 5931 5747 + 9 5891 5892 5933 5932 5748 + 9 5892 5893 5934 5933 5749 + 9 5893 5894 5935 5934 5750 + 9 5894 5895 5936 5935 5751 + 9 5895 5896 5937 5936 5752 + 9 5896 5897 5938 5937 5753 + 9 5897 5898 5939 5938 5754 + 9 5898 5899 5940 5939 5755 + 9 5899 5900 5941 5940 5756 + 9 5900 5901 5942 5941 5757 + 9 5901 5902 5943 5942 5758 + 9 5902 5903 5944 5943 5759 + 9 5904 5905 5946 5945 5760 + 9 5905 5906 5947 5946 5761 + 9 5906 5907 5948 5947 5762 + 9 5907 5908 5949 5948 5763 + 9 5908 5909 5950 5949 5764 + 9 5909 5910 5951 5950 5765 + 9 5910 5911 5952 5951 5766 + 9 5911 5912 5953 5952 5767 + 9 5912 5913 5954 5953 5768 + 9 5913 5914 5955 5954 5769 + 9 5914 5915 5956 5955 5770 + 9 5915 5916 5957 5956 5771 + 9 5916 5917 5958 5957 5772 + 9 5917 5918 5959 5958 5773 + 9 5918 5919 5960 5959 5774 + 9 5919 5920 5961 5960 5775 + 9 5920 5921 5962 5961 5776 + 9 5921 5922 5963 5962 5777 + 9 5922 5923 5964 5963 5778 + 9 5923 5924 5965 5964 5779 + 9 5924 5925 5966 5965 5780 + 9 5925 5926 5967 5966 5781 + 9 5926 5927 5968 5967 5782 + 9 5927 5928 5969 5968 5783 + 9 5928 5929 5970 5969 5784 + 9 5929 5930 5971 5970 5785 + 9 5930 5931 5972 5971 5786 + 9 5931 5932 5973 5972 5787 + 9 5932 5933 5974 5973 5788 + 9 5933 5934 5975 5974 5789 + 9 5934 5935 5976 5975 5790 + 9 5935 5936 5977 5976 5791 + 9 5936 5937 5978 5977 5792 + 9 5937 5938 5979 5978 5793 + 9 5938 5939 5980 5979 5794 + 9 5939 5940 5981 5980 5795 + 9 5940 5941 5982 5981 5796 + 9 5941 5942 5983 5982 5797 + 9 5942 5943 5984 5983 5798 + 9 5943 5944 5985 5984 5799 + 9 5945 5946 5987 5986 5800 + 9 5946 5947 5988 5987 5801 + 9 5947 5948 5989 5988 5802 + 9 5948 5949 5990 5989 5803 + 9 5949 5950 5991 5990 5804 + 9 5950 5951 5992 5991 5805 + 9 5951 5952 5993 5992 5806 + 9 5952 5953 5994 5993 5807 + 9 5953 5954 5995 5994 5808 + 9 5954 5955 5996 5995 5809 + 9 5955 5956 5997 5996 5810 + 9 5956 5957 5998 5997 5811 + 9 5957 5958 5999 5998 5812 + 9 5958 5959 6000 5999 5813 + 9 5959 5960 6001 6000 5814 + 9 5960 5961 6002 6001 5815 + 9 5961 5962 6003 6002 5816 + 9 5962 5963 6004 6003 5817 + 9 5963 5964 6005 6004 5818 + 9 5964 5965 6006 6005 5819 + 9 5965 5966 6007 6006 5820 + 9 5966 5967 6008 6007 5821 + 9 5967 5968 6009 6008 5822 + 9 5968 5969 6010 6009 5823 + 9 5969 5970 6011 6010 5824 + 9 5970 5971 6012 6011 5825 + 9 5971 5972 6013 6012 5826 + 9 5972 5973 6014 6013 5827 + 9 5973 5974 6015 6014 5828 + 9 5974 5975 6016 6015 5829 + 9 5975 5976 6017 6016 5830 + 9 5976 5977 6018 6017 5831 + 9 5977 5978 6019 6018 5832 + 9 5978 5979 6020 6019 5833 + 9 5979 5980 6021 6020 5834 + 9 5980 5981 6022 6021 5835 + 9 5981 5982 6023 6022 5836 + 9 5982 5983 6024 6023 5837 + 9 5983 5984 6025 6024 5838 + 9 5984 5985 6026 6025 5839 + 9 5986 5987 6028 6027 5840 + 9 5987 5988 6029 6028 5841 + 9 5988 5989 6030 6029 5842 + 9 5989 5990 6031 6030 5843 + 9 5990 5991 6032 6031 5844 + 9 5991 5992 6033 6032 5845 + 9 5992 5993 6034 6033 5846 + 9 5993 5994 6035 6034 5847 + 9 5994 5995 6036 6035 5848 + 9 5995 5996 6037 6036 5849 + 9 5996 5997 6038 6037 5850 + 9 5997 5998 6039 6038 5851 + 9 5998 5999 6040 6039 5852 + 9 5999 6000 6041 6040 5853 + 9 6000 6001 6042 6041 5854 + 9 6001 6002 6043 6042 5855 + 9 6002 6003 6044 6043 5856 + 9 6003 6004 6045 6044 5857 + 9 6004 6005 6046 6045 5858 + 9 6005 6006 6047 6046 5859 + 9 6006 6007 6048 6047 5860 + 9 6007 6008 6049 6048 5861 + 9 6008 6009 6050 6049 5862 + 9 6009 6010 6051 6050 5863 + 9 6010 6011 6052 6051 5864 + 9 6011 6012 6053 6052 5865 + 9 6012 6013 6054 6053 5866 + 9 6013 6014 6055 6054 5867 + 9 6014 6015 6056 6055 5868 + 9 6015 6016 6057 6056 5869 + 9 6016 6017 6058 6057 5870 + 9 6017 6018 6059 6058 5871 + 9 6018 6019 6060 6059 5872 + 9 6019 6020 6061 6060 5873 + 9 6020 6021 6062 6061 5874 + 9 6021 6022 6063 6062 5875 + 9 6022 6023 6064 6063 5876 + 9 6023 6024 6065 6064 5877 + 9 6024 6025 6066 6065 5878 + 9 6025 6026 6067 6066 5879 + 9 6027 6028 6069 6068 5880 + 9 6028 6029 6070 6069 5881 + 9 6029 6030 6071 6070 5882 + 9 6030 6031 6072 6071 5883 + 9 6031 6032 6073 6072 5884 + 9 6032 6033 6074 6073 5885 + 9 6033 6034 6075 6074 5886 + 9 6034 6035 6076 6075 5887 + 9 6035 6036 6077 6076 5888 + 9 6036 6037 6078 6077 5889 + 9 6037 6038 6079 6078 5890 + 9 6038 6039 6080 6079 5891 + 9 6039 6040 6081 6080 5892 + 9 6040 6041 6082 6081 5893 + 9 6041 6042 6083 6082 5894 + 9 6042 6043 6084 6083 5895 + 9 6043 6044 6085 6084 5896 + 9 6044 6045 6086 6085 5897 + 9 6045 6046 6087 6086 5898 + 9 6046 6047 6088 6087 5899 + 9 6047 6048 6089 6088 5900 + 9 6048 6049 6090 6089 5901 + 9 6049 6050 6091 6090 5902 + 9 6050 6051 6092 6091 5903 + 9 6051 6052 6093 6092 5904 + 9 6052 6053 6094 6093 5905 + 9 6053 6054 6095 6094 5906 + 9 6054 6055 6096 6095 5907 + 9 6055 6056 6097 6096 5908 + 9 6056 6057 6098 6097 5909 + 9 6057 6058 6099 6098 5910 + 9 6058 6059 6100 6099 5911 + 9 6059 6060 6101 6100 5912 + 9 6060 6061 6102 6101 5913 + 9 6061 6062 6103 6102 5914 + 9 6062 6063 6104 6103 5915 + 9 6063 6064 6105 6104 5916 + 9 6064 6065 6106 6105 5917 + 9 6065 6066 6107 6106 5918 + 9 6066 6067 6108 6107 5919 + 9 6068 6069 6110 6109 5920 + 9 6069 6070 6111 6110 5921 + 9 6070 6071 6112 6111 5922 + 9 6071 6072 6113 6112 5923 + 9 6072 6073 6114 6113 5924 + 9 6073 6074 6115 6114 5925 + 9 6074 6075 6116 6115 5926 + 9 6075 6076 6117 6116 5927 + 9 6076 6077 6118 6117 5928 + 9 6077 6078 6119 6118 5929 + 9 6078 6079 6120 6119 5930 + 9 6079 6080 6121 6120 5931 + 9 6080 6081 6122 6121 5932 + 9 6081 6082 6123 6122 5933 + 9 6082 6083 6124 6123 5934 + 9 6083 6084 6125 6124 5935 + 9 6084 6085 6126 6125 5936 + 9 6085 6086 6127 6126 5937 + 9 6086 6087 6128 6127 5938 + 9 6087 6088 6129 6128 5939 + 9 6088 6089 6130 6129 5940 + 9 6089 6090 6131 6130 5941 + 9 6090 6091 6132 6131 5942 + 9 6091 6092 6133 6132 5943 + 9 6092 6093 6134 6133 5944 + 9 6093 6094 6135 6134 5945 + 9 6094 6095 6136 6135 5946 + 9 6095 6096 6137 6136 5947 + 9 6096 6097 6138 6137 5948 + 9 6097 6098 6139 6138 5949 + 9 6098 6099 6140 6139 5950 + 9 6099 6100 6141 6140 5951 + 9 6100 6101 6142 6141 5952 + 9 6101 6102 6143 6142 5953 + 9 6102 6103 6144 6143 5954 + 9 6103 6104 6145 6144 5955 + 9 6104 6105 6146 6145 5956 + 9 6105 6106 6147 6146 5957 + 9 6106 6107 6148 6147 5958 + 9 6107 6108 6149 6148 5959 + 9 6109 6110 6151 6150 5960 + 9 6110 6111 6152 6151 5961 + 9 6111 6112 6153 6152 5962 + 9 6112 6113 6154 6153 5963 + 9 6113 6114 6155 6154 5964 + 9 6114 6115 6156 6155 5965 + 9 6115 6116 6157 6156 5966 + 9 6116 6117 6158 6157 5967 + 9 6117 6118 6159 6158 5968 + 9 6118 6119 6160 6159 5969 + 9 6119 6120 6161 6160 5970 + 9 6120 6121 6162 6161 5971 + 9 6121 6122 6163 6162 5972 + 9 6122 6123 6164 6163 5973 + 9 6123 6124 6165 6164 5974 + 9 6124 6125 6166 6165 5975 + 9 6125 6126 6167 6166 5976 + 9 6126 6127 6168 6167 5977 + 9 6127 6128 6169 6168 5978 + 9 6128 6129 6170 6169 5979 + 9 6129 6130 6171 6170 5980 + 9 6130 6131 6172 6171 5981 + 9 6131 6132 6173 6172 5982 + 9 6132 6133 6174 6173 5983 + 9 6133 6134 6175 6174 5984 + 9 6134 6135 6176 6175 5985 + 9 6135 6136 6177 6176 5986 + 9 6136 6137 6178 6177 5987 + 9 6137 6138 6179 6178 5988 + 9 6138 6139 6180 6179 5989 + 9 6139 6140 6181 6180 5990 + 9 6140 6141 6182 6181 5991 + 9 6141 6142 6183 6182 5992 + 9 6142 6143 6184 6183 5993 + 9 6143 6144 6185 6184 5994 + 9 6144 6145 6186 6185 5995 + 9 6145 6146 6187 6186 5996 + 9 6146 6147 6188 6187 5997 + 9 6147 6148 6189 6188 5998 + 9 6148 6149 6190 6189 5999 + 9 6150 6151 6192 6191 6000 + 9 6151 6152 6193 6192 6001 + 9 6152 6153 6194 6193 6002 + 9 6153 6154 6195 6194 6003 + 9 6154 6155 6196 6195 6004 + 9 6155 6156 6197 6196 6005 + 9 6156 6157 6198 6197 6006 + 9 6157 6158 6199 6198 6007 + 9 6158 6159 6200 6199 6008 + 9 6159 6160 6201 6200 6009 + 9 6160 6161 6202 6201 6010 + 9 6161 6162 6203 6202 6011 + 9 6162 6163 6204 6203 6012 + 9 6163 6164 6205 6204 6013 + 9 6164 6165 6206 6205 6014 + 9 6165 6166 6207 6206 6015 + 9 6166 6167 6208 6207 6016 + 9 6167 6168 6209 6208 6017 + 9 6168 6169 6210 6209 6018 + 9 6169 6170 6211 6210 6019 + 9 6170 6171 6212 6211 6020 + 9 6171 6172 6213 6212 6021 + 9 6172 6173 6214 6213 6022 + 9 6173 6174 6215 6214 6023 + 9 6174 6175 6216 6215 6024 + 9 6175 6176 6217 6216 6025 + 9 6176 6177 6218 6217 6026 + 9 6177 6178 6219 6218 6027 + 9 6178 6179 6220 6219 6028 + 9 6179 6180 6221 6220 6029 + 9 6180 6181 6222 6221 6030 + 9 6181 6182 6223 6222 6031 + 9 6182 6183 6224 6223 6032 + 9 6183 6184 6225 6224 6033 + 9 6184 6185 6226 6225 6034 + 9 6185 6186 6227 6226 6035 + 9 6186 6187 6228 6227 6036 + 9 6187 6188 6229 6228 6037 + 9 6188 6189 6230 6229 6038 + 9 6189 6190 6231 6230 6039 + 9 6191 6192 6233 6232 6040 + 9 6192 6193 6234 6233 6041 + 9 6193 6194 6235 6234 6042 + 9 6194 6195 6236 6235 6043 + 9 6195 6196 6237 6236 6044 + 9 6196 6197 6238 6237 6045 + 9 6197 6198 6239 6238 6046 + 9 6198 6199 6240 6239 6047 + 9 6199 6200 6241 6240 6048 + 9 6200 6201 6242 6241 6049 + 9 6201 6202 6243 6242 6050 + 9 6202 6203 6244 6243 6051 + 9 6203 6204 6245 6244 6052 + 9 6204 6205 6246 6245 6053 + 9 6205 6206 6247 6246 6054 + 9 6206 6207 6248 6247 6055 + 9 6207 6208 6249 6248 6056 + 9 6208 6209 6250 6249 6057 + 9 6209 6210 6251 6250 6058 + 9 6210 6211 6252 6251 6059 + 9 6211 6212 6253 6252 6060 + 9 6212 6213 6254 6253 6061 + 9 6213 6214 6255 6254 6062 + 9 6214 6215 6256 6255 6063 + 9 6215 6216 6257 6256 6064 + 9 6216 6217 6258 6257 6065 + 9 6217 6218 6259 6258 6066 + 9 6218 6219 6260 6259 6067 + 9 6219 6220 6261 6260 6068 + 9 6220 6221 6262 6261 6069 + 9 6221 6222 6263 6262 6070 + 9 6222 6223 6264 6263 6071 + 9 6223 6224 6265 6264 6072 + 9 6224 6225 6266 6265 6073 + 9 6225 6226 6267 6266 6074 + 9 6226 6227 6268 6267 6075 + 9 6227 6228 6269 6268 6076 + 9 6228 6229 6270 6269 6077 + 9 6229 6230 6271 6270 6078 + 9 6230 6231 6272 6271 6079 + 9 6232 6233 6274 6273 6080 + 9 6233 6234 6275 6274 6081 + 9 6234 6235 6276 6275 6082 + 9 6235 6236 6277 6276 6083 + 9 6236 6237 6278 6277 6084 + 9 6237 6238 6279 6278 6085 + 9 6238 6239 6280 6279 6086 + 9 6239 6240 6281 6280 6087 + 9 6240 6241 6282 6281 6088 + 9 6241 6242 6283 6282 6089 + 9 6242 6243 6284 6283 6090 + 9 6243 6244 6285 6284 6091 + 9 6244 6245 6286 6285 6092 + 9 6245 6246 6287 6286 6093 + 9 6246 6247 6288 6287 6094 + 9 6247 6248 6289 6288 6095 + 9 6248 6249 6290 6289 6096 + 9 6249 6250 6291 6290 6097 + 9 6250 6251 6292 6291 6098 + 9 6251 6252 6293 6292 6099 + 9 6252 6253 6294 6293 6100 + 9 6253 6254 6295 6294 6101 + 9 6254 6255 6296 6295 6102 + 9 6255 6256 6297 6296 6103 + 9 6256 6257 6298 6297 6104 + 9 6257 6258 6299 6298 6105 + 9 6258 6259 6300 6299 6106 + 9 6259 6260 6301 6300 6107 + 9 6260 6261 6302 6301 6108 + 9 6261 6262 6303 6302 6109 + 9 6262 6263 6304 6303 6110 + 9 6263 6264 6305 6304 6111 + 9 6264 6265 6306 6305 6112 + 9 6265 6266 6307 6306 6113 + 9 6266 6267 6308 6307 6114 + 9 6267 6268 6309 6308 6115 + 9 6268 6269 6310 6309 6116 + 9 6269 6270 6311 6310 6117 + 9 6270 6271 6312 6311 6118 + 9 6271 6272 6313 6312 6119 + 9 6273 6274 6315 6314 6120 + 9 6274 6275 6316 6315 6121 + 9 6275 6276 6317 6316 6122 + 9 6276 6277 6318 6317 6123 + 9 6277 6278 6319 6318 6124 + 9 6278 6279 6320 6319 6125 + 9 6279 6280 6321 6320 6126 + 9 6280 6281 6322 6321 6127 + 9 6281 6282 6323 6322 6128 + 9 6282 6283 6324 6323 6129 + 9 6283 6284 6325 6324 6130 + 9 6284 6285 6326 6325 6131 + 9 6285 6286 6327 6326 6132 + 9 6286 6287 6328 6327 6133 + 9 6287 6288 6329 6328 6134 + 9 6288 6289 6330 6329 6135 + 9 6289 6290 6331 6330 6136 + 9 6290 6291 6332 6331 6137 + 9 6291 6292 6333 6332 6138 + 9 6292 6293 6334 6333 6139 + 9 6293 6294 6335 6334 6140 + 9 6294 6295 6336 6335 6141 + 9 6295 6296 6337 6336 6142 + 9 6296 6297 6338 6337 6143 + 9 6297 6298 6339 6338 6144 + 9 6298 6299 6340 6339 6145 + 9 6299 6300 6341 6340 6146 + 9 6300 6301 6342 6341 6147 + 9 6301 6302 6343 6342 6148 + 9 6302 6303 6344 6343 6149 + 9 6303 6304 6345 6344 6150 + 9 6304 6305 6346 6345 6151 + 9 6305 6306 6347 6346 6152 + 9 6306 6307 6348 6347 6153 + 9 6307 6308 6349 6348 6154 + 9 6308 6309 6350 6349 6155 + 9 6309 6310 6351 6350 6156 + 9 6310 6311 6352 6351 6157 + 9 6311 6312 6353 6352 6158 + 9 6312 6313 6354 6353 6159 + 9 6314 6315 6356 6355 6160 + 9 6315 6316 6357 6356 6161 + 9 6316 6317 6358 6357 6162 + 9 6317 6318 6359 6358 6163 + 9 6318 6319 6360 6359 6164 + 9 6319 6320 6361 6360 6165 + 9 6320 6321 6362 6361 6166 + 9 6321 6322 6363 6362 6167 + 9 6322 6323 6364 6363 6168 + 9 6323 6324 6365 6364 6169 + 9 6324 6325 6366 6365 6170 + 9 6325 6326 6367 6366 6171 + 9 6326 6327 6368 6367 6172 + 9 6327 6328 6369 6368 6173 + 9 6328 6329 6370 6369 6174 + 9 6329 6330 6371 6370 6175 + 9 6330 6331 6372 6371 6176 + 9 6331 6332 6373 6372 6177 + 9 6332 6333 6374 6373 6178 + 9 6333 6334 6375 6374 6179 + 9 6334 6335 6376 6375 6180 + 9 6335 6336 6377 6376 6181 + 9 6336 6337 6378 6377 6182 + 9 6337 6338 6379 6378 6183 + 9 6338 6339 6380 6379 6184 + 9 6339 6340 6381 6380 6185 + 9 6340 6341 6382 6381 6186 + 9 6341 6342 6383 6382 6187 + 9 6342 6343 6384 6383 6188 + 9 6343 6344 6385 6384 6189 + 9 6344 6345 6386 6385 6190 + 9 6345 6346 6387 6386 6191 + 9 6346 6347 6388 6387 6192 + 9 6347 6348 6389 6388 6193 + 9 6348 6349 6390 6389 6194 + 9 6349 6350 6391 6390 6195 + 9 6350 6351 6392 6391 6196 + 9 6351 6352 6393 6392 6197 + 9 6352 6353 6394 6393 6198 + 9 6353 6354 6395 6394 6199 + 9 6355 6356 6397 6396 6200 + 9 6356 6357 6398 6397 6201 + 9 6357 6358 6399 6398 6202 + 9 6358 6359 6400 6399 6203 + 9 6359 6360 6401 6400 6204 + 9 6360 6361 6402 6401 6205 + 9 6361 6362 6403 6402 6206 + 9 6362 6363 6404 6403 6207 + 9 6363 6364 6405 6404 6208 + 9 6364 6365 6406 6405 6209 + 9 6365 6366 6407 6406 6210 + 9 6366 6367 6408 6407 6211 + 9 6367 6368 6409 6408 6212 + 9 6368 6369 6410 6409 6213 + 9 6369 6370 6411 6410 6214 + 9 6370 6371 6412 6411 6215 + 9 6371 6372 6413 6412 6216 + 9 6372 6373 6414 6413 6217 + 9 6373 6374 6415 6414 6218 + 9 6374 6375 6416 6415 6219 + 9 6375 6376 6417 6416 6220 + 9 6376 6377 6418 6417 6221 + 9 6377 6378 6419 6418 6222 + 9 6378 6379 6420 6419 6223 + 9 6379 6380 6421 6420 6224 + 9 6380 6381 6422 6421 6225 + 9 6381 6382 6423 6422 6226 + 9 6382 6383 6424 6423 6227 + 9 6383 6384 6425 6424 6228 + 9 6384 6385 6426 6425 6229 + 9 6385 6386 6427 6426 6230 + 9 6386 6387 6428 6427 6231 + 9 6387 6388 6429 6428 6232 + 9 6388 6389 6430 6429 6233 + 9 6389 6390 6431 6430 6234 + 9 6390 6391 6432 6431 6235 + 9 6391 6392 6433 6432 6236 + 9 6392 6393 6434 6433 6237 + 9 6393 6394 6435 6434 6238 + 9 6394 6395 6436 6435 6239 + 9 6396 6397 6438 6437 6240 + 9 6397 6398 6439 6438 6241 + 9 6398 6399 6440 6439 6242 + 9 6399 6400 6441 6440 6243 + 9 6400 6401 6442 6441 6244 + 9 6401 6402 6443 6442 6245 + 9 6402 6403 6444 6443 6246 + 9 6403 6404 6445 6444 6247 + 9 6404 6405 6446 6445 6248 + 9 6405 6406 6447 6446 6249 + 9 6406 6407 6448 6447 6250 + 9 6407 6408 6449 6448 6251 + 9 6408 6409 6450 6449 6252 + 9 6409 6410 6451 6450 6253 + 9 6410 6411 6452 6451 6254 + 9 6411 6412 6453 6452 6255 + 9 6412 6413 6454 6453 6256 + 9 6413 6414 6455 6454 6257 + 9 6414 6415 6456 6455 6258 + 9 6415 6416 6457 6456 6259 + 9 6416 6417 6458 6457 6260 + 9 6417 6418 6459 6458 6261 + 9 6418 6419 6460 6459 6262 + 9 6419 6420 6461 6460 6263 + 9 6420 6421 6462 6461 6264 + 9 6421 6422 6463 6462 6265 + 9 6422 6423 6464 6463 6266 + 9 6423 6424 6465 6464 6267 + 9 6424 6425 6466 6465 6268 + 9 6425 6426 6467 6466 6269 + 9 6426 6427 6468 6467 6270 + 9 6427 6428 6469 6468 6271 + 9 6428 6429 6470 6469 6272 + 9 6429 6430 6471 6470 6273 + 9 6430 6431 6472 6471 6274 + 9 6431 6432 6473 6472 6275 + 9 6432 6433 6474 6473 6276 + 9 6433 6434 6475 6474 6277 + 9 6434 6435 6476 6475 6278 + 9 6435 6436 6477 6476 6279 + 9 6437 6438 6479 6478 6280 + 9 6438 6439 6480 6479 6281 + 9 6439 6440 6481 6480 6282 + 9 6440 6441 6482 6481 6283 + 9 6441 6442 6483 6482 6284 + 9 6442 6443 6484 6483 6285 + 9 6443 6444 6485 6484 6286 + 9 6444 6445 6486 6485 6287 + 9 6445 6446 6487 6486 6288 + 9 6446 6447 6488 6487 6289 + 9 6447 6448 6489 6488 6290 + 9 6448 6449 6490 6489 6291 + 9 6449 6450 6491 6490 6292 + 9 6450 6451 6492 6491 6293 + 9 6451 6452 6493 6492 6294 + 9 6452 6453 6494 6493 6295 + 9 6453 6454 6495 6494 6296 + 9 6454 6455 6496 6495 6297 + 9 6455 6456 6497 6496 6298 + 9 6456 6457 6498 6497 6299 + 9 6457 6458 6499 6498 6300 + 9 6458 6459 6500 6499 6301 + 9 6459 6460 6501 6500 6302 + 9 6460 6461 6502 6501 6303 + 9 6461 6462 6503 6502 6304 + 9 6462 6463 6504 6503 6305 + 9 6463 6464 6505 6504 6306 + 9 6464 6465 6506 6505 6307 + 9 6465 6466 6507 6506 6308 + 9 6466 6467 6508 6507 6309 + 9 6467 6468 6509 6508 6310 + 9 6468 6469 6510 6509 6311 + 9 6469 6470 6511 6510 6312 + 9 6470 6471 6512 6511 6313 + 9 6471 6472 6513 6512 6314 + 9 6472 6473 6514 6513 6315 + 9 6473 6474 6515 6514 6316 + 9 6474 6475 6516 6515 6317 + 9 6475 6476 6517 6516 6318 + 9 6476 6477 6518 6517 6319 + 9 6478 6479 6520 6519 6320 + 9 6479 6480 6521 6520 6321 + 9 6480 6481 6522 6521 6322 + 9 6481 6482 6523 6522 6323 + 9 6482 6483 6524 6523 6324 + 9 6483 6484 6525 6524 6325 + 9 6484 6485 6526 6525 6326 + 9 6485 6486 6527 6526 6327 + 9 6486 6487 6528 6527 6328 + 9 6487 6488 6529 6528 6329 + 9 6488 6489 6530 6529 6330 + 9 6489 6490 6531 6530 6331 + 9 6490 6491 6532 6531 6332 + 9 6491 6492 6533 6532 6333 + 9 6492 6493 6534 6533 6334 + 9 6493 6494 6535 6534 6335 + 9 6494 6495 6536 6535 6336 + 9 6495 6496 6537 6536 6337 + 9 6496 6497 6538 6537 6338 + 9 6497 6498 6539 6538 6339 + 9 6498 6499 6540 6539 6340 + 9 6499 6500 6541 6540 6341 + 9 6500 6501 6542 6541 6342 + 9 6501 6502 6543 6542 6343 + 9 6502 6503 6544 6543 6344 + 9 6503 6504 6545 6544 6345 + 9 6504 6505 6546 6545 6346 + 9 6505 6506 6547 6546 6347 + 9 6506 6507 6548 6547 6348 + 9 6507 6508 6549 6548 6349 + 9 6508 6509 6550 6549 6350 + 9 6509 6510 6551 6550 6351 + 9 6510 6511 6552 6551 6352 + 9 6511 6512 6553 6552 6353 + 9 6512 6513 6554 6553 6354 + 9 6513 6514 6555 6554 6355 + 9 6514 6515 6556 6555 6356 + 9 6515 6516 6557 6556 6357 + 9 6516 6517 6558 6557 6358 + 9 6517 6518 6559 6558 6359 + 9 6519 6520 6561 6560 6360 + 9 6520 6521 6562 6561 6361 + 9 6521 6522 6563 6562 6362 + 9 6522 6523 6564 6563 6363 + 9 6523 6524 6565 6564 6364 + 9 6524 6525 6566 6565 6365 + 9 6525 6526 6567 6566 6366 + 9 6526 6527 6568 6567 6367 + 9 6527 6528 6569 6568 6368 + 9 6528 6529 6570 6569 6369 + 9 6529 6530 6571 6570 6370 + 9 6530 6531 6572 6571 6371 + 9 6531 6532 6573 6572 6372 + 9 6532 6533 6574 6573 6373 + 9 6533 6534 6575 6574 6374 + 9 6534 6535 6576 6575 6375 + 9 6535 6536 6577 6576 6376 + 9 6536 6537 6578 6577 6377 + 9 6537 6538 6579 6578 6378 + 9 6538 6539 6580 6579 6379 + 9 6539 6540 6581 6580 6380 + 9 6540 6541 6582 6581 6381 + 9 6541 6542 6583 6582 6382 + 9 6542 6543 6584 6583 6383 + 9 6543 6544 6585 6584 6384 + 9 6544 6545 6586 6585 6385 + 9 6545 6546 6587 6586 6386 + 9 6546 6547 6588 6587 6387 + 9 6547 6548 6589 6588 6388 + 9 6548 6549 6590 6589 6389 + 9 6549 6550 6591 6590 6390 + 9 6550 6551 6592 6591 6391 + 9 6551 6552 6593 6592 6392 + 9 6552 6553 6594 6593 6393 + 9 6553 6554 6595 6594 6394 + 9 6554 6555 6596 6595 6395 + 9 6555 6556 6597 6596 6396 + 9 6556 6557 6598 6597 6397 + 9 6557 6558 6599 6598 6398 + 9 6558 6559 6600 6599 6399 + 9 6560 6561 6602 6601 6400 + 9 6561 6562 6603 6602 6401 + 9 6562 6563 6604 6603 6402 + 9 6563 6564 6605 6604 6403 + 9 6564 6565 6606 6605 6404 + 9 6565 6566 6607 6606 6405 + 9 6566 6567 6608 6607 6406 + 9 6567 6568 6609 6608 6407 + 9 6568 6569 6610 6609 6408 + 9 6569 6570 6611 6610 6409 + 9 6570 6571 6612 6611 6410 + 9 6571 6572 6613 6612 6411 + 9 6572 6573 6614 6613 6412 + 9 6573 6574 6615 6614 6413 + 9 6574 6575 6616 6615 6414 + 9 6575 6576 6617 6616 6415 + 9 6576 6577 6618 6617 6416 + 9 6577 6578 6619 6618 6417 + 9 6578 6579 6620 6619 6418 + 9 6579 6580 6621 6620 6419 + 9 6580 6581 6622 6621 6420 + 9 6581 6582 6623 6622 6421 + 9 6582 6583 6624 6623 6422 + 9 6583 6584 6625 6624 6423 + 9 6584 6585 6626 6625 6424 + 9 6585 6586 6627 6626 6425 + 9 6586 6587 6628 6627 6426 + 9 6587 6588 6629 6628 6427 + 9 6588 6589 6630 6629 6428 + 9 6589 6590 6631 6630 6429 + 9 6590 6591 6632 6631 6430 + 9 6591 6592 6633 6632 6431 + 9 6592 6593 6634 6633 6432 + 9 6593 6594 6635 6634 6433 + 9 6594 6595 6636 6635 6434 + 9 6595 6596 6637 6636 6435 + 9 6596 6597 6638 6637 6436 + 9 6597 6598 6639 6638 6437 + 9 6598 6599 6640 6639 6438 + 9 6599 6600 6641 6640 6439 + 9 6601 6602 6643 6642 6440 + 9 6602 6603 6644 6643 6441 + 9 6603 6604 6645 6644 6442 + 9 6604 6605 6646 6645 6443 + 9 6605 6606 6647 6646 6444 + 9 6606 6607 6648 6647 6445 + 9 6607 6608 6649 6648 6446 + 9 6608 6609 6650 6649 6447 + 9 6609 6610 6651 6650 6448 + 9 6610 6611 6652 6651 6449 + 9 6611 6612 6653 6652 6450 + 9 6612 6613 6654 6653 6451 + 9 6613 6614 6655 6654 6452 + 9 6614 6615 6656 6655 6453 + 9 6615 6616 6657 6656 6454 + 9 6616 6617 6658 6657 6455 + 9 6617 6618 6659 6658 6456 + 9 6618 6619 6660 6659 6457 + 9 6619 6620 6661 6660 6458 + 9 6620 6621 6662 6661 6459 + 9 6621 6622 6663 6662 6460 + 9 6622 6623 6664 6663 6461 + 9 6623 6624 6665 6664 6462 + 9 6624 6625 6666 6665 6463 + 9 6625 6626 6667 6666 6464 + 9 6626 6627 6668 6667 6465 + 9 6627 6628 6669 6668 6466 + 9 6628 6629 6670 6669 6467 + 9 6629 6630 6671 6670 6468 + 9 6630 6631 6672 6671 6469 + 9 6631 6632 6673 6672 6470 + 9 6632 6633 6674 6673 6471 + 9 6633 6634 6675 6674 6472 + 9 6634 6635 6676 6675 6473 + 9 6635 6636 6677 6676 6474 + 9 6636 6637 6678 6677 6475 + 9 6637 6638 6679 6678 6476 + 9 6638 6639 6680 6679 6477 + 9 6639 6640 6681 6680 6478 + 9 6640 6641 6682 6681 6479 + 9 6642 6643 6684 6683 6480 + 9 6643 6644 6685 6684 6481 + 9 6644 6645 6686 6685 6482 + 9 6645 6646 6687 6686 6483 + 9 6646 6647 6688 6687 6484 + 9 6647 6648 6689 6688 6485 + 9 6648 6649 6690 6689 6486 + 9 6649 6650 6691 6690 6487 + 9 6650 6651 6692 6691 6488 + 9 6651 6652 6693 6692 6489 + 9 6652 6653 6694 6693 6490 + 9 6653 6654 6695 6694 6491 + 9 6654 6655 6696 6695 6492 + 9 6655 6656 6697 6696 6493 + 9 6656 6657 6698 6697 6494 + 9 6657 6658 6699 6698 6495 + 9 6658 6659 6700 6699 6496 + 9 6659 6660 6701 6700 6497 + 9 6660 6661 6702 6701 6498 + 9 6661 6662 6703 6702 6499 + 9 6662 6663 6704 6703 6500 + 9 6663 6664 6705 6704 6501 + 9 6664 6665 6706 6705 6502 + 9 6665 6666 6707 6706 6503 + 9 6666 6667 6708 6707 6504 + 9 6667 6668 6709 6708 6505 + 9 6668 6669 6710 6709 6506 + 9 6669 6670 6711 6710 6507 + 9 6670 6671 6712 6711 6508 + 9 6671 6672 6713 6712 6509 + 9 6672 6673 6714 6713 6510 + 9 6673 6674 6715 6714 6511 + 9 6674 6675 6716 6715 6512 + 9 6675 6676 6717 6716 6513 + 9 6676 6677 6718 6717 6514 + 9 6677 6678 6719 6718 6515 + 9 6678 6679 6720 6719 6516 + 9 6679 6680 6721 6720 6517 + 9 6680 6681 6722 6721 6518 + 9 6681 6682 6723 6722 6519 + 9 6683 6684 6725 6724 6520 + 9 6684 6685 6726 6725 6521 + 9 6685 6686 6727 6726 6522 + 9 6686 6687 6728 6727 6523 + 9 6687 6688 6729 6728 6524 + 9 6688 6689 6730 6729 6525 + 9 6689 6690 6731 6730 6526 + 9 6690 6691 6732 6731 6527 + 9 6691 6692 6733 6732 6528 + 9 6692 6693 6734 6733 6529 + 9 6693 6694 6735 6734 6530 + 9 6694 6695 6736 6735 6531 + 9 6695 6696 6737 6736 6532 + 9 6696 6697 6738 6737 6533 + 9 6697 6698 6739 6738 6534 + 9 6698 6699 6740 6739 6535 + 9 6699 6700 6741 6740 6536 + 9 6700 6701 6742 6741 6537 + 9 6701 6702 6743 6742 6538 + 9 6702 6703 6744 6743 6539 + 9 6703 6704 6745 6744 6540 + 9 6704 6705 6746 6745 6541 + 9 6705 6706 6747 6746 6542 + 9 6706 6707 6748 6747 6543 + 9 6707 6708 6749 6748 6544 + 9 6708 6709 6750 6749 6545 + 9 6709 6710 6751 6750 6546 + 9 6710 6711 6752 6751 6547 + 9 6711 6712 6753 6752 6548 + 9 6712 6713 6754 6753 6549 + 9 6713 6714 6755 6754 6550 + 9 6714 6715 6756 6755 6551 + 9 6715 6716 6757 6756 6552 + 9 6716 6717 6758 6757 6553 + 9 6717 6718 6759 6758 6554 + 9 6718 6719 6760 6759 6555 + 9 6719 6720 6761 6760 6556 + 9 6720 6721 6762 6761 6557 + 9 6721 6722 6763 6762 6558 + 9 6722 6723 6764 6763 6559 + 9 6724 6725 6766 6765 6560 + 9 6725 6726 6767 6766 6561 + 9 6726 6727 6768 6767 6562 + 9 6727 6728 6769 6768 6563 + 9 6728 6729 6770 6769 6564 + 9 6729 6730 6771 6770 6565 + 9 6730 6731 6772 6771 6566 + 9 6731 6732 6773 6772 6567 + 9 6732 6733 6774 6773 6568 + 9 6733 6734 6775 6774 6569 + 9 6734 6735 6776 6775 6570 + 9 6735 6736 6777 6776 6571 + 9 6736 6737 6778 6777 6572 + 9 6737 6738 6779 6778 6573 + 9 6738 6739 6780 6779 6574 + 9 6739 6740 6781 6780 6575 + 9 6740 6741 6782 6781 6576 + 9 6741 6742 6783 6782 6577 + 9 6742 6743 6784 6783 6578 + 9 6743 6744 6785 6784 6579 + 9 6744 6745 6786 6785 6580 + 9 6745 6746 6787 6786 6581 + 9 6746 6747 6788 6787 6582 + 9 6747 6748 6789 6788 6583 + 9 6748 6749 6790 6789 6584 + 9 6749 6750 6791 6790 6585 + 9 6750 6751 6792 6791 6586 + 9 6751 6752 6793 6792 6587 + 9 6752 6753 6794 6793 6588 + 9 6753 6754 6795 6794 6589 + 9 6754 6755 6796 6795 6590 + 9 6755 6756 6797 6796 6591 + 9 6756 6757 6798 6797 6592 + 9 6757 6758 6799 6798 6593 + 9 6758 6759 6800 6799 6594 + 9 6759 6760 6801 6800 6595 + 9 6760 6761 6802 6801 6596 + 9 6761 6762 6803 6802 6597 + 9 6762 6763 6804 6803 6598 + 9 6763 6764 6805 6804 6599 + 9 6765 6766 6807 6806 6600 + 9 6766 6767 6808 6807 6601 + 9 6767 6768 6809 6808 6602 + 9 6768 6769 6810 6809 6603 + 9 6769 6770 6811 6810 6604 + 9 6770 6771 6812 6811 6605 + 9 6771 6772 6813 6812 6606 + 9 6772 6773 6814 6813 6607 + 9 6773 6774 6815 6814 6608 + 9 6774 6775 6816 6815 6609 + 9 6775 6776 6817 6816 6610 + 9 6776 6777 6818 6817 6611 + 9 6777 6778 6819 6818 6612 + 9 6778 6779 6820 6819 6613 + 9 6779 6780 6821 6820 6614 + 9 6780 6781 6822 6821 6615 + 9 6781 6782 6823 6822 6616 + 9 6782 6783 6824 6823 6617 + 9 6783 6784 6825 6824 6618 + 9 6784 6785 6826 6825 6619 + 9 6785 6786 6827 6826 6620 + 9 6786 6787 6828 6827 6621 + 9 6787 6788 6829 6828 6622 + 9 6788 6789 6830 6829 6623 + 9 6789 6790 6831 6830 6624 + 9 6790 6791 6832 6831 6625 + 9 6791 6792 6833 6832 6626 + 9 6792 6793 6834 6833 6627 + 9 6793 6794 6835 6834 6628 + 9 6794 6795 6836 6835 6629 + 9 6795 6796 6837 6836 6630 + 9 6796 6797 6838 6837 6631 + 9 6797 6798 6839 6838 6632 + 9 6798 6799 6840 6839 6633 + 9 6799 6800 6841 6840 6634 + 9 6800 6801 6842 6841 6635 + 9 6801 6802 6843 6842 6636 + 9 6802 6803 6844 6843 6637 + 9 6803 6804 6845 6844 6638 + 9 6804 6805 6846 6845 6639 + 9 6806 6807 6848 6847 6640 + 9 6807 6808 6849 6848 6641 + 9 6808 6809 6850 6849 6642 + 9 6809 6810 6851 6850 6643 + 9 6810 6811 6852 6851 6644 + 9 6811 6812 6853 6852 6645 + 9 6812 6813 6854 6853 6646 + 9 6813 6814 6855 6854 6647 + 9 6814 6815 6856 6855 6648 + 9 6815 6816 6857 6856 6649 + 9 6816 6817 6858 6857 6650 + 9 6817 6818 6859 6858 6651 + 9 6818 6819 6860 6859 6652 + 9 6819 6820 6861 6860 6653 + 9 6820 6821 6862 6861 6654 + 9 6821 6822 6863 6862 6655 + 9 6822 6823 6864 6863 6656 + 9 6823 6824 6865 6864 6657 + 9 6824 6825 6866 6865 6658 + 9 6825 6826 6867 6866 6659 + 9 6826 6827 6868 6867 6660 + 9 6827 6828 6869 6868 6661 + 9 6828 6829 6870 6869 6662 + 9 6829 6830 6871 6870 6663 + 9 6830 6831 6872 6871 6664 + 9 6831 6832 6873 6872 6665 + 9 6832 6833 6874 6873 6666 + 9 6833 6834 6875 6874 6667 + 9 6834 6835 6876 6875 6668 + 9 6835 6836 6877 6876 6669 + 9 6836 6837 6878 6877 6670 + 9 6837 6838 6879 6878 6671 + 9 6838 6839 6880 6879 6672 + 9 6839 6840 6881 6880 6673 + 9 6840 6841 6882 6881 6674 + 9 6841 6842 6883 6882 6675 + 9 6842 6843 6884 6883 6676 + 9 6843 6844 6885 6884 6677 + 9 6844 6845 6886 6885 6678 + 9 6845 6846 6887 6886 6679 + 9 6847 6848 6889 6888 6680 + 9 6848 6849 6890 6889 6681 + 9 6849 6850 6891 6890 6682 + 9 6850 6851 6892 6891 6683 + 9 6851 6852 6893 6892 6684 + 9 6852 6853 6894 6893 6685 + 9 6853 6854 6895 6894 6686 + 9 6854 6855 6896 6895 6687 + 9 6855 6856 6897 6896 6688 + 9 6856 6857 6898 6897 6689 + 9 6857 6858 6899 6898 6690 + 9 6858 6859 6900 6899 6691 + 9 6859 6860 6901 6900 6692 + 9 6860 6861 6902 6901 6693 + 9 6861 6862 6903 6902 6694 + 9 6862 6863 6904 6903 6695 + 9 6863 6864 6905 6904 6696 + 9 6864 6865 6906 6905 6697 + 9 6865 6866 6907 6906 6698 + 9 6866 6867 6908 6907 6699 + 9 6867 6868 6909 6908 6700 + 9 6868 6869 6910 6909 6701 + 9 6869 6870 6911 6910 6702 + 9 6870 6871 6912 6911 6703 + 9 6871 6872 6913 6912 6704 + 9 6872 6873 6914 6913 6705 + 9 6873 6874 6915 6914 6706 + 9 6874 6875 6916 6915 6707 + 9 6875 6876 6917 6916 6708 + 9 6876 6877 6918 6917 6709 + 9 6877 6878 6919 6918 6710 + 9 6878 6879 6920 6919 6711 + 9 6879 6880 6921 6920 6712 + 9 6880 6881 6922 6921 6713 + 9 6881 6882 6923 6922 6714 + 9 6882 6883 6924 6923 6715 + 9 6883 6884 6925 6924 6716 + 9 6884 6885 6926 6925 6717 + 9 6885 6886 6927 6926 6718 + 9 6886 6887 6928 6927 6719 + 9 6888 6889 6930 6929 6720 + 9 6889 6890 6931 6930 6721 + 9 6890 6891 6932 6931 6722 + 9 6891 6892 6933 6932 6723 + 9 6892 6893 6934 6933 6724 + 9 6893 6894 6935 6934 6725 + 9 6894 6895 6936 6935 6726 + 9 6895 6896 6937 6936 6727 + 9 6896 6897 6938 6937 6728 + 9 6897 6898 6939 6938 6729 + 9 6898 6899 6940 6939 6730 + 9 6899 6900 6941 6940 6731 + 9 6900 6901 6942 6941 6732 + 9 6901 6902 6943 6942 6733 + 9 6902 6903 6944 6943 6734 + 9 6903 6904 6945 6944 6735 + 9 6904 6905 6946 6945 6736 + 9 6905 6906 6947 6946 6737 + 9 6906 6907 6948 6947 6738 + 9 6907 6908 6949 6948 6739 + 9 6908 6909 6950 6949 6740 + 9 6909 6910 6951 6950 6741 + 9 6910 6911 6952 6951 6742 + 9 6911 6912 6953 6952 6743 + 9 6912 6913 6954 6953 6744 + 9 6913 6914 6955 6954 6745 + 9 6914 6915 6956 6955 6746 + 9 6915 6916 6957 6956 6747 + 9 6916 6917 6958 6957 6748 + 9 6917 6918 6959 6958 6749 + 9 6918 6919 6960 6959 6750 + 9 6919 6920 6961 6960 6751 + 9 6920 6921 6962 6961 6752 + 9 6921 6922 6963 6962 6753 + 9 6922 6923 6964 6963 6754 + 9 6923 6924 6965 6964 6755 + 9 6924 6925 6966 6965 6756 + 9 6925 6926 6967 6966 6757 + 9 6926 6927 6968 6967 6758 + 9 6927 6928 6969 6968 6759 + 9 6929 6930 6971 6970 6760 + 9 6930 6931 6972 6971 6761 + 9 6931 6932 6973 6972 6762 + 9 6932 6933 6974 6973 6763 + 9 6933 6934 6975 6974 6764 + 9 6934 6935 6976 6975 6765 + 9 6935 6936 6977 6976 6766 + 9 6936 6937 6978 6977 6767 + 9 6937 6938 6979 6978 6768 + 9 6938 6939 6980 6979 6769 + 9 6939 6940 6981 6980 6770 + 9 6940 6941 6982 6981 6771 + 9 6941 6942 6983 6982 6772 + 9 6942 6943 6984 6983 6773 + 9 6943 6944 6985 6984 6774 + 9 6944 6945 6986 6985 6775 + 9 6945 6946 6987 6986 6776 + 9 6946 6947 6988 6987 6777 + 9 6947 6948 6989 6988 6778 + 9 6948 6949 6990 6989 6779 + 9 6949 6950 6991 6990 6780 + 9 6950 6951 6992 6991 6781 + 9 6951 6952 6993 6992 6782 + 9 6952 6953 6994 6993 6783 + 9 6953 6954 6995 6994 6784 + 9 6954 6955 6996 6995 6785 + 9 6955 6956 6997 6996 6786 + 9 6956 6957 6998 6997 6787 + 9 6957 6958 6999 6998 6788 + 9 6958 6959 7000 6999 6789 + 9 6959 6960 7001 7000 6790 + 9 6960 6961 7002 7001 6791 + 9 6961 6962 7003 7002 6792 + 9 6962 6963 7004 7003 6793 + 9 6963 6964 7005 7004 6794 + 9 6964 6965 7006 7005 6795 + 9 6965 6966 7007 7006 6796 + 9 6966 6967 7008 7007 6797 + 9 6967 6968 7009 7008 6798 + 9 6968 6969 7010 7009 6799 + 9 6970 6971 7012 7011 6800 + 9 6971 6972 7013 7012 6801 + 9 6972 6973 7014 7013 6802 + 9 6973 6974 7015 7014 6803 + 9 6974 6975 7016 7015 6804 + 9 6975 6976 7017 7016 6805 + 9 6976 6977 7018 7017 6806 + 9 6977 6978 7019 7018 6807 + 9 6978 6979 7020 7019 6808 + 9 6979 6980 7021 7020 6809 + 9 6980 6981 7022 7021 6810 + 9 6981 6982 7023 7022 6811 + 9 6982 6983 7024 7023 6812 + 9 6983 6984 7025 7024 6813 + 9 6984 6985 7026 7025 6814 + 9 6985 6986 7027 7026 6815 + 9 6986 6987 7028 7027 6816 + 9 6987 6988 7029 7028 6817 + 9 6988 6989 7030 7029 6818 + 9 6989 6990 7031 7030 6819 + 9 6990 6991 7032 7031 6820 + 9 6991 6992 7033 7032 6821 + 9 6992 6993 7034 7033 6822 + 9 6993 6994 7035 7034 6823 + 9 6994 6995 7036 7035 6824 + 9 6995 6996 7037 7036 6825 + 9 6996 6997 7038 7037 6826 + 9 6997 6998 7039 7038 6827 + 9 6998 6999 7040 7039 6828 + 9 6999 7000 7041 7040 6829 + 9 7000 7001 7042 7041 6830 + 9 7001 7002 7043 7042 6831 + 9 7002 7003 7044 7043 6832 + 9 7003 7004 7045 7044 6833 + 9 7004 7005 7046 7045 6834 + 9 7005 7006 7047 7046 6835 + 9 7006 7007 7048 7047 6836 + 9 7007 7008 7049 7048 6837 + 9 7008 7009 7050 7049 6838 + 9 7009 7010 7051 7050 6839 + 9 7011 7012 7053 7052 6840 + 9 7012 7013 7054 7053 6841 + 9 7013 7014 7055 7054 6842 + 9 7014 7015 7056 7055 6843 + 9 7015 7016 7057 7056 6844 + 9 7016 7017 7058 7057 6845 + 9 7017 7018 7059 7058 6846 + 9 7018 7019 7060 7059 6847 + 9 7019 7020 7061 7060 6848 + 9 7020 7021 7062 7061 6849 + 9 7021 7022 7063 7062 6850 + 9 7022 7023 7064 7063 6851 + 9 7023 7024 7065 7064 6852 + 9 7024 7025 7066 7065 6853 + 9 7025 7026 7067 7066 6854 + 9 7026 7027 7068 7067 6855 + 9 7027 7028 7069 7068 6856 + 9 7028 7029 7070 7069 6857 + 9 7029 7030 7071 7070 6858 + 9 7030 7031 7072 7071 6859 + 9 7031 7032 7073 7072 6860 + 9 7032 7033 7074 7073 6861 + 9 7033 7034 7075 7074 6862 + 9 7034 7035 7076 7075 6863 + 9 7035 7036 7077 7076 6864 + 9 7036 7037 7078 7077 6865 + 9 7037 7038 7079 7078 6866 + 9 7038 7039 7080 7079 6867 + 9 7039 7040 7081 7080 6868 + 9 7040 7041 7082 7081 6869 + 9 7041 7042 7083 7082 6870 + 9 7042 7043 7084 7083 6871 + 9 7043 7044 7085 7084 6872 + 9 7044 7045 7086 7085 6873 + 9 7045 7046 7087 7086 6874 + 9 7046 7047 7088 7087 6875 + 9 7047 7048 7089 7088 6876 + 9 7048 7049 7090 7089 6877 + 9 7049 7050 7091 7090 6878 + 9 7050 7051 7092 7091 6879 + 9 7052 7053 7094 7093 6880 + 9 7053 7054 7095 7094 6881 + 9 7054 7055 7096 7095 6882 + 9 7055 7056 7097 7096 6883 + 9 7056 7057 7098 7097 6884 + 9 7057 7058 7099 7098 6885 + 9 7058 7059 7100 7099 6886 + 9 7059 7060 7101 7100 6887 + 9 7060 7061 7102 7101 6888 + 9 7061 7062 7103 7102 6889 + 9 7062 7063 7104 7103 6890 + 9 7063 7064 7105 7104 6891 + 9 7064 7065 7106 7105 6892 + 9 7065 7066 7107 7106 6893 + 9 7066 7067 7108 7107 6894 + 9 7067 7068 7109 7108 6895 + 9 7068 7069 7110 7109 6896 + 9 7069 7070 7111 7110 6897 + 9 7070 7071 7112 7111 6898 + 9 7071 7072 7113 7112 6899 + 9 7072 7073 7114 7113 6900 + 9 7073 7074 7115 7114 6901 + 9 7074 7075 7116 7115 6902 + 9 7075 7076 7117 7116 6903 + 9 7076 7077 7118 7117 6904 + 9 7077 7078 7119 7118 6905 + 9 7078 7079 7120 7119 6906 + 9 7079 7080 7121 7120 6907 + 9 7080 7081 7122 7121 6908 + 9 7081 7082 7123 7122 6909 + 9 7082 7083 7124 7123 6910 + 9 7083 7084 7125 7124 6911 + 9 7084 7085 7126 7125 6912 + 9 7085 7086 7127 7126 6913 + 9 7086 7087 7128 7127 6914 + 9 7087 7088 7129 7128 6915 + 9 7088 7089 7130 7129 6916 + 9 7089 7090 7131 7130 6917 + 9 7090 7091 7132 7131 6918 + 9 7091 7092 7133 7132 6919 + 9 7093 7094 7135 7134 6920 + 9 7094 7095 7136 7135 6921 + 9 7095 7096 7137 7136 6922 + 9 7096 7097 7138 7137 6923 + 9 7097 7098 7139 7138 6924 + 9 7098 7099 7140 7139 6925 + 9 7099 7100 7141 7140 6926 + 9 7100 7101 7142 7141 6927 + 9 7101 7102 7143 7142 6928 + 9 7102 7103 7144 7143 6929 + 9 7103 7104 7145 7144 6930 + 9 7104 7105 7146 7145 6931 + 9 7105 7106 7147 7146 6932 + 9 7106 7107 7148 7147 6933 + 9 7107 7108 7149 7148 6934 + 9 7108 7109 7150 7149 6935 + 9 7109 7110 7151 7150 6936 + 9 7110 7111 7152 7151 6937 + 9 7111 7112 7153 7152 6938 + 9 7112 7113 7154 7153 6939 + 9 7113 7114 7155 7154 6940 + 9 7114 7115 7156 7155 6941 + 9 7115 7116 7157 7156 6942 + 9 7116 7117 7158 7157 6943 + 9 7117 7118 7159 7158 6944 + 9 7118 7119 7160 7159 6945 + 9 7119 7120 7161 7160 6946 + 9 7120 7121 7162 7161 6947 + 9 7121 7122 7163 7162 6948 + 9 7122 7123 7164 7163 6949 + 9 7123 7124 7165 7164 6950 + 9 7124 7125 7166 7165 6951 + 9 7125 7126 7167 7166 6952 + 9 7126 7127 7168 7167 6953 + 9 7127 7128 7169 7168 6954 + 9 7128 7129 7170 7169 6955 + 9 7129 7130 7171 7170 6956 + 9 7130 7131 7172 7171 6957 + 9 7131 7132 7173 7172 6958 + 9 7132 7133 7174 7173 6959 + 9 7134 7135 7176 7175 6960 + 9 7135 7136 7177 7176 6961 + 9 7136 7137 7178 7177 6962 + 9 7137 7138 7179 7178 6963 + 9 7138 7139 7180 7179 6964 + 9 7139 7140 7181 7180 6965 + 9 7140 7141 7182 7181 6966 + 9 7141 7142 7183 7182 6967 + 9 7142 7143 7184 7183 6968 + 9 7143 7144 7185 7184 6969 + 9 7144 7145 7186 7185 6970 + 9 7145 7146 7187 7186 6971 + 9 7146 7147 7188 7187 6972 + 9 7147 7148 7189 7188 6973 + 9 7148 7149 7190 7189 6974 + 9 7149 7150 7191 7190 6975 + 9 7150 7151 7192 7191 6976 + 9 7151 7152 7193 7192 6977 + 9 7152 7153 7194 7193 6978 + 9 7153 7154 7195 7194 6979 + 9 7154 7155 7196 7195 6980 + 9 7155 7156 7197 7196 6981 + 9 7156 7157 7198 7197 6982 + 9 7157 7158 7199 7198 6983 + 9 7158 7159 7200 7199 6984 + 9 7159 7160 7201 7200 6985 + 9 7160 7161 7202 7201 6986 + 9 7161 7162 7203 7202 6987 + 9 7162 7163 7204 7203 6988 + 9 7163 7164 7205 7204 6989 + 9 7164 7165 7206 7205 6990 + 9 7165 7166 7207 7206 6991 + 9 7166 7167 7208 7207 6992 + 9 7167 7168 7209 7208 6993 + 9 7168 7169 7210 7209 6994 + 9 7169 7170 7211 7210 6995 + 9 7170 7171 7212 7211 6996 + 9 7171 7172 7213 7212 6997 + 9 7172 7173 7214 7213 6998 + 9 7173 7174 7215 7214 6999 + 9 7175 7176 7217 7216 7000 + 9 7176 7177 7218 7217 7001 + 9 7177 7178 7219 7218 7002 + 9 7178 7179 7220 7219 7003 + 9 7179 7180 7221 7220 7004 + 9 7180 7181 7222 7221 7005 + 9 7181 7182 7223 7222 7006 + 9 7182 7183 7224 7223 7007 + 9 7183 7184 7225 7224 7008 + 9 7184 7185 7226 7225 7009 + 9 7185 7186 7227 7226 7010 + 9 7186 7187 7228 7227 7011 + 9 7187 7188 7229 7228 7012 + 9 7188 7189 7230 7229 7013 + 9 7189 7190 7231 7230 7014 + 9 7190 7191 7232 7231 7015 + 9 7191 7192 7233 7232 7016 + 9 7192 7193 7234 7233 7017 + 9 7193 7194 7235 7234 7018 + 9 7194 7195 7236 7235 7019 + 9 7195 7196 7237 7236 7020 + 9 7196 7197 7238 7237 7021 + 9 7197 7198 7239 7238 7022 + 9 7198 7199 7240 7239 7023 + 9 7199 7200 7241 7240 7024 + 9 7200 7201 7242 7241 7025 + 9 7201 7202 7243 7242 7026 + 9 7202 7203 7244 7243 7027 + 9 7203 7204 7245 7244 7028 + 9 7204 7205 7246 7245 7029 + 9 7205 7206 7247 7246 7030 + 9 7206 7207 7248 7247 7031 + 9 7207 7208 7249 7248 7032 + 9 7208 7209 7250 7249 7033 + 9 7209 7210 7251 7250 7034 + 9 7210 7211 7252 7251 7035 + 9 7211 7212 7253 7252 7036 + 9 7212 7213 7254 7253 7037 + 9 7213 7214 7255 7254 7038 + 9 7214 7215 7256 7255 7039 + 9 7216 7217 7258 7257 7040 + 9 7217 7218 7259 7258 7041 + 9 7218 7219 7260 7259 7042 + 9 7219 7220 7261 7260 7043 + 9 7220 7221 7262 7261 7044 + 9 7221 7222 7263 7262 7045 + 9 7222 7223 7264 7263 7046 + 9 7223 7224 7265 7264 7047 + 9 7224 7225 7266 7265 7048 + 9 7225 7226 7267 7266 7049 + 9 7226 7227 7268 7267 7050 + 9 7227 7228 7269 7268 7051 + 9 7228 7229 7270 7269 7052 + 9 7229 7230 7271 7270 7053 + 9 7230 7231 7272 7271 7054 + 9 7231 7232 7273 7272 7055 + 9 7232 7233 7274 7273 7056 + 9 7233 7234 7275 7274 7057 + 9 7234 7235 7276 7275 7058 + 9 7235 7236 7277 7276 7059 + 9 7236 7237 7278 7277 7060 + 9 7237 7238 7279 7278 7061 + 9 7238 7239 7280 7279 7062 + 9 7239 7240 7281 7280 7063 + 9 7240 7241 7282 7281 7064 + 9 7241 7242 7283 7282 7065 + 9 7242 7243 7284 7283 7066 + 9 7243 7244 7285 7284 7067 + 9 7244 7245 7286 7285 7068 + 9 7245 7246 7287 7286 7069 + 9 7246 7247 7288 7287 7070 + 9 7247 7248 7289 7288 7071 + 9 7248 7249 7290 7289 7072 + 9 7249 7250 7291 7290 7073 + 9 7250 7251 7292 7291 7074 + 9 7251 7252 7293 7292 7075 + 9 7252 7253 7294 7293 7076 + 9 7253 7254 7295 7294 7077 + 9 7254 7255 7296 7295 7078 + 9 7255 7256 7297 7296 7079 + 9 7257 7258 7299 7298 7080 + 9 7258 7259 7300 7299 7081 + 9 7259 7260 7301 7300 7082 + 9 7260 7261 7302 7301 7083 + 9 7261 7262 7303 7302 7084 + 9 7262 7263 7304 7303 7085 + 9 7263 7264 7305 7304 7086 + 9 7264 7265 7306 7305 7087 + 9 7265 7266 7307 7306 7088 + 9 7266 7267 7308 7307 7089 + 9 7267 7268 7309 7308 7090 + 9 7268 7269 7310 7309 7091 + 9 7269 7270 7311 7310 7092 + 9 7270 7271 7312 7311 7093 + 9 7271 7272 7313 7312 7094 + 9 7272 7273 7314 7313 7095 + 9 7273 7274 7315 7314 7096 + 9 7274 7275 7316 7315 7097 + 9 7275 7276 7317 7316 7098 + 9 7276 7277 7318 7317 7099 + 9 7277 7278 7319 7318 7100 + 9 7278 7279 7320 7319 7101 + 9 7279 7280 7321 7320 7102 + 9 7280 7281 7322 7321 7103 + 9 7281 7282 7323 7322 7104 + 9 7282 7283 7324 7323 7105 + 9 7283 7284 7325 7324 7106 + 9 7284 7285 7326 7325 7107 + 9 7285 7286 7327 7326 7108 + 9 7286 7287 7328 7327 7109 + 9 7287 7288 7329 7328 7110 + 9 7288 7289 7330 7329 7111 + 9 7289 7290 7331 7330 7112 + 9 7290 7291 7332 7331 7113 + 9 7291 7292 7333 7332 7114 + 9 7292 7293 7334 7333 7115 + 9 7293 7294 7335 7334 7116 + 9 7294 7295 7336 7335 7117 + 9 7295 7296 7337 7336 7118 + 9 7296 7297 7338 7337 7119 + 9 7298 7299 7340 7339 7120 + 9 7299 7300 7341 7340 7121 + 9 7300 7301 7342 7341 7122 + 9 7301 7302 7343 7342 7123 + 9 7302 7303 7344 7343 7124 + 9 7303 7304 7345 7344 7125 + 9 7304 7305 7346 7345 7126 + 9 7305 7306 7347 7346 7127 + 9 7306 7307 7348 7347 7128 + 9 7307 7308 7349 7348 7129 + 9 7308 7309 7350 7349 7130 + 9 7309 7310 7351 7350 7131 + 9 7310 7311 7352 7351 7132 + 9 7311 7312 7353 7352 7133 + 9 7312 7313 7354 7353 7134 + 9 7313 7314 7355 7354 7135 + 9 7314 7315 7356 7355 7136 + 9 7315 7316 7357 7356 7137 + 9 7316 7317 7358 7357 7138 + 9 7317 7318 7359 7358 7139 + 9 7318 7319 7360 7359 7140 + 9 7319 7320 7361 7360 7141 + 9 7320 7321 7362 7361 7142 + 9 7321 7322 7363 7362 7143 + 9 7322 7323 7364 7363 7144 + 9 7323 7324 7365 7364 7145 + 9 7324 7325 7366 7365 7146 + 9 7325 7326 7367 7366 7147 + 9 7326 7327 7368 7367 7148 + 9 7327 7328 7369 7368 7149 + 9 7328 7329 7370 7369 7150 + 9 7329 7330 7371 7370 7151 + 9 7330 7331 7372 7371 7152 + 9 7331 7332 7373 7372 7153 + 9 7332 7333 7374 7373 7154 + 9 7333 7334 7375 7374 7155 + 9 7334 7335 7376 7375 7156 + 9 7335 7336 7377 7376 7157 + 9 7336 7337 7378 7377 7158 + 9 7337 7338 7379 7378 7159 + 9 7339 7340 7381 7380 7160 + 9 7340 7341 7382 7381 7161 + 9 7341 7342 7383 7382 7162 + 9 7342 7343 7384 7383 7163 + 9 7343 7344 7385 7384 7164 + 9 7344 7345 7386 7385 7165 + 9 7345 7346 7387 7386 7166 + 9 7346 7347 7388 7387 7167 + 9 7347 7348 7389 7388 7168 + 9 7348 7349 7390 7389 7169 + 9 7349 7350 7391 7390 7170 + 9 7350 7351 7392 7391 7171 + 9 7351 7352 7393 7392 7172 + 9 7352 7353 7394 7393 7173 + 9 7353 7354 7395 7394 7174 + 9 7354 7355 7396 7395 7175 + 9 7355 7356 7397 7396 7176 + 9 7356 7357 7398 7397 7177 + 9 7357 7358 7399 7398 7178 + 9 7358 7359 7400 7399 7179 + 9 7359 7360 7401 7400 7180 + 9 7360 7361 7402 7401 7181 + 9 7361 7362 7403 7402 7182 + 9 7362 7363 7404 7403 7183 + 9 7363 7364 7405 7404 7184 + 9 7364 7365 7406 7405 7185 + 9 7365 7366 7407 7406 7186 + 9 7366 7367 7408 7407 7187 + 9 7367 7368 7409 7408 7188 + 9 7368 7369 7410 7409 7189 + 9 7369 7370 7411 7410 7190 + 9 7370 7371 7412 7411 7191 + 9 7371 7372 7413 7412 7192 + 9 7372 7373 7414 7413 7193 + 9 7373 7374 7415 7414 7194 + 9 7374 7375 7416 7415 7195 + 9 7375 7376 7417 7416 7196 + 9 7376 7377 7418 7417 7197 + 9 7377 7378 7419 7418 7198 + 9 7378 7379 7420 7419 7199 + 9 7380 7381 7422 7421 7200 + 9 7381 7382 7423 7422 7201 + 9 7382 7383 7424 7423 7202 + 9 7383 7384 7425 7424 7203 + 9 7384 7385 7426 7425 7204 + 9 7385 7386 7427 7426 7205 + 9 7386 7387 7428 7427 7206 + 9 7387 7388 7429 7428 7207 + 9 7388 7389 7430 7429 7208 + 9 7389 7390 7431 7430 7209 + 9 7390 7391 7432 7431 7210 + 9 7391 7392 7433 7432 7211 + 9 7392 7393 7434 7433 7212 + 9 7393 7394 7435 7434 7213 + 9 7394 7395 7436 7435 7214 + 9 7395 7396 7437 7436 7215 + 9 7396 7397 7438 7437 7216 + 9 7397 7398 7439 7438 7217 + 9 7398 7399 7440 7439 7218 + 9 7399 7400 7441 7440 7219 + 9 7400 7401 7442 7441 7220 + 9 7401 7402 7443 7442 7221 + 9 7402 7403 7444 7443 7222 + 9 7403 7404 7445 7444 7223 + 9 7404 7405 7446 7445 7224 + 9 7405 7406 7447 7446 7225 + 9 7406 7407 7448 7447 7226 + 9 7407 7408 7449 7448 7227 + 9 7408 7409 7450 7449 7228 + 9 7409 7410 7451 7450 7229 + 9 7410 7411 7452 7451 7230 + 9 7411 7412 7453 7452 7231 + 9 7412 7413 7454 7453 7232 + 9 7413 7414 7455 7454 7233 + 9 7414 7415 7456 7455 7234 + 9 7415 7416 7457 7456 7235 + 9 7416 7417 7458 7457 7236 + 9 7417 7418 7459 7458 7237 + 9 7418 7419 7460 7459 7238 + 9 7419 7420 7461 7460 7239 + 9 7421 7422 7463 7462 7240 + 9 7422 7423 7464 7463 7241 + 9 7423 7424 7465 7464 7242 + 9 7424 7425 7466 7465 7243 + 9 7425 7426 7467 7466 7244 + 9 7426 7427 7468 7467 7245 + 9 7427 7428 7469 7468 7246 + 9 7428 7429 7470 7469 7247 + 9 7429 7430 7471 7470 7248 + 9 7430 7431 7472 7471 7249 + 9 7431 7432 7473 7472 7250 + 9 7432 7433 7474 7473 7251 + 9 7433 7434 7475 7474 7252 + 9 7434 7435 7476 7475 7253 + 9 7435 7436 7477 7476 7254 + 9 7436 7437 7478 7477 7255 + 9 7437 7438 7479 7478 7256 + 9 7438 7439 7480 7479 7257 + 9 7439 7440 7481 7480 7258 + 9 7440 7441 7482 7481 7259 + 9 7441 7442 7483 7482 7260 + 9 7442 7443 7484 7483 7261 + 9 7443 7444 7485 7484 7262 + 9 7444 7445 7486 7485 7263 + 9 7445 7446 7487 7486 7264 + 9 7446 7447 7488 7487 7265 + 9 7447 7448 7489 7488 7266 + 9 7448 7449 7490 7489 7267 + 9 7449 7450 7491 7490 7268 + 9 7450 7451 7492 7491 7269 + 9 7451 7452 7493 7492 7270 + 9 7452 7453 7494 7493 7271 + 9 7453 7454 7495 7494 7272 + 9 7454 7455 7496 7495 7273 + 9 7455 7456 7497 7496 7274 + 9 7456 7457 7498 7497 7275 + 9 7457 7458 7499 7498 7276 + 9 7458 7459 7500 7499 7277 + 9 7459 7460 7501 7500 7278 + 9 7460 7461 7502 7501 7279 + 9 7462 7463 7504 7503 7280 + 9 7463 7464 7505 7504 7281 + 9 7464 7465 7506 7505 7282 + 9 7465 7466 7507 7506 7283 + 9 7466 7467 7508 7507 7284 + 9 7467 7468 7509 7508 7285 + 9 7468 7469 7510 7509 7286 + 9 7469 7470 7511 7510 7287 + 9 7470 7471 7512 7511 7288 + 9 7471 7472 7513 7512 7289 + 9 7472 7473 7514 7513 7290 + 9 7473 7474 7515 7514 7291 + 9 7474 7475 7516 7515 7292 + 9 7475 7476 7517 7516 7293 + 9 7476 7477 7518 7517 7294 + 9 7477 7478 7519 7518 7295 + 9 7478 7479 7520 7519 7296 + 9 7479 7480 7521 7520 7297 + 9 7480 7481 7522 7521 7298 + 9 7481 7482 7523 7522 7299 + 9 7482 7483 7524 7523 7300 + 9 7483 7484 7525 7524 7301 + 9 7484 7485 7526 7525 7302 + 9 7485 7486 7527 7526 7303 + 9 7486 7487 7528 7527 7304 + 9 7487 7488 7529 7528 7305 + 9 7488 7489 7530 7529 7306 + 9 7489 7490 7531 7530 7307 + 9 7490 7491 7532 7531 7308 + 9 7491 7492 7533 7532 7309 + 9 7492 7493 7534 7533 7310 + 9 7493 7494 7535 7534 7311 + 9 7494 7495 7536 7535 7312 + 9 7495 7496 7537 7536 7313 + 9 7496 7497 7538 7537 7314 + 9 7497 7498 7539 7538 7315 + 9 7498 7499 7540 7539 7316 + 9 7499 7500 7541 7540 7317 + 9 7500 7501 7542 7541 7318 + 9 7501 7502 7543 7542 7319 + 9 7503 7504 7545 7544 7320 + 9 7504 7505 7546 7545 7321 + 9 7505 7506 7547 7546 7322 + 9 7506 7507 7548 7547 7323 + 9 7507 7508 7549 7548 7324 + 9 7508 7509 7550 7549 7325 + 9 7509 7510 7551 7550 7326 + 9 7510 7511 7552 7551 7327 + 9 7511 7512 7553 7552 7328 + 9 7512 7513 7554 7553 7329 + 9 7513 7514 7555 7554 7330 + 9 7514 7515 7556 7555 7331 + 9 7515 7516 7557 7556 7332 + 9 7516 7517 7558 7557 7333 + 9 7517 7518 7559 7558 7334 + 9 7518 7519 7560 7559 7335 + 9 7519 7520 7561 7560 7336 + 9 7520 7521 7562 7561 7337 + 9 7521 7522 7563 7562 7338 + 9 7522 7523 7564 7563 7339 + 9 7523 7524 7565 7564 7340 + 9 7524 7525 7566 7565 7341 + 9 7525 7526 7567 7566 7342 + 9 7526 7527 7568 7567 7343 + 9 7527 7528 7569 7568 7344 + 9 7528 7529 7570 7569 7345 + 9 7529 7530 7571 7570 7346 + 9 7530 7531 7572 7571 7347 + 9 7531 7532 7573 7572 7348 + 9 7532 7533 7574 7573 7349 + 9 7533 7534 7575 7574 7350 + 9 7534 7535 7576 7575 7351 + 9 7535 7536 7577 7576 7352 + 9 7536 7537 7578 7577 7353 + 9 7537 7538 7579 7578 7354 + 9 7538 7539 7580 7579 7355 + 9 7539 7540 7581 7580 7356 + 9 7540 7541 7582 7581 7357 + 9 7541 7542 7583 7582 7358 + 9 7542 7543 7584 7583 7359 + 9 7544 7545 7586 7585 7360 + 9 7545 7546 7587 7586 7361 + 9 7546 7547 7588 7587 7362 + 9 7547 7548 7589 7588 7363 + 9 7548 7549 7590 7589 7364 + 9 7549 7550 7591 7590 7365 + 9 7550 7551 7592 7591 7366 + 9 7551 7552 7593 7592 7367 + 9 7552 7553 7594 7593 7368 + 9 7553 7554 7595 7594 7369 + 9 7554 7555 7596 7595 7370 + 9 7555 7556 7597 7596 7371 + 9 7556 7557 7598 7597 7372 + 9 7557 7558 7599 7598 7373 + 9 7558 7559 7600 7599 7374 + 9 7559 7560 7601 7600 7375 + 9 7560 7561 7602 7601 7376 + 9 7561 7562 7603 7602 7377 + 9 7562 7563 7604 7603 7378 + 9 7563 7564 7605 7604 7379 + 9 7564 7565 7606 7605 7380 + 9 7565 7566 7607 7606 7381 + 9 7566 7567 7608 7607 7382 + 9 7567 7568 7609 7608 7383 + 9 7568 7569 7610 7609 7384 + 9 7569 7570 7611 7610 7385 + 9 7570 7571 7612 7611 7386 + 9 7571 7572 7613 7612 7387 + 9 7572 7573 7614 7613 7388 + 9 7573 7574 7615 7614 7389 + 9 7574 7575 7616 7615 7390 + 9 7575 7576 7617 7616 7391 + 9 7576 7577 7618 7617 7392 + 9 7577 7578 7619 7618 7393 + 9 7578 7579 7620 7619 7394 + 9 7579 7580 7621 7620 7395 + 9 7580 7581 7622 7621 7396 + 9 7581 7582 7623 7622 7397 + 9 7582 7583 7624 7623 7398 + 9 7583 7584 7625 7624 7399 + 9 7585 7586 7627 7626 7400 + 9 7586 7587 7628 7627 7401 + 9 7587 7588 7629 7628 7402 + 9 7588 7589 7630 7629 7403 + 9 7589 7590 7631 7630 7404 + 9 7590 7591 7632 7631 7405 + 9 7591 7592 7633 7632 7406 + 9 7592 7593 7634 7633 7407 + 9 7593 7594 7635 7634 7408 + 9 7594 7595 7636 7635 7409 + 9 7595 7596 7637 7636 7410 + 9 7596 7597 7638 7637 7411 + 9 7597 7598 7639 7638 7412 + 9 7598 7599 7640 7639 7413 + 9 7599 7600 7641 7640 7414 + 9 7600 7601 7642 7641 7415 + 9 7601 7602 7643 7642 7416 + 9 7602 7603 7644 7643 7417 + 9 7603 7604 7645 7644 7418 + 9 7604 7605 7646 7645 7419 + 9 7605 7606 7647 7646 7420 + 9 7606 7607 7648 7647 7421 + 9 7607 7608 7649 7648 7422 + 9 7608 7609 7650 7649 7423 + 9 7609 7610 7651 7650 7424 + 9 7610 7611 7652 7651 7425 + 9 7611 7612 7653 7652 7426 + 9 7612 7613 7654 7653 7427 + 9 7613 7614 7655 7654 7428 + 9 7614 7615 7656 7655 7429 + 9 7615 7616 7657 7656 7430 + 9 7616 7617 7658 7657 7431 + 9 7617 7618 7659 7658 7432 + 9 7618 7619 7660 7659 7433 + 9 7619 7620 7661 7660 7434 + 9 7620 7621 7662 7661 7435 + 9 7621 7622 7663 7662 7436 + 9 7622 7623 7664 7663 7437 + 9 7623 7624 7665 7664 7438 + 9 7624 7625 7666 7665 7439 + 9 7626 7627 7668 7667 7440 + 9 7627 7628 7669 7668 7441 + 9 7628 7629 7670 7669 7442 + 9 7629 7630 7671 7670 7443 + 9 7630 7631 7672 7671 7444 + 9 7631 7632 7673 7672 7445 + 9 7632 7633 7674 7673 7446 + 9 7633 7634 7675 7674 7447 + 9 7634 7635 7676 7675 7448 + 9 7635 7636 7677 7676 7449 + 9 7636 7637 7678 7677 7450 + 9 7637 7638 7679 7678 7451 + 9 7638 7639 7680 7679 7452 + 9 7639 7640 7681 7680 7453 + 9 7640 7641 7682 7681 7454 + 9 7641 7642 7683 7682 7455 + 9 7642 7643 7684 7683 7456 + 9 7643 7644 7685 7684 7457 + 9 7644 7645 7686 7685 7458 + 9 7645 7646 7687 7686 7459 + 9 7646 7647 7688 7687 7460 + 9 7647 7648 7689 7688 7461 + 9 7648 7649 7690 7689 7462 + 9 7649 7650 7691 7690 7463 + 9 7650 7651 7692 7691 7464 + 9 7651 7652 7693 7692 7465 + 9 7652 7653 7694 7693 7466 + 9 7653 7654 7695 7694 7467 + 9 7654 7655 7696 7695 7468 + 9 7655 7656 7697 7696 7469 + 9 7656 7657 7698 7697 7470 + 9 7657 7658 7699 7698 7471 + 9 7658 7659 7700 7699 7472 + 9 7659 7660 7701 7700 7473 + 9 7660 7661 7702 7701 7474 + 9 7661 7662 7703 7702 7475 + 9 7662 7663 7704 7703 7476 + 9 7663 7664 7705 7704 7477 + 9 7664 7665 7706 7705 7478 + 9 7665 7666 7707 7706 7479 + 9 7667 7668 7709 7708 7480 + 9 7668 7669 7710 7709 7481 + 9 7669 7670 7711 7710 7482 + 9 7670 7671 7712 7711 7483 + 9 7671 7672 7713 7712 7484 + 9 7672 7673 7714 7713 7485 + 9 7673 7674 7715 7714 7486 + 9 7674 7675 7716 7715 7487 + 9 7675 7676 7717 7716 7488 + 9 7676 7677 7718 7717 7489 + 9 7677 7678 7719 7718 7490 + 9 7678 7679 7720 7719 7491 + 9 7679 7680 7721 7720 7492 + 9 7680 7681 7722 7721 7493 + 9 7681 7682 7723 7722 7494 + 9 7682 7683 7724 7723 7495 + 9 7683 7684 7725 7724 7496 + 9 7684 7685 7726 7725 7497 + 9 7685 7686 7727 7726 7498 + 9 7686 7687 7728 7727 7499 + 9 7687 7688 7729 7728 7500 + 9 7688 7689 7730 7729 7501 + 9 7689 7690 7731 7730 7502 + 9 7690 7691 7732 7731 7503 + 9 7691 7692 7733 7732 7504 + 9 7692 7693 7734 7733 7505 + 9 7693 7694 7735 7734 7506 + 9 7694 7695 7736 7735 7507 + 9 7695 7696 7737 7736 7508 + 9 7696 7697 7738 7737 7509 + 9 7697 7698 7739 7738 7510 + 9 7698 7699 7740 7739 7511 + 9 7699 7700 7741 7740 7512 + 9 7700 7701 7742 7741 7513 + 9 7701 7702 7743 7742 7514 + 9 7702 7703 7744 7743 7515 + 9 7703 7704 7745 7744 7516 + 9 7704 7705 7746 7745 7517 + 9 7705 7706 7747 7746 7518 + 9 7706 7707 7748 7747 7519 + 9 7708 7709 7750 7749 7520 + 9 7709 7710 7751 7750 7521 + 9 7710 7711 7752 7751 7522 + 9 7711 7712 7753 7752 7523 + 9 7712 7713 7754 7753 7524 + 9 7713 7714 7755 7754 7525 + 9 7714 7715 7756 7755 7526 + 9 7715 7716 7757 7756 7527 + 9 7716 7717 7758 7757 7528 + 9 7717 7718 7759 7758 7529 + 9 7718 7719 7760 7759 7530 + 9 7719 7720 7761 7760 7531 + 9 7720 7721 7762 7761 7532 + 9 7721 7722 7763 7762 7533 + 9 7722 7723 7764 7763 7534 + 9 7723 7724 7765 7764 7535 + 9 7724 7725 7766 7765 7536 + 9 7725 7726 7767 7766 7537 + 9 7726 7727 7768 7767 7538 + 9 7727 7728 7769 7768 7539 + 9 7728 7729 7770 7769 7540 + 9 7729 7730 7771 7770 7541 + 9 7730 7731 7772 7771 7542 + 9 7731 7732 7773 7772 7543 + 9 7732 7733 7774 7773 7544 + 9 7733 7734 7775 7774 7545 + 9 7734 7735 7776 7775 7546 + 9 7735 7736 7777 7776 7547 + 9 7736 7737 7778 7777 7548 + 9 7737 7738 7779 7778 7549 + 9 7738 7739 7780 7779 7550 + 9 7739 7740 7781 7780 7551 + 9 7740 7741 7782 7781 7552 + 9 7741 7742 7783 7782 7553 + 9 7742 7743 7784 7783 7554 + 9 7743 7744 7785 7784 7555 + 9 7744 7745 7786 7785 7556 + 9 7745 7746 7787 7786 7557 + 9 7746 7747 7788 7787 7558 + 9 7747 7748 7789 7788 7559 + 9 7749 7750 7791 7790 7560 + 9 7750 7751 7792 7791 7561 + 9 7751 7752 7793 7792 7562 + 9 7752 7753 7794 7793 7563 + 9 7753 7754 7795 7794 7564 + 9 7754 7755 7796 7795 7565 + 9 7755 7756 7797 7796 7566 + 9 7756 7757 7798 7797 7567 + 9 7757 7758 7799 7798 7568 + 9 7758 7759 7800 7799 7569 + 9 7759 7760 7801 7800 7570 + 9 7760 7761 7802 7801 7571 + 9 7761 7762 7803 7802 7572 + 9 7762 7763 7804 7803 7573 + 9 7763 7764 7805 7804 7574 + 9 7764 7765 7806 7805 7575 + 9 7765 7766 7807 7806 7576 + 9 7766 7767 7808 7807 7577 + 9 7767 7768 7809 7808 7578 + 9 7768 7769 7810 7809 7579 + 9 7769 7770 7811 7810 7580 + 9 7770 7771 7812 7811 7581 + 9 7771 7772 7813 7812 7582 + 9 7772 7773 7814 7813 7583 + 9 7773 7774 7815 7814 7584 + 9 7774 7775 7816 7815 7585 + 9 7775 7776 7817 7816 7586 + 9 7776 7777 7818 7817 7587 + 9 7777 7778 7819 7818 7588 + 9 7778 7779 7820 7819 7589 + 9 7779 7780 7821 7820 7590 + 9 7780 7781 7822 7821 7591 + 9 7781 7782 7823 7822 7592 + 9 7782 7783 7824 7823 7593 + 9 7783 7784 7825 7824 7594 + 9 7784 7785 7826 7825 7595 + 9 7785 7786 7827 7826 7596 + 9 7786 7787 7828 7827 7597 + 9 7787 7788 7829 7828 7598 + 9 7788 7789 7830 7829 7599 + 9 7790 7791 7832 7831 7600 + 9 7791 7792 7833 7832 7601 + 9 7792 7793 7834 7833 7602 + 9 7793 7794 7835 7834 7603 + 9 7794 7795 7836 7835 7604 + 9 7795 7796 7837 7836 7605 + 9 7796 7797 7838 7837 7606 + 9 7797 7798 7839 7838 7607 + 9 7798 7799 7840 7839 7608 + 9 7799 7800 7841 7840 7609 + 9 7800 7801 7842 7841 7610 + 9 7801 7802 7843 7842 7611 + 9 7802 7803 7844 7843 7612 + 9 7803 7804 7845 7844 7613 + 9 7804 7805 7846 7845 7614 + 9 7805 7806 7847 7846 7615 + 9 7806 7807 7848 7847 7616 + 9 7807 7808 7849 7848 7617 + 9 7808 7809 7850 7849 7618 + 9 7809 7810 7851 7850 7619 + 9 7810 7811 7852 7851 7620 + 9 7811 7812 7853 7852 7621 + 9 7812 7813 7854 7853 7622 + 9 7813 7814 7855 7854 7623 + 9 7814 7815 7856 7855 7624 + 9 7815 7816 7857 7856 7625 + 9 7816 7817 7858 7857 7626 + 9 7817 7818 7859 7858 7627 + 9 7818 7819 7860 7859 7628 + 9 7819 7820 7861 7860 7629 + 9 7820 7821 7862 7861 7630 + 9 7821 7822 7863 7862 7631 + 9 7822 7823 7864 7863 7632 + 9 7823 7824 7865 7864 7633 + 9 7824 7825 7866 7865 7634 + 9 7825 7826 7867 7866 7635 + 9 7826 7827 7868 7867 7636 + 9 7827 7828 7869 7868 7637 + 9 7828 7829 7870 7869 7638 + 9 7829 7830 7871 7870 7639 + 9 7831 7832 7873 7872 7640 + 9 7832 7833 7874 7873 7641 + 9 7833 7834 7875 7874 7642 + 9 7834 7835 7876 7875 7643 + 9 7835 7836 7877 7876 7644 + 9 7836 7837 7878 7877 7645 + 9 7837 7838 7879 7878 7646 + 9 7838 7839 7880 7879 7647 + 9 7839 7840 7881 7880 7648 + 9 7840 7841 7882 7881 7649 + 9 7841 7842 7883 7882 7650 + 9 7842 7843 7884 7883 7651 + 9 7843 7844 7885 7884 7652 + 9 7844 7845 7886 7885 7653 + 9 7845 7846 7887 7886 7654 + 9 7846 7847 7888 7887 7655 + 9 7847 7848 7889 7888 7656 + 9 7848 7849 7890 7889 7657 + 9 7849 7850 7891 7890 7658 + 9 7850 7851 7892 7891 7659 + 9 7851 7852 7893 7892 7660 + 9 7852 7853 7894 7893 7661 + 9 7853 7854 7895 7894 7662 + 9 7854 7855 7896 7895 7663 + 9 7855 7856 7897 7896 7664 + 9 7856 7857 7898 7897 7665 + 9 7857 7858 7899 7898 7666 + 9 7858 7859 7900 7899 7667 + 9 7859 7860 7901 7900 7668 + 9 7860 7861 7902 7901 7669 + 9 7861 7862 7903 7902 7670 + 9 7862 7863 7904 7903 7671 + 9 7863 7864 7905 7904 7672 + 9 7864 7865 7906 7905 7673 + 9 7865 7866 7907 7906 7674 + 9 7866 7867 7908 7907 7675 + 9 7867 7868 7909 7908 7676 + 9 7868 7869 7910 7909 7677 + 9 7869 7870 7911 7910 7678 + 9 7870 7871 7912 7911 7679 + 9 7872 7873 7914 7913 7680 + 9 7873 7874 7915 7914 7681 + 9 7874 7875 7916 7915 7682 + 9 7875 7876 7917 7916 7683 + 9 7876 7877 7918 7917 7684 + 9 7877 7878 7919 7918 7685 + 9 7878 7879 7920 7919 7686 + 9 7879 7880 7921 7920 7687 + 9 7880 7881 7922 7921 7688 + 9 7881 7882 7923 7922 7689 + 9 7882 7883 7924 7923 7690 + 9 7883 7884 7925 7924 7691 + 9 7884 7885 7926 7925 7692 + 9 7885 7886 7927 7926 7693 + 9 7886 7887 7928 7927 7694 + 9 7887 7888 7929 7928 7695 + 9 7888 7889 7930 7929 7696 + 9 7889 7890 7931 7930 7697 + 9 7890 7891 7932 7931 7698 + 9 7891 7892 7933 7932 7699 + 9 7892 7893 7934 7933 7700 + 9 7893 7894 7935 7934 7701 + 9 7894 7895 7936 7935 7702 + 9 7895 7896 7937 7936 7703 + 9 7896 7897 7938 7937 7704 + 9 7897 7898 7939 7938 7705 + 9 7898 7899 7940 7939 7706 + 9 7899 7900 7941 7940 7707 + 9 7900 7901 7942 7941 7708 + 9 7901 7902 7943 7942 7709 + 9 7902 7903 7944 7943 7710 + 9 7903 7904 7945 7944 7711 + 9 7904 7905 7946 7945 7712 + 9 7905 7906 7947 7946 7713 + 9 7906 7907 7948 7947 7714 + 9 7907 7908 7949 7948 7715 + 9 7908 7909 7950 7949 7716 + 9 7909 7910 7951 7950 7717 + 9 7910 7911 7952 7951 7718 + 9 7911 7912 7953 7952 7719 + 9 7913 7914 7955 7954 7720 + 9 7914 7915 7956 7955 7721 + 9 7915 7916 7957 7956 7722 + 9 7916 7917 7958 7957 7723 + 9 7917 7918 7959 7958 7724 + 9 7918 7919 7960 7959 7725 + 9 7919 7920 7961 7960 7726 + 9 7920 7921 7962 7961 7727 + 9 7921 7922 7963 7962 7728 + 9 7922 7923 7964 7963 7729 + 9 7923 7924 7965 7964 7730 + 9 7924 7925 7966 7965 7731 + 9 7925 7926 7967 7966 7732 + 9 7926 7927 7968 7967 7733 + 9 7927 7928 7969 7968 7734 + 9 7928 7929 7970 7969 7735 + 9 7929 7930 7971 7970 7736 + 9 7930 7931 7972 7971 7737 + 9 7931 7932 7973 7972 7738 + 9 7932 7933 7974 7973 7739 + 9 7933 7934 7975 7974 7740 + 9 7934 7935 7976 7975 7741 + 9 7935 7936 7977 7976 7742 + 9 7936 7937 7978 7977 7743 + 9 7937 7938 7979 7978 7744 + 9 7938 7939 7980 7979 7745 + 9 7939 7940 7981 7980 7746 + 9 7940 7941 7982 7981 7747 + 9 7941 7942 7983 7982 7748 + 9 7942 7943 7984 7983 7749 + 9 7943 7944 7985 7984 7750 + 9 7944 7945 7986 7985 7751 + 9 7945 7946 7987 7986 7752 + 9 7946 7947 7988 7987 7753 + 9 7947 7948 7989 7988 7754 + 9 7948 7949 7990 7989 7755 + 9 7949 7950 7991 7990 7756 + 9 7950 7951 7992 7991 7757 + 9 7951 7952 7993 7992 7758 + 9 7952 7953 7994 7993 7759 + 9 7954 7955 7996 7995 7760 + 9 7955 7956 7997 7996 7761 + 9 7956 7957 7998 7997 7762 + 9 7957 7958 7999 7998 7763 + 9 7958 7959 8000 7999 7764 + 9 7959 7960 8001 8000 7765 + 9 7960 7961 8002 8001 7766 + 9 7961 7962 8003 8002 7767 + 9 7962 7963 8004 8003 7768 + 9 7963 7964 8005 8004 7769 + 9 7964 7965 8006 8005 7770 + 9 7965 7966 8007 8006 7771 + 9 7966 7967 8008 8007 7772 + 9 7967 7968 8009 8008 7773 + 9 7968 7969 8010 8009 7774 + 9 7969 7970 8011 8010 7775 + 9 7970 7971 8012 8011 7776 + 9 7971 7972 8013 8012 7777 + 9 7972 7973 8014 8013 7778 + 9 7973 7974 8015 8014 7779 + 9 7974 7975 8016 8015 7780 + 9 7975 7976 8017 8016 7781 + 9 7976 7977 8018 8017 7782 + 9 7977 7978 8019 8018 7783 + 9 7978 7979 8020 8019 7784 + 9 7979 7980 8021 8020 7785 + 9 7980 7981 8022 8021 7786 + 9 7981 7982 8023 8022 7787 + 9 7982 7983 8024 8023 7788 + 9 7983 7984 8025 8024 7789 + 9 7984 7985 8026 8025 7790 + 9 7985 7986 8027 8026 7791 + 9 7986 7987 8028 8027 7792 + 9 7987 7988 8029 8028 7793 + 9 7988 7989 8030 8029 7794 + 9 7989 7990 8031 8030 7795 + 9 7990 7991 8032 8031 7796 + 9 7991 7992 8033 8032 7797 + 9 7992 7993 8034 8033 7798 + 9 7993 7994 8035 8034 7799 + 9 7995 7996 8037 8036 7800 + 9 7996 7997 8038 8037 7801 + 9 7997 7998 8039 8038 7802 + 9 7998 7999 8040 8039 7803 + 9 7999 8000 8041 8040 7804 + 9 8000 8001 8042 8041 7805 + 9 8001 8002 8043 8042 7806 + 9 8002 8003 8044 8043 7807 + 9 8003 8004 8045 8044 7808 + 9 8004 8005 8046 8045 7809 + 9 8005 8006 8047 8046 7810 + 9 8006 8007 8048 8047 7811 + 9 8007 8008 8049 8048 7812 + 9 8008 8009 8050 8049 7813 + 9 8009 8010 8051 8050 7814 + 9 8010 8011 8052 8051 7815 + 9 8011 8012 8053 8052 7816 + 9 8012 8013 8054 8053 7817 + 9 8013 8014 8055 8054 7818 + 9 8014 8015 8056 8055 7819 + 9 8015 8016 8057 8056 7820 + 9 8016 8017 8058 8057 7821 + 9 8017 8018 8059 8058 7822 + 9 8018 8019 8060 8059 7823 + 9 8019 8020 8061 8060 7824 + 9 8020 8021 8062 8061 7825 + 9 8021 8022 8063 8062 7826 + 9 8022 8023 8064 8063 7827 + 9 8023 8024 8065 8064 7828 + 9 8024 8025 8066 8065 7829 + 9 8025 8026 8067 8066 7830 + 9 8026 8027 8068 8067 7831 + 9 8027 8028 8069 8068 7832 + 9 8028 8029 8070 8069 7833 + 9 8029 8030 8071 8070 7834 + 9 8030 8031 8072 8071 7835 + 9 8031 8032 8073 8072 7836 + 9 8032 8033 8074 8073 7837 + 9 8033 8034 8075 8074 7838 + 9 8034 8035 8076 8075 7839 + 9 8036 8037 8078 8077 7840 + 9 8037 8038 8079 8078 7841 + 9 8038 8039 8080 8079 7842 + 9 8039 8040 8081 8080 7843 + 9 8040 8041 8082 8081 7844 + 9 8041 8042 8083 8082 7845 + 9 8042 8043 8084 8083 7846 + 9 8043 8044 8085 8084 7847 + 9 8044 8045 8086 8085 7848 + 9 8045 8046 8087 8086 7849 + 9 8046 8047 8088 8087 7850 + 9 8047 8048 8089 8088 7851 + 9 8048 8049 8090 8089 7852 + 9 8049 8050 8091 8090 7853 + 9 8050 8051 8092 8091 7854 + 9 8051 8052 8093 8092 7855 + 9 8052 8053 8094 8093 7856 + 9 8053 8054 8095 8094 7857 + 9 8054 8055 8096 8095 7858 + 9 8055 8056 8097 8096 7859 + 9 8056 8057 8098 8097 7860 + 9 8057 8058 8099 8098 7861 + 9 8058 8059 8100 8099 7862 + 9 8059 8060 8101 8100 7863 + 9 8060 8061 8102 8101 7864 + 9 8061 8062 8103 8102 7865 + 9 8062 8063 8104 8103 7866 + 9 8063 8064 8105 8104 7867 + 9 8064 8065 8106 8105 7868 + 9 8065 8066 8107 8106 7869 + 9 8066 8067 8108 8107 7870 + 9 8067 8068 8109 8108 7871 + 9 8068 8069 8110 8109 7872 + 9 8069 8070 8111 8110 7873 + 9 8070 8071 8112 8111 7874 + 9 8071 8072 8113 8112 7875 + 9 8072 8073 8114 8113 7876 + 9 8073 8074 8115 8114 7877 + 9 8074 8075 8116 8115 7878 + 9 8075 8076 8117 8116 7879 + 9 8077 8078 8119 8118 7880 + 9 8078 8079 8120 8119 7881 + 9 8079 8080 8121 8120 7882 + 9 8080 8081 8122 8121 7883 + 9 8081 8082 8123 8122 7884 + 9 8082 8083 8124 8123 7885 + 9 8083 8084 8125 8124 7886 + 9 8084 8085 8126 8125 7887 + 9 8085 8086 8127 8126 7888 + 9 8086 8087 8128 8127 7889 + 9 8087 8088 8129 8128 7890 + 9 8088 8089 8130 8129 7891 + 9 8089 8090 8131 8130 7892 + 9 8090 8091 8132 8131 7893 + 9 8091 8092 8133 8132 7894 + 9 8092 8093 8134 8133 7895 + 9 8093 8094 8135 8134 7896 + 9 8094 8095 8136 8135 7897 + 9 8095 8096 8137 8136 7898 + 9 8096 8097 8138 8137 7899 + 9 8097 8098 8139 8138 7900 + 9 8098 8099 8140 8139 7901 + 9 8099 8100 8141 8140 7902 + 9 8100 8101 8142 8141 7903 + 9 8101 8102 8143 8142 7904 + 9 8102 8103 8144 8143 7905 + 9 8103 8104 8145 8144 7906 + 9 8104 8105 8146 8145 7907 + 9 8105 8106 8147 8146 7908 + 9 8106 8107 8148 8147 7909 + 9 8107 8108 8149 8148 7910 + 9 8108 8109 8150 8149 7911 + 9 8109 8110 8151 8150 7912 + 9 8110 8111 8152 8151 7913 + 9 8111 8112 8153 8152 7914 + 9 8112 8113 8154 8153 7915 + 9 8113 8114 8155 8154 7916 + 9 8114 8115 8156 8155 7917 + 9 8115 8116 8157 8156 7918 + 9 8116 8117 8158 8157 7919 + 9 8118 8119 8160 8159 7920 + 9 8119 8120 8161 8160 7921 + 9 8120 8121 8162 8161 7922 + 9 8121 8122 8163 8162 7923 + 9 8122 8123 8164 8163 7924 + 9 8123 8124 8165 8164 7925 + 9 8124 8125 8166 8165 7926 + 9 8125 8126 8167 8166 7927 + 9 8126 8127 8168 8167 7928 + 9 8127 8128 8169 8168 7929 + 9 8128 8129 8170 8169 7930 + 9 8129 8130 8171 8170 7931 + 9 8130 8131 8172 8171 7932 + 9 8131 8132 8173 8172 7933 + 9 8132 8133 8174 8173 7934 + 9 8133 8134 8175 8174 7935 + 9 8134 8135 8176 8175 7936 + 9 8135 8136 8177 8176 7937 + 9 8136 8137 8178 8177 7938 + 9 8137 8138 8179 8178 7939 + 9 8138 8139 8180 8179 7940 + 9 8139 8140 8181 8180 7941 + 9 8140 8141 8182 8181 7942 + 9 8141 8142 8183 8182 7943 + 9 8142 8143 8184 8183 7944 + 9 8143 8144 8185 8184 7945 + 9 8144 8145 8186 8185 7946 + 9 8145 8146 8187 8186 7947 + 9 8146 8147 8188 8187 7948 + 9 8147 8148 8189 8188 7949 + 9 8148 8149 8190 8189 7950 + 9 8149 8150 8191 8190 7951 + 9 8150 8151 8192 8191 7952 + 9 8151 8152 8193 8192 7953 + 9 8152 8153 8194 8193 7954 + 9 8153 8154 8195 8194 7955 + 9 8154 8155 8196 8195 7956 + 9 8155 8156 8197 8196 7957 + 9 8156 8157 8198 8197 7958 + 9 8157 8158 8199 8198 7959 + 9 8159 8160 8201 8200 7960 + 9 8160 8161 8202 8201 7961 + 9 8161 8162 8203 8202 7962 + 9 8162 8163 8204 8203 7963 + 9 8163 8164 8205 8204 7964 + 9 8164 8165 8206 8205 7965 + 9 8165 8166 8207 8206 7966 + 9 8166 8167 8208 8207 7967 + 9 8167 8168 8209 8208 7968 + 9 8168 8169 8210 8209 7969 + 9 8169 8170 8211 8210 7970 + 9 8170 8171 8212 8211 7971 + 9 8171 8172 8213 8212 7972 + 9 8172 8173 8214 8213 7973 + 9 8173 8174 8215 8214 7974 + 9 8174 8175 8216 8215 7975 + 9 8175 8176 8217 8216 7976 + 9 8176 8177 8218 8217 7977 + 9 8177 8178 8219 8218 7978 + 9 8178 8179 8220 8219 7979 + 9 8179 8180 8221 8220 7980 + 9 8180 8181 8222 8221 7981 + 9 8181 8182 8223 8222 7982 + 9 8182 8183 8224 8223 7983 + 9 8183 8184 8225 8224 7984 + 9 8184 8185 8226 8225 7985 + 9 8185 8186 8227 8226 7986 + 9 8186 8187 8228 8227 7987 + 9 8187 8188 8229 8228 7988 + 9 8188 8189 8230 8229 7989 + 9 8189 8190 8231 8230 7990 + 9 8190 8191 8232 8231 7991 + 9 8191 8192 8233 8232 7992 + 9 8192 8193 8234 8233 7993 + 9 8193 8194 8235 8234 7994 + 9 8194 8195 8236 8235 7995 + 9 8195 8196 8237 8236 7996 + 9 8196 8197 8238 8237 7997 + 9 8197 8198 8239 8238 7998 + 9 8198 8199 8240 8239 7999 + 9 8200 8201 8242 8241 8000 + 9 8201 8202 8243 8242 8001 + 9 8202 8203 8244 8243 8002 + 9 8203 8204 8245 8244 8003 + 9 8204 8205 8246 8245 8004 + 9 8205 8206 8247 8246 8005 + 9 8206 8207 8248 8247 8006 + 9 8207 8208 8249 8248 8007 + 9 8208 8209 8250 8249 8008 + 9 8209 8210 8251 8250 8009 + 9 8210 8211 8252 8251 8010 + 9 8211 8212 8253 8252 8011 + 9 8212 8213 8254 8253 8012 + 9 8213 8214 8255 8254 8013 + 9 8214 8215 8256 8255 8014 + 9 8215 8216 8257 8256 8015 + 9 8216 8217 8258 8257 8016 + 9 8217 8218 8259 8258 8017 + 9 8218 8219 8260 8259 8018 + 9 8219 8220 8261 8260 8019 + 9 8220 8221 8262 8261 8020 + 9 8221 8222 8263 8262 8021 + 9 8222 8223 8264 8263 8022 + 9 8223 8224 8265 8264 8023 + 9 8224 8225 8266 8265 8024 + 9 8225 8226 8267 8266 8025 + 9 8226 8227 8268 8267 8026 + 9 8227 8228 8269 8268 8027 + 9 8228 8229 8270 8269 8028 + 9 8229 8230 8271 8270 8029 + 9 8230 8231 8272 8271 8030 + 9 8231 8232 8273 8272 8031 + 9 8232 8233 8274 8273 8032 + 9 8233 8234 8275 8274 8033 + 9 8234 8235 8276 8275 8034 + 9 8235 8236 8277 8276 8035 + 9 8236 8237 8278 8277 8036 + 9 8237 8238 8279 8278 8037 + 9 8238 8239 8280 8279 8038 + 9 8239 8240 8281 8280 8039 + 9 8241 8242 8283 8282 8040 + 9 8242 8243 8284 8283 8041 + 9 8243 8244 8285 8284 8042 + 9 8244 8245 8286 8285 8043 + 9 8245 8246 8287 8286 8044 + 9 8246 8247 8288 8287 8045 + 9 8247 8248 8289 8288 8046 + 9 8248 8249 8290 8289 8047 + 9 8249 8250 8291 8290 8048 + 9 8250 8251 8292 8291 8049 + 9 8251 8252 8293 8292 8050 + 9 8252 8253 8294 8293 8051 + 9 8253 8254 8295 8294 8052 + 9 8254 8255 8296 8295 8053 + 9 8255 8256 8297 8296 8054 + 9 8256 8257 8298 8297 8055 + 9 8257 8258 8299 8298 8056 + 9 8258 8259 8300 8299 8057 + 9 8259 8260 8301 8300 8058 + 9 8260 8261 8302 8301 8059 + 9 8261 8262 8303 8302 8060 + 9 8262 8263 8304 8303 8061 + 9 8263 8264 8305 8304 8062 + 9 8264 8265 8306 8305 8063 + 9 8265 8266 8307 8306 8064 + 9 8266 8267 8308 8307 8065 + 9 8267 8268 8309 8308 8066 + 9 8268 8269 8310 8309 8067 + 9 8269 8270 8311 8310 8068 + 9 8270 8271 8312 8311 8069 + 9 8271 8272 8313 8312 8070 + 9 8272 8273 8314 8313 8071 + 9 8273 8274 8315 8314 8072 + 9 8274 8275 8316 8315 8073 + 9 8275 8276 8317 8316 8074 + 9 8276 8277 8318 8317 8075 + 9 8277 8278 8319 8318 8076 + 9 8278 8279 8320 8319 8077 + 9 8279 8280 8321 8320 8078 + 9 8280 8281 8322 8321 8079 + 9 8282 8283 8324 8323 8080 + 9 8283 8284 8325 8324 8081 + 9 8284 8285 8326 8325 8082 + 9 8285 8286 8327 8326 8083 + 9 8286 8287 8328 8327 8084 + 9 8287 8288 8329 8328 8085 + 9 8288 8289 8330 8329 8086 + 9 8289 8290 8331 8330 8087 + 9 8290 8291 8332 8331 8088 + 9 8291 8292 8333 8332 8089 + 9 8292 8293 8334 8333 8090 + 9 8293 8294 8335 8334 8091 + 9 8294 8295 8336 8335 8092 + 9 8295 8296 8337 8336 8093 + 9 8296 8297 8338 8337 8094 + 9 8297 8298 8339 8338 8095 + 9 8298 8299 8340 8339 8096 + 9 8299 8300 8341 8340 8097 + 9 8300 8301 8342 8341 8098 + 9 8301 8302 8343 8342 8099 + 9 8302 8303 8344 8343 8100 + 9 8303 8304 8345 8344 8101 + 9 8304 8305 8346 8345 8102 + 9 8305 8306 8347 8346 8103 + 9 8306 8307 8348 8347 8104 + 9 8307 8308 8349 8348 8105 + 9 8308 8309 8350 8349 8106 + 9 8309 8310 8351 8350 8107 + 9 8310 8311 8352 8351 8108 + 9 8311 8312 8353 8352 8109 + 9 8312 8313 8354 8353 8110 + 9 8313 8314 8355 8354 8111 + 9 8314 8315 8356 8355 8112 + 9 8315 8316 8357 8356 8113 + 9 8316 8317 8358 8357 8114 + 9 8317 8318 8359 8358 8115 + 9 8318 8319 8360 8359 8116 + 9 8319 8320 8361 8360 8117 + 9 8320 8321 8362 8361 8118 + 9 8321 8322 8363 8362 8119 + 9 8323 8324 8365 8364 8120 + 9 8324 8325 8366 8365 8121 + 9 8325 8326 8367 8366 8122 + 9 8326 8327 8368 8367 8123 + 9 8327 8328 8369 8368 8124 + 9 8328 8329 8370 8369 8125 + 9 8329 8330 8371 8370 8126 + 9 8330 8331 8372 8371 8127 + 9 8331 8332 8373 8372 8128 + 9 8332 8333 8374 8373 8129 + 9 8333 8334 8375 8374 8130 + 9 8334 8335 8376 8375 8131 + 9 8335 8336 8377 8376 8132 + 9 8336 8337 8378 8377 8133 + 9 8337 8338 8379 8378 8134 + 9 8338 8339 8380 8379 8135 + 9 8339 8340 8381 8380 8136 + 9 8340 8341 8382 8381 8137 + 9 8341 8342 8383 8382 8138 + 9 8342 8343 8384 8383 8139 + 9 8343 8344 8385 8384 8140 + 9 8344 8345 8386 8385 8141 + 9 8345 8346 8387 8386 8142 + 9 8346 8347 8388 8387 8143 + 9 8347 8348 8389 8388 8144 + 9 8348 8349 8390 8389 8145 + 9 8349 8350 8391 8390 8146 + 9 8350 8351 8392 8391 8147 + 9 8351 8352 8393 8392 8148 + 9 8352 8353 8394 8393 8149 + 9 8353 8354 8395 8394 8150 + 9 8354 8355 8396 8395 8151 + 9 8355 8356 8397 8396 8152 + 9 8356 8357 8398 8397 8153 + 9 8357 8358 8399 8398 8154 + 9 8358 8359 8400 8399 8155 + 9 8359 8360 8401 8400 8156 + 9 8360 8361 8402 8401 8157 + 9 8361 8362 8403 8402 8158 + 9 8362 8363 8404 8403 8159 + 9 8364 8365 8406 8405 8160 + 9 8365 8366 8407 8406 8161 + 9 8366 8367 8408 8407 8162 + 9 8367 8368 8409 8408 8163 + 9 8368 8369 8410 8409 8164 + 9 8369 8370 8411 8410 8165 + 9 8370 8371 8412 8411 8166 + 9 8371 8372 8413 8412 8167 + 9 8372 8373 8414 8413 8168 + 9 8373 8374 8415 8414 8169 + 9 8374 8375 8416 8415 8170 + 9 8375 8376 8417 8416 8171 + 9 8376 8377 8418 8417 8172 + 9 8377 8378 8419 8418 8173 + 9 8378 8379 8420 8419 8174 + 9 8379 8380 8421 8420 8175 + 9 8380 8381 8422 8421 8176 + 9 8381 8382 8423 8422 8177 + 9 8382 8383 8424 8423 8178 + 9 8383 8384 8425 8424 8179 + 9 8384 8385 8426 8425 8180 + 9 8385 8386 8427 8426 8181 + 9 8386 8387 8428 8427 8182 + 9 8387 8388 8429 8428 8183 + 9 8388 8389 8430 8429 8184 + 9 8389 8390 8431 8430 8185 + 9 8390 8391 8432 8431 8186 + 9 8391 8392 8433 8432 8187 + 9 8392 8393 8434 8433 8188 + 9 8393 8394 8435 8434 8189 + 9 8394 8395 8436 8435 8190 + 9 8395 8396 8437 8436 8191 + 9 8396 8397 8438 8437 8192 + 9 8397 8398 8439 8438 8193 + 9 8398 8399 8440 8439 8194 + 9 8399 8400 8441 8440 8195 + 9 8400 8401 8442 8441 8196 + 9 8401 8402 8443 8442 8197 + 9 8402 8403 8444 8443 8198 + 9 8403 8404 8445 8444 8199 + 9 8405 8406 8447 8446 8200 + 9 8406 8407 8448 8447 8201 + 9 8407 8408 8449 8448 8202 + 9 8408 8409 8450 8449 8203 + 9 8409 8410 8451 8450 8204 + 9 8410 8411 8452 8451 8205 + 9 8411 8412 8453 8452 8206 + 9 8412 8413 8454 8453 8207 + 9 8413 8414 8455 8454 8208 + 9 8414 8415 8456 8455 8209 + 9 8415 8416 8457 8456 8210 + 9 8416 8417 8458 8457 8211 + 9 8417 8418 8459 8458 8212 + 9 8418 8419 8460 8459 8213 + 9 8419 8420 8461 8460 8214 + 9 8420 8421 8462 8461 8215 + 9 8421 8422 8463 8462 8216 + 9 8422 8423 8464 8463 8217 + 9 8423 8424 8465 8464 8218 + 9 8424 8425 8466 8465 8219 + 9 8425 8426 8467 8466 8220 + 9 8426 8427 8468 8467 8221 + 9 8427 8428 8469 8468 8222 + 9 8428 8429 8470 8469 8223 + 9 8429 8430 8471 8470 8224 + 9 8430 8431 8472 8471 8225 + 9 8431 8432 8473 8472 8226 + 9 8432 8433 8474 8473 8227 + 9 8433 8434 8475 8474 8228 + 9 8434 8435 8476 8475 8229 + 9 8435 8436 8477 8476 8230 + 9 8436 8437 8478 8477 8231 + 9 8437 8438 8479 8478 8232 + 9 8438 8439 8480 8479 8233 + 9 8439 8440 8481 8480 8234 + 9 8440 8441 8482 8481 8235 + 9 8441 8442 8483 8482 8236 + 9 8442 8443 8484 8483 8237 + 9 8443 8444 8485 8484 8238 + 9 8444 8445 8486 8485 8239 + 9 8446 8447 8488 8487 8240 + 9 8447 8448 8489 8488 8241 + 9 8448 8449 8490 8489 8242 + 9 8449 8450 8491 8490 8243 + 9 8450 8451 8492 8491 8244 + 9 8451 8452 8493 8492 8245 + 9 8452 8453 8494 8493 8246 + 9 8453 8454 8495 8494 8247 + 9 8454 8455 8496 8495 8248 + 9 8455 8456 8497 8496 8249 + 9 8456 8457 8498 8497 8250 + 9 8457 8458 8499 8498 8251 + 9 8458 8459 8500 8499 8252 + 9 8459 8460 8501 8500 8253 + 9 8460 8461 8502 8501 8254 + 9 8461 8462 8503 8502 8255 + 9 8462 8463 8504 8503 8256 + 9 8463 8464 8505 8504 8257 + 9 8464 8465 8506 8505 8258 + 9 8465 8466 8507 8506 8259 + 9 8466 8467 8508 8507 8260 + 9 8467 8468 8509 8508 8261 + 9 8468 8469 8510 8509 8262 + 9 8469 8470 8511 8510 8263 + 9 8470 8471 8512 8511 8264 + 9 8471 8472 8513 8512 8265 + 9 8472 8473 8514 8513 8266 + 9 8473 8474 8515 8514 8267 + 9 8474 8475 8516 8515 8268 + 9 8475 8476 8517 8516 8269 + 9 8476 8477 8518 8517 8270 + 9 8477 8478 8519 8518 8271 + 9 8478 8479 8520 8519 8272 + 9 8479 8480 8521 8520 8273 + 9 8480 8481 8522 8521 8274 + 9 8481 8482 8523 8522 8275 + 9 8482 8483 8524 8523 8276 + 9 8483 8484 8525 8524 8277 + 9 8484 8485 8526 8525 8278 + 9 8485 8486 8527 8526 8279 + 9 8487 8488 8529 8528 8280 + 9 8488 8489 8530 8529 8281 + 9 8489 8490 8531 8530 8282 + 9 8490 8491 8532 8531 8283 + 9 8491 8492 8533 8532 8284 + 9 8492 8493 8534 8533 8285 + 9 8493 8494 8535 8534 8286 + 9 8494 8495 8536 8535 8287 + 9 8495 8496 8537 8536 8288 + 9 8496 8497 8538 8537 8289 + 9 8497 8498 8539 8538 8290 + 9 8498 8499 8540 8539 8291 + 9 8499 8500 8541 8540 8292 + 9 8500 8501 8542 8541 8293 + 9 8501 8502 8543 8542 8294 + 9 8502 8503 8544 8543 8295 + 9 8503 8504 8545 8544 8296 + 9 8504 8505 8546 8545 8297 + 9 8505 8506 8547 8546 8298 + 9 8506 8507 8548 8547 8299 + 9 8507 8508 8549 8548 8300 + 9 8508 8509 8550 8549 8301 + 9 8509 8510 8551 8550 8302 + 9 8510 8511 8552 8551 8303 + 9 8511 8512 8553 8552 8304 + 9 8512 8513 8554 8553 8305 + 9 8513 8514 8555 8554 8306 + 9 8514 8515 8556 8555 8307 + 9 8515 8516 8557 8556 8308 + 9 8516 8517 8558 8557 8309 + 9 8517 8518 8559 8558 8310 + 9 8518 8519 8560 8559 8311 + 9 8519 8520 8561 8560 8312 + 9 8520 8521 8562 8561 8313 + 9 8521 8522 8563 8562 8314 + 9 8522 8523 8564 8563 8315 + 9 8523 8524 8565 8564 8316 + 9 8524 8525 8566 8565 8317 + 9 8525 8526 8567 8566 8318 + 9 8526 8527 8568 8567 8319 + 9 8528 8529 8570 8569 8320 + 9 8529 8530 8571 8570 8321 + 9 8530 8531 8572 8571 8322 + 9 8531 8532 8573 8572 8323 + 9 8532 8533 8574 8573 8324 + 9 8533 8534 8575 8574 8325 + 9 8534 8535 8576 8575 8326 + 9 8535 8536 8577 8576 8327 + 9 8536 8537 8578 8577 8328 + 9 8537 8538 8579 8578 8329 + 9 8538 8539 8580 8579 8330 + 9 8539 8540 8581 8580 8331 + 9 8540 8541 8582 8581 8332 + 9 8541 8542 8583 8582 8333 + 9 8542 8543 8584 8583 8334 + 9 8543 8544 8585 8584 8335 + 9 8544 8545 8586 8585 8336 + 9 8545 8546 8587 8586 8337 + 9 8546 8547 8588 8587 8338 + 9 8547 8548 8589 8588 8339 + 9 8548 8549 8590 8589 8340 + 9 8549 8550 8591 8590 8341 + 9 8550 8551 8592 8591 8342 + 9 8551 8552 8593 8592 8343 + 9 8552 8553 8594 8593 8344 + 9 8553 8554 8595 8594 8345 + 9 8554 8555 8596 8595 8346 + 9 8555 8556 8597 8596 8347 + 9 8556 8557 8598 8597 8348 + 9 8557 8558 8599 8598 8349 + 9 8558 8559 8600 8599 8350 + 9 8559 8560 8601 8600 8351 + 9 8560 8561 8602 8601 8352 + 9 8561 8562 8603 8602 8353 + 9 8562 8563 8604 8603 8354 + 9 8563 8564 8605 8604 8355 + 9 8564 8565 8606 8605 8356 + 9 8565 8566 8607 8606 8357 + 9 8566 8567 8608 8607 8358 + 9 8567 8568 8609 8608 8359 + 9 8569 8570 8611 8610 8360 + 9 8570 8571 8612 8611 8361 + 9 8571 8572 8613 8612 8362 + 9 8572 8573 8614 8613 8363 + 9 8573 8574 8615 8614 8364 + 9 8574 8575 8616 8615 8365 + 9 8575 8576 8617 8616 8366 + 9 8576 8577 8618 8617 8367 + 9 8577 8578 8619 8618 8368 + 9 8578 8579 8620 8619 8369 + 9 8579 8580 8621 8620 8370 + 9 8580 8581 8622 8621 8371 + 9 8581 8582 8623 8622 8372 + 9 8582 8583 8624 8623 8373 + 9 8583 8584 8625 8624 8374 + 9 8584 8585 8626 8625 8375 + 9 8585 8586 8627 8626 8376 + 9 8586 8587 8628 8627 8377 + 9 8587 8588 8629 8628 8378 + 9 8588 8589 8630 8629 8379 + 9 8589 8590 8631 8630 8380 + 9 8590 8591 8632 8631 8381 + 9 8591 8592 8633 8632 8382 + 9 8592 8593 8634 8633 8383 + 9 8593 8594 8635 8634 8384 + 9 8594 8595 8636 8635 8385 + 9 8595 8596 8637 8636 8386 + 9 8596 8597 8638 8637 8387 + 9 8597 8598 8639 8638 8388 + 9 8598 8599 8640 8639 8389 + 9 8599 8600 8641 8640 8390 + 9 8600 8601 8642 8641 8391 + 9 8601 8602 8643 8642 8392 + 9 8602 8603 8644 8643 8393 + 9 8603 8604 8645 8644 8394 + 9 8604 8605 8646 8645 8395 + 9 8605 8606 8647 8646 8396 + 9 8606 8607 8648 8647 8397 + 9 8607 8608 8649 8648 8398 + 9 8608 8609 8650 8649 8399 + 9 8610 8611 8652 8651 8400 + 9 8611 8612 8653 8652 8401 + 9 8612 8613 8654 8653 8402 + 9 8613 8614 8655 8654 8403 + 9 8614 8615 8656 8655 8404 + 9 8615 8616 8657 8656 8405 + 9 8616 8617 8658 8657 8406 + 9 8617 8618 8659 8658 8407 + 9 8618 8619 8660 8659 8408 + 9 8619 8620 8661 8660 8409 + 9 8620 8621 8662 8661 8410 + 9 8621 8622 8663 8662 8411 + 9 8622 8623 8664 8663 8412 + 9 8623 8624 8665 8664 8413 + 9 8624 8625 8666 8665 8414 + 9 8625 8626 8667 8666 8415 + 9 8626 8627 8668 8667 8416 + 9 8627 8628 8669 8668 8417 + 9 8628 8629 8670 8669 8418 + 9 8629 8630 8671 8670 8419 + 9 8630 8631 8672 8671 8420 + 9 8631 8632 8673 8672 8421 + 9 8632 8633 8674 8673 8422 + 9 8633 8634 8675 8674 8423 + 9 8634 8635 8676 8675 8424 + 9 8635 8636 8677 8676 8425 + 9 8636 8637 8678 8677 8426 + 9 8637 8638 8679 8678 8427 + 9 8638 8639 8680 8679 8428 + 9 8639 8640 8681 8680 8429 + 9 8640 8641 8682 8681 8430 + 9 8641 8642 8683 8682 8431 + 9 8642 8643 8684 8683 8432 + 9 8643 8644 8685 8684 8433 + 9 8644 8645 8686 8685 8434 + 9 8645 8646 8687 8686 8435 + 9 8646 8647 8688 8687 8436 + 9 8647 8648 8689 8688 8437 + 9 8648 8649 8690 8689 8438 + 9 8649 8650 8691 8690 8439 + 9 8651 8652 8693 8692 8440 + 9 8652 8653 8694 8693 8441 + 9 8653 8654 8695 8694 8442 + 9 8654 8655 8696 8695 8443 + 9 8655 8656 8697 8696 8444 + 9 8656 8657 8698 8697 8445 + 9 8657 8658 8699 8698 8446 + 9 8658 8659 8700 8699 8447 + 9 8659 8660 8701 8700 8448 + 9 8660 8661 8702 8701 8449 + 9 8661 8662 8703 8702 8450 + 9 8662 8663 8704 8703 8451 + 9 8663 8664 8705 8704 8452 + 9 8664 8665 8706 8705 8453 + 9 8665 8666 8707 8706 8454 + 9 8666 8667 8708 8707 8455 + 9 8667 8668 8709 8708 8456 + 9 8668 8669 8710 8709 8457 + 9 8669 8670 8711 8710 8458 + 9 8670 8671 8712 8711 8459 + 9 8671 8672 8713 8712 8460 + 9 8672 8673 8714 8713 8461 + 9 8673 8674 8715 8714 8462 + 9 8674 8675 8716 8715 8463 + 9 8675 8676 8717 8716 8464 + 9 8676 8677 8718 8717 8465 + 9 8677 8678 8719 8718 8466 + 9 8678 8679 8720 8719 8467 + 9 8679 8680 8721 8720 8468 + 9 8680 8681 8722 8721 8469 + 9 8681 8682 8723 8722 8470 + 9 8682 8683 8724 8723 8471 + 9 8683 8684 8725 8724 8472 + 9 8684 8685 8726 8725 8473 + 9 8685 8686 8727 8726 8474 + 9 8686 8687 8728 8727 8475 + 9 8687 8688 8729 8728 8476 + 9 8688 8689 8730 8729 8477 + 9 8689 8690 8731 8730 8478 + 9 8690 8691 8732 8731 8479 + 9 8692 8693 8734 8733 8480 + 9 8693 8694 8735 8734 8481 + 9 8694 8695 8736 8735 8482 + 9 8695 8696 8737 8736 8483 + 9 8696 8697 8738 8737 8484 + 9 8697 8698 8739 8738 8485 + 9 8698 8699 8740 8739 8486 + 9 8699 8700 8741 8740 8487 + 9 8700 8701 8742 8741 8488 + 9 8701 8702 8743 8742 8489 + 9 8702 8703 8744 8743 8490 + 9 8703 8704 8745 8744 8491 + 9 8704 8705 8746 8745 8492 + 9 8705 8706 8747 8746 8493 + 9 8706 8707 8748 8747 8494 + 9 8707 8708 8749 8748 8495 + 9 8708 8709 8750 8749 8496 + 9 8709 8710 8751 8750 8497 + 9 8710 8711 8752 8751 8498 + 9 8711 8712 8753 8752 8499 + 9 8712 8713 8754 8753 8500 + 9 8713 8714 8755 8754 8501 + 9 8714 8715 8756 8755 8502 + 9 8715 8716 8757 8756 8503 + 9 8716 8717 8758 8757 8504 + 9 8717 8718 8759 8758 8505 + 9 8718 8719 8760 8759 8506 + 9 8719 8720 8761 8760 8507 + 9 8720 8721 8762 8761 8508 + 9 8721 8722 8763 8762 8509 + 9 8722 8723 8764 8763 8510 + 9 8723 8724 8765 8764 8511 + 9 8724 8725 8766 8765 8512 + 9 8725 8726 8767 8766 8513 + 9 8726 8727 8768 8767 8514 + 9 8727 8728 8769 8768 8515 + 9 8728 8729 8770 8769 8516 + 9 8729 8730 8771 8770 8517 + 9 8730 8731 8772 8771 8518 + 9 8731 8732 8773 8772 8519 + 9 8733 8734 8775 8774 8520 + 9 8734 8735 8776 8775 8521 + 9 8735 8736 8777 8776 8522 + 9 8736 8737 8778 8777 8523 + 9 8737 8738 8779 8778 8524 + 9 8738 8739 8780 8779 8525 + 9 8739 8740 8781 8780 8526 + 9 8740 8741 8782 8781 8527 + 9 8741 8742 8783 8782 8528 + 9 8742 8743 8784 8783 8529 + 9 8743 8744 8785 8784 8530 + 9 8744 8745 8786 8785 8531 + 9 8745 8746 8787 8786 8532 + 9 8746 8747 8788 8787 8533 + 9 8747 8748 8789 8788 8534 + 9 8748 8749 8790 8789 8535 + 9 8749 8750 8791 8790 8536 + 9 8750 8751 8792 8791 8537 + 9 8751 8752 8793 8792 8538 + 9 8752 8753 8794 8793 8539 + 9 8753 8754 8795 8794 8540 + 9 8754 8755 8796 8795 8541 + 9 8755 8756 8797 8796 8542 + 9 8756 8757 8798 8797 8543 + 9 8757 8758 8799 8798 8544 + 9 8758 8759 8800 8799 8545 + 9 8759 8760 8801 8800 8546 + 9 8760 8761 8802 8801 8547 + 9 8761 8762 8803 8802 8548 + 9 8762 8763 8804 8803 8549 + 9 8763 8764 8805 8804 8550 + 9 8764 8765 8806 8805 8551 + 9 8765 8766 8807 8806 8552 + 9 8766 8767 8808 8807 8553 + 9 8767 8768 8809 8808 8554 + 9 8768 8769 8810 8809 8555 + 9 8769 8770 8811 8810 8556 + 9 8770 8771 8812 8811 8557 + 9 8771 8772 8813 8812 8558 + 9 8772 8773 8814 8813 8559 + 9 8774 8775 8816 8815 8560 + 9 8775 8776 8817 8816 8561 + 9 8776 8777 8818 8817 8562 + 9 8777 8778 8819 8818 8563 + 9 8778 8779 8820 8819 8564 + 9 8779 8780 8821 8820 8565 + 9 8780 8781 8822 8821 8566 + 9 8781 8782 8823 8822 8567 + 9 8782 8783 8824 8823 8568 + 9 8783 8784 8825 8824 8569 + 9 8784 8785 8826 8825 8570 + 9 8785 8786 8827 8826 8571 + 9 8786 8787 8828 8827 8572 + 9 8787 8788 8829 8828 8573 + 9 8788 8789 8830 8829 8574 + 9 8789 8790 8831 8830 8575 + 9 8790 8791 8832 8831 8576 + 9 8791 8792 8833 8832 8577 + 9 8792 8793 8834 8833 8578 + 9 8793 8794 8835 8834 8579 + 9 8794 8795 8836 8835 8580 + 9 8795 8796 8837 8836 8581 + 9 8796 8797 8838 8837 8582 + 9 8797 8798 8839 8838 8583 + 9 8798 8799 8840 8839 8584 + 9 8799 8800 8841 8840 8585 + 9 8800 8801 8842 8841 8586 + 9 8801 8802 8843 8842 8587 + 9 8802 8803 8844 8843 8588 + 9 8803 8804 8845 8844 8589 + 9 8804 8805 8846 8845 8590 + 9 8805 8806 8847 8846 8591 + 9 8806 8807 8848 8847 8592 + 9 8807 8808 8849 8848 8593 + 9 8808 8809 8850 8849 8594 + 9 8809 8810 8851 8850 8595 + 9 8810 8811 8852 8851 8596 + 9 8811 8812 8853 8852 8597 + 9 8812 8813 8854 8853 8598 + 9 8813 8814 8855 8854 8599 + 9 8815 8816 8857 8856 8600 + 9 8816 8817 8858 8857 8601 + 9 8817 8818 8859 8858 8602 + 9 8818 8819 8860 8859 8603 + 9 8819 8820 8861 8860 8604 + 9 8820 8821 8862 8861 8605 + 9 8821 8822 8863 8862 8606 + 9 8822 8823 8864 8863 8607 + 9 8823 8824 8865 8864 8608 + 9 8824 8825 8866 8865 8609 + 9 8825 8826 8867 8866 8610 + 9 8826 8827 8868 8867 8611 + 9 8827 8828 8869 8868 8612 + 9 8828 8829 8870 8869 8613 + 9 8829 8830 8871 8870 8614 + 9 8830 8831 8872 8871 8615 + 9 8831 8832 8873 8872 8616 + 9 8832 8833 8874 8873 8617 + 9 8833 8834 8875 8874 8618 + 9 8834 8835 8876 8875 8619 + 9 8835 8836 8877 8876 8620 + 9 8836 8837 8878 8877 8621 + 9 8837 8838 8879 8878 8622 + 9 8838 8839 8880 8879 8623 + 9 8839 8840 8881 8880 8624 + 9 8840 8841 8882 8881 8625 + 9 8841 8842 8883 8882 8626 + 9 8842 8843 8884 8883 8627 + 9 8843 8844 8885 8884 8628 + 9 8844 8845 8886 8885 8629 + 9 8845 8846 8887 8886 8630 + 9 8846 8847 8888 8887 8631 + 9 8847 8848 8889 8888 8632 + 9 8848 8849 8890 8889 8633 + 9 8849 8850 8891 8890 8634 + 9 8850 8851 8892 8891 8635 + 9 8851 8852 8893 8892 8636 + 9 8852 8853 8894 8893 8637 + 9 8853 8854 8895 8894 8638 + 9 8854 8855 8896 8895 8639 + 9 8856 8857 8898 8897 8640 + 9 8857 8858 8899 8898 8641 + 9 8858 8859 8900 8899 8642 + 9 8859 8860 8901 8900 8643 + 9 8860 8861 8902 8901 8644 + 9 8861 8862 8903 8902 8645 + 9 8862 8863 8904 8903 8646 + 9 8863 8864 8905 8904 8647 + 9 8864 8865 8906 8905 8648 + 9 8865 8866 8907 8906 8649 + 9 8866 8867 8908 8907 8650 + 9 8867 8868 8909 8908 8651 + 9 8868 8869 8910 8909 8652 + 9 8869 8870 8911 8910 8653 + 9 8870 8871 8912 8911 8654 + 9 8871 8872 8913 8912 8655 + 9 8872 8873 8914 8913 8656 + 9 8873 8874 8915 8914 8657 + 9 8874 8875 8916 8915 8658 + 9 8875 8876 8917 8916 8659 + 9 8876 8877 8918 8917 8660 + 9 8877 8878 8919 8918 8661 + 9 8878 8879 8920 8919 8662 + 9 8879 8880 8921 8920 8663 + 9 8880 8881 8922 8921 8664 + 9 8881 8882 8923 8922 8665 + 9 8882 8883 8924 8923 8666 + 9 8883 8884 8925 8924 8667 + 9 8884 8885 8926 8925 8668 + 9 8885 8886 8927 8926 8669 + 9 8886 8887 8928 8927 8670 + 9 8887 8888 8929 8928 8671 + 9 8888 8889 8930 8929 8672 + 9 8889 8890 8931 8930 8673 + 9 8890 8891 8932 8931 8674 + 9 8891 8892 8933 8932 8675 + 9 8892 8893 8934 8933 8676 + 9 8893 8894 8935 8934 8677 + 9 8894 8895 8936 8935 8678 + 9 8895 8896 8937 8936 8679 + 9 8897 8898 8939 8938 8680 + 9 8898 8899 8940 8939 8681 + 9 8899 8900 8941 8940 8682 + 9 8900 8901 8942 8941 8683 + 9 8901 8902 8943 8942 8684 + 9 8902 8903 8944 8943 8685 + 9 8903 8904 8945 8944 8686 + 9 8904 8905 8946 8945 8687 + 9 8905 8906 8947 8946 8688 + 9 8906 8907 8948 8947 8689 + 9 8907 8908 8949 8948 8690 + 9 8908 8909 8950 8949 8691 + 9 8909 8910 8951 8950 8692 + 9 8910 8911 8952 8951 8693 + 9 8911 8912 8953 8952 8694 + 9 8912 8913 8954 8953 8695 + 9 8913 8914 8955 8954 8696 + 9 8914 8915 8956 8955 8697 + 9 8915 8916 8957 8956 8698 + 9 8916 8917 8958 8957 8699 + 9 8917 8918 8959 8958 8700 + 9 8918 8919 8960 8959 8701 + 9 8919 8920 8961 8960 8702 + 9 8920 8921 8962 8961 8703 + 9 8921 8922 8963 8962 8704 + 9 8922 8923 8964 8963 8705 + 9 8923 8924 8965 8964 8706 + 9 8924 8925 8966 8965 8707 + 9 8925 8926 8967 8966 8708 + 9 8926 8927 8968 8967 8709 + 9 8927 8928 8969 8968 8710 + 9 8928 8929 8970 8969 8711 + 9 8929 8930 8971 8970 8712 + 9 8930 8931 8972 8971 8713 + 9 8931 8932 8973 8972 8714 + 9 8932 8933 8974 8973 8715 + 9 8933 8934 8975 8974 8716 + 9 8934 8935 8976 8975 8717 + 9 8935 8936 8977 8976 8718 + 9 8936 8937 8978 8977 8719 + 9 8938 8939 8980 8979 8720 + 9 8939 8940 8981 8980 8721 + 9 8940 8941 8982 8981 8722 + 9 8941 8942 8983 8982 8723 + 9 8942 8943 8984 8983 8724 + 9 8943 8944 8985 8984 8725 + 9 8944 8945 8986 8985 8726 + 9 8945 8946 8987 8986 8727 + 9 8946 8947 8988 8987 8728 + 9 8947 8948 8989 8988 8729 + 9 8948 8949 8990 8989 8730 + 9 8949 8950 8991 8990 8731 + 9 8950 8951 8992 8991 8732 + 9 8951 8952 8993 8992 8733 + 9 8952 8953 8994 8993 8734 + 9 8953 8954 8995 8994 8735 + 9 8954 8955 8996 8995 8736 + 9 8955 8956 8997 8996 8737 + 9 8956 8957 8998 8997 8738 + 9 8957 8958 8999 8998 8739 + 9 8958 8959 9000 8999 8740 + 9 8959 8960 9001 9000 8741 + 9 8960 8961 9002 9001 8742 + 9 8961 8962 9003 9002 8743 + 9 8962 8963 9004 9003 8744 + 9 8963 8964 9005 9004 8745 + 9 8964 8965 9006 9005 8746 + 9 8965 8966 9007 9006 8747 + 9 8966 8967 9008 9007 8748 + 9 8967 8968 9009 9008 8749 + 9 8968 8969 9010 9009 8750 + 9 8969 8970 9011 9010 8751 + 9 8970 8971 9012 9011 8752 + 9 8971 8972 9013 9012 8753 + 9 8972 8973 9014 9013 8754 + 9 8973 8974 9015 9014 8755 + 9 8974 8975 9016 9015 8756 + 9 8975 8976 9017 9016 8757 + 9 8976 8977 9018 9017 8758 + 9 8977 8978 9019 9018 8759 + 9 8979 8980 9021 9020 8760 + 9 8980 8981 9022 9021 8761 + 9 8981 8982 9023 9022 8762 + 9 8982 8983 9024 9023 8763 + 9 8983 8984 9025 9024 8764 + 9 8984 8985 9026 9025 8765 + 9 8985 8986 9027 9026 8766 + 9 8986 8987 9028 9027 8767 + 9 8987 8988 9029 9028 8768 + 9 8988 8989 9030 9029 8769 + 9 8989 8990 9031 9030 8770 + 9 8990 8991 9032 9031 8771 + 9 8991 8992 9033 9032 8772 + 9 8992 8993 9034 9033 8773 + 9 8993 8994 9035 9034 8774 + 9 8994 8995 9036 9035 8775 + 9 8995 8996 9037 9036 8776 + 9 8996 8997 9038 9037 8777 + 9 8997 8998 9039 9038 8778 + 9 8998 8999 9040 9039 8779 + 9 8999 9000 9041 9040 8780 + 9 9000 9001 9042 9041 8781 + 9 9001 9002 9043 9042 8782 + 9 9002 9003 9044 9043 8783 + 9 9003 9004 9045 9044 8784 + 9 9004 9005 9046 9045 8785 + 9 9005 9006 9047 9046 8786 + 9 9006 9007 9048 9047 8787 + 9 9007 9008 9049 9048 8788 + 9 9008 9009 9050 9049 8789 + 9 9009 9010 9051 9050 8790 + 9 9010 9011 9052 9051 8791 + 9 9011 9012 9053 9052 8792 + 9 9012 9013 9054 9053 8793 + 9 9013 9014 9055 9054 8794 + 9 9014 9015 9056 9055 8795 + 9 9015 9016 9057 9056 8796 + 9 9016 9017 9058 9057 8797 + 9 9017 9018 9059 9058 8798 + 9 9018 9019 9060 9059 8799 + 9 9020 9021 9062 9061 8800 + 9 9021 9022 9063 9062 8801 + 9 9022 9023 9064 9063 8802 + 9 9023 9024 9065 9064 8803 + 9 9024 9025 9066 9065 8804 + 9 9025 9026 9067 9066 8805 + 9 9026 9027 9068 9067 8806 + 9 9027 9028 9069 9068 8807 + 9 9028 9029 9070 9069 8808 + 9 9029 9030 9071 9070 8809 + 9 9030 9031 9072 9071 8810 + 9 9031 9032 9073 9072 8811 + 9 9032 9033 9074 9073 8812 + 9 9033 9034 9075 9074 8813 + 9 9034 9035 9076 9075 8814 + 9 9035 9036 9077 9076 8815 + 9 9036 9037 9078 9077 8816 + 9 9037 9038 9079 9078 8817 + 9 9038 9039 9080 9079 8818 + 9 9039 9040 9081 9080 8819 + 9 9040 9041 9082 9081 8820 + 9 9041 9042 9083 9082 8821 + 9 9042 9043 9084 9083 8822 + 9 9043 9044 9085 9084 8823 + 9 9044 9045 9086 9085 8824 + 9 9045 9046 9087 9086 8825 + 9 9046 9047 9088 9087 8826 + 9 9047 9048 9089 9088 8827 + 9 9048 9049 9090 9089 8828 + 9 9049 9050 9091 9090 8829 + 9 9050 9051 9092 9091 8830 + 9 9051 9052 9093 9092 8831 + 9 9052 9053 9094 9093 8832 + 9 9053 9054 9095 9094 8833 + 9 9054 9055 9096 9095 8834 + 9 9055 9056 9097 9096 8835 + 9 9056 9057 9098 9097 8836 + 9 9057 9058 9099 9098 8837 + 9 9058 9059 9100 9099 8838 + 9 9059 9060 9101 9100 8839 + 9 9061 9062 9103 9102 8840 + 9 9062 9063 9104 9103 8841 + 9 9063 9064 9105 9104 8842 + 9 9064 9065 9106 9105 8843 + 9 9065 9066 9107 9106 8844 + 9 9066 9067 9108 9107 8845 + 9 9067 9068 9109 9108 8846 + 9 9068 9069 9110 9109 8847 + 9 9069 9070 9111 9110 8848 + 9 9070 9071 9112 9111 8849 + 9 9071 9072 9113 9112 8850 + 9 9072 9073 9114 9113 8851 + 9 9073 9074 9115 9114 8852 + 9 9074 9075 9116 9115 8853 + 9 9075 9076 9117 9116 8854 + 9 9076 9077 9118 9117 8855 + 9 9077 9078 9119 9118 8856 + 9 9078 9079 9120 9119 8857 + 9 9079 9080 9121 9120 8858 + 9 9080 9081 9122 9121 8859 + 9 9081 9082 9123 9122 8860 + 9 9082 9083 9124 9123 8861 + 9 9083 9084 9125 9124 8862 + 9 9084 9085 9126 9125 8863 + 9 9085 9086 9127 9126 8864 + 9 9086 9087 9128 9127 8865 + 9 9087 9088 9129 9128 8866 + 9 9088 9089 9130 9129 8867 + 9 9089 9090 9131 9130 8868 + 9 9090 9091 9132 9131 8869 + 9 9091 9092 9133 9132 8870 + 9 9092 9093 9134 9133 8871 + 9 9093 9094 9135 9134 8872 + 9 9094 9095 9136 9135 8873 + 9 9095 9096 9137 9136 8874 + 9 9096 9097 9138 9137 8875 + 9 9097 9098 9139 9138 8876 + 9 9098 9099 9140 9139 8877 + 9 9099 9100 9141 9140 8878 + 9 9100 9101 9142 9141 8879 + 9 9102 9103 9144 9143 8880 + 9 9103 9104 9145 9144 8881 + 9 9104 9105 9146 9145 8882 + 9 9105 9106 9147 9146 8883 + 9 9106 9107 9148 9147 8884 + 9 9107 9108 9149 9148 8885 + 9 9108 9109 9150 9149 8886 + 9 9109 9110 9151 9150 8887 + 9 9110 9111 9152 9151 8888 + 9 9111 9112 9153 9152 8889 + 9 9112 9113 9154 9153 8890 + 9 9113 9114 9155 9154 8891 + 9 9114 9115 9156 9155 8892 + 9 9115 9116 9157 9156 8893 + 9 9116 9117 9158 9157 8894 + 9 9117 9118 9159 9158 8895 + 9 9118 9119 9160 9159 8896 + 9 9119 9120 9161 9160 8897 + 9 9120 9121 9162 9161 8898 + 9 9121 9122 9163 9162 8899 + 9 9122 9123 9164 9163 8900 + 9 9123 9124 9165 9164 8901 + 9 9124 9125 9166 9165 8902 + 9 9125 9126 9167 9166 8903 + 9 9126 9127 9168 9167 8904 + 9 9127 9128 9169 9168 8905 + 9 9128 9129 9170 9169 8906 + 9 9129 9130 9171 9170 8907 + 9 9130 9131 9172 9171 8908 + 9 9131 9132 9173 9172 8909 + 9 9132 9133 9174 9173 8910 + 9 9133 9134 9175 9174 8911 + 9 9134 9135 9176 9175 8912 + 9 9135 9136 9177 9176 8913 + 9 9136 9137 9178 9177 8914 + 9 9137 9138 9179 9178 8915 + 9 9138 9139 9180 9179 8916 + 9 9139 9140 9181 9180 8917 + 9 9140 9141 9182 9181 8918 + 9 9141 9142 9183 9182 8919 + 9 9143 9144 9185 9184 8920 + 9 9144 9145 9186 9185 8921 + 9 9145 9146 9187 9186 8922 + 9 9146 9147 9188 9187 8923 + 9 9147 9148 9189 9188 8924 + 9 9148 9149 9190 9189 8925 + 9 9149 9150 9191 9190 8926 + 9 9150 9151 9192 9191 8927 + 9 9151 9152 9193 9192 8928 + 9 9152 9153 9194 9193 8929 + 9 9153 9154 9195 9194 8930 + 9 9154 9155 9196 9195 8931 + 9 9155 9156 9197 9196 8932 + 9 9156 9157 9198 9197 8933 + 9 9157 9158 9199 9198 8934 + 9 9158 9159 9200 9199 8935 + 9 9159 9160 9201 9200 8936 + 9 9160 9161 9202 9201 8937 + 9 9161 9162 9203 9202 8938 + 9 9162 9163 9204 9203 8939 + 9 9163 9164 9205 9204 8940 + 9 9164 9165 9206 9205 8941 + 9 9165 9166 9207 9206 8942 + 9 9166 9167 9208 9207 8943 + 9 9167 9168 9209 9208 8944 + 9 9168 9169 9210 9209 8945 + 9 9169 9170 9211 9210 8946 + 9 9170 9171 9212 9211 8947 + 9 9171 9172 9213 9212 8948 + 9 9172 9173 9214 9213 8949 + 9 9173 9174 9215 9214 8950 + 9 9174 9175 9216 9215 8951 + 9 9175 9176 9217 9216 8952 + 9 9176 9177 9218 9217 8953 + 9 9177 9178 9219 9218 8954 + 9 9178 9179 9220 9219 8955 + 9 9179 9180 9221 9220 8956 + 9 9180 9181 9222 9221 8957 + 9 9181 9182 9223 9222 8958 + 9 9182 9183 9224 9223 8959 + 9 9184 9185 9226 9225 8960 + 9 9185 9186 9227 9226 8961 + 9 9186 9187 9228 9227 8962 + 9 9187 9188 9229 9228 8963 + 9 9188 9189 9230 9229 8964 + 9 9189 9190 9231 9230 8965 + 9 9190 9191 9232 9231 8966 + 9 9191 9192 9233 9232 8967 + 9 9192 9193 9234 9233 8968 + 9 9193 9194 9235 9234 8969 + 9 9194 9195 9236 9235 8970 + 9 9195 9196 9237 9236 8971 + 9 9196 9197 9238 9237 8972 + 9 9197 9198 9239 9238 8973 + 9 9198 9199 9240 9239 8974 + 9 9199 9200 9241 9240 8975 + 9 9200 9201 9242 9241 8976 + 9 9201 9202 9243 9242 8977 + 9 9202 9203 9244 9243 8978 + 9 9203 9204 9245 9244 8979 + 9 9204 9205 9246 9245 8980 + 9 9205 9206 9247 9246 8981 + 9 9206 9207 9248 9247 8982 + 9 9207 9208 9249 9248 8983 + 9 9208 9209 9250 9249 8984 + 9 9209 9210 9251 9250 8985 + 9 9210 9211 9252 9251 8986 + 9 9211 9212 9253 9252 8987 + 9 9212 9213 9254 9253 8988 + 9 9213 9214 9255 9254 8989 + 9 9214 9215 9256 9255 8990 + 9 9215 9216 9257 9256 8991 + 9 9216 9217 9258 9257 8992 + 9 9217 9218 9259 9258 8993 + 9 9218 9219 9260 9259 8994 + 9 9219 9220 9261 9260 8995 + 9 9220 9221 9262 9261 8996 + 9 9221 9222 9263 9262 8997 + 9 9222 9223 9264 9263 8998 + 9 9223 9224 9265 9264 8999 + 9 9225 9226 9267 9266 9000 + 9 9226 9227 9268 9267 9001 + 9 9227 9228 9269 9268 9002 + 9 9228 9229 9270 9269 9003 + 9 9229 9230 9271 9270 9004 + 9 9230 9231 9272 9271 9005 + 9 9231 9232 9273 9272 9006 + 9 9232 9233 9274 9273 9007 + 9 9233 9234 9275 9274 9008 + 9 9234 9235 9276 9275 9009 + 9 9235 9236 9277 9276 9010 + 9 9236 9237 9278 9277 9011 + 9 9237 9238 9279 9278 9012 + 9 9238 9239 9280 9279 9013 + 9 9239 9240 9281 9280 9014 + 9 9240 9241 9282 9281 9015 + 9 9241 9242 9283 9282 9016 + 9 9242 9243 9284 9283 9017 + 9 9243 9244 9285 9284 9018 + 9 9244 9245 9286 9285 9019 + 9 9245 9246 9287 9286 9020 + 9 9246 9247 9288 9287 9021 + 9 9247 9248 9289 9288 9022 + 9 9248 9249 9290 9289 9023 + 9 9249 9250 9291 9290 9024 + 9 9250 9251 9292 9291 9025 + 9 9251 9252 9293 9292 9026 + 9 9252 9253 9294 9293 9027 + 9 9253 9254 9295 9294 9028 + 9 9254 9255 9296 9295 9029 + 9 9255 9256 9297 9296 9030 + 9 9256 9257 9298 9297 9031 + 9 9257 9258 9299 9298 9032 + 9 9258 9259 9300 9299 9033 + 9 9259 9260 9301 9300 9034 + 9 9260 9261 9302 9301 9035 + 9 9261 9262 9303 9302 9036 + 9 9262 9263 9304 9303 9037 + 9 9263 9264 9305 9304 9038 + 9 9264 9265 9306 9305 9039 + 9 9266 9267 9308 9307 9040 + 9 9267 9268 9309 9308 9041 + 9 9268 9269 9310 9309 9042 + 9 9269 9270 9311 9310 9043 + 9 9270 9271 9312 9311 9044 + 9 9271 9272 9313 9312 9045 + 9 9272 9273 9314 9313 9046 + 9 9273 9274 9315 9314 9047 + 9 9274 9275 9316 9315 9048 + 9 9275 9276 9317 9316 9049 + 9 9276 9277 9318 9317 9050 + 9 9277 9278 9319 9318 9051 + 9 9278 9279 9320 9319 9052 + 9 9279 9280 9321 9320 9053 + 9 9280 9281 9322 9321 9054 + 9 9281 9282 9323 9322 9055 + 9 9282 9283 9324 9323 9056 + 9 9283 9284 9325 9324 9057 + 9 9284 9285 9326 9325 9058 + 9 9285 9286 9327 9326 9059 + 9 9286 9287 9328 9327 9060 + 9 9287 9288 9329 9328 9061 + 9 9288 9289 9330 9329 9062 + 9 9289 9290 9331 9330 9063 + 9 9290 9291 9332 9331 9064 + 9 9291 9292 9333 9332 9065 + 9 9292 9293 9334 9333 9066 + 9 9293 9294 9335 9334 9067 + 9 9294 9295 9336 9335 9068 + 9 9295 9296 9337 9336 9069 + 9 9296 9297 9338 9337 9070 + 9 9297 9298 9339 9338 9071 + 9 9298 9299 9340 9339 9072 + 9 9299 9300 9341 9340 9073 + 9 9300 9301 9342 9341 9074 + 9 9301 9302 9343 9342 9075 + 9 9302 9303 9344 9343 9076 + 9 9303 9304 9345 9344 9077 + 9 9304 9305 9346 9345 9078 + 9 9305 9306 9347 9346 9079 + 9 9307 9308 9349 9348 9080 + 9 9308 9309 9350 9349 9081 + 9 9309 9310 9351 9350 9082 + 9 9310 9311 9352 9351 9083 + 9 9311 9312 9353 9352 9084 + 9 9312 9313 9354 9353 9085 + 9 9313 9314 9355 9354 9086 + 9 9314 9315 9356 9355 9087 + 9 9315 9316 9357 9356 9088 + 9 9316 9317 9358 9357 9089 + 9 9317 9318 9359 9358 9090 + 9 9318 9319 9360 9359 9091 + 9 9319 9320 9361 9360 9092 + 9 9320 9321 9362 9361 9093 + 9 9321 9322 9363 9362 9094 + 9 9322 9323 9364 9363 9095 + 9 9323 9324 9365 9364 9096 + 9 9324 9325 9366 9365 9097 + 9 9325 9326 9367 9366 9098 + 9 9326 9327 9368 9367 9099 + 9 9327 9328 9369 9368 9100 + 9 9328 9329 9370 9369 9101 + 9 9329 9330 9371 9370 9102 + 9 9330 9331 9372 9371 9103 + 9 9331 9332 9373 9372 9104 + 9 9332 9333 9374 9373 9105 + 9 9333 9334 9375 9374 9106 + 9 9334 9335 9376 9375 9107 + 9 9335 9336 9377 9376 9108 + 9 9336 9337 9378 9377 9109 + 9 9337 9338 9379 9378 9110 + 9 9338 9339 9380 9379 9111 + 9 9339 9340 9381 9380 9112 + 9 9340 9341 9382 9381 9113 + 9 9341 9342 9383 9382 9114 + 9 9342 9343 9384 9383 9115 + 9 9343 9344 9385 9384 9116 + 9 9344 9345 9386 9385 9117 + 9 9345 9346 9387 9386 9118 + 9 9346 9347 9388 9387 9119 + 9 9348 9349 9390 9389 9120 + 9 9349 9350 9391 9390 9121 + 9 9350 9351 9392 9391 9122 + 9 9351 9352 9393 9392 9123 + 9 9352 9353 9394 9393 9124 + 9 9353 9354 9395 9394 9125 + 9 9354 9355 9396 9395 9126 + 9 9355 9356 9397 9396 9127 + 9 9356 9357 9398 9397 9128 + 9 9357 9358 9399 9398 9129 + 9 9358 9359 9400 9399 9130 + 9 9359 9360 9401 9400 9131 + 9 9360 9361 9402 9401 9132 + 9 9361 9362 9403 9402 9133 + 9 9362 9363 9404 9403 9134 + 9 9363 9364 9405 9404 9135 + 9 9364 9365 9406 9405 9136 + 9 9365 9366 9407 9406 9137 + 9 9366 9367 9408 9407 9138 + 9 9367 9368 9409 9408 9139 + 9 9368 9369 9410 9409 9140 + 9 9369 9370 9411 9410 9141 + 9 9370 9371 9412 9411 9142 + 9 9371 9372 9413 9412 9143 + 9 9372 9373 9414 9413 9144 + 9 9373 9374 9415 9414 9145 + 9 9374 9375 9416 9415 9146 + 9 9375 9376 9417 9416 9147 + 9 9376 9377 9418 9417 9148 + 9 9377 9378 9419 9418 9149 + 9 9378 9379 9420 9419 9150 + 9 9379 9380 9421 9420 9151 + 9 9380 9381 9422 9421 9152 + 9 9381 9382 9423 9422 9153 + 9 9382 9383 9424 9423 9154 + 9 9383 9384 9425 9424 9155 + 9 9384 9385 9426 9425 9156 + 9 9385 9386 9427 9426 9157 + 9 9386 9387 9428 9427 9158 + 9 9387 9388 9429 9428 9159 + 9 9389 9390 9431 9430 9160 + 9 9390 9391 9432 9431 9161 + 9 9391 9392 9433 9432 9162 + 9 9392 9393 9434 9433 9163 + 9 9393 9394 9435 9434 9164 + 9 9394 9395 9436 9435 9165 + 9 9395 9396 9437 9436 9166 + 9 9396 9397 9438 9437 9167 + 9 9397 9398 9439 9438 9168 + 9 9398 9399 9440 9439 9169 + 9 9399 9400 9441 9440 9170 + 9 9400 9401 9442 9441 9171 + 9 9401 9402 9443 9442 9172 + 9 9402 9403 9444 9443 9173 + 9 9403 9404 9445 9444 9174 + 9 9404 9405 9446 9445 9175 + 9 9405 9406 9447 9446 9176 + 9 9406 9407 9448 9447 9177 + 9 9407 9408 9449 9448 9178 + 9 9408 9409 9450 9449 9179 + 9 9409 9410 9451 9450 9180 + 9 9410 9411 9452 9451 9181 + 9 9411 9412 9453 9452 9182 + 9 9412 9413 9454 9453 9183 + 9 9413 9414 9455 9454 9184 + 9 9414 9415 9456 9455 9185 + 9 9415 9416 9457 9456 9186 + 9 9416 9417 9458 9457 9187 + 9 9417 9418 9459 9458 9188 + 9 9418 9419 9460 9459 9189 + 9 9419 9420 9461 9460 9190 + 9 9420 9421 9462 9461 9191 + 9 9421 9422 9463 9462 9192 + 9 9422 9423 9464 9463 9193 + 9 9423 9424 9465 9464 9194 + 9 9424 9425 9466 9465 9195 + 9 9425 9426 9467 9466 9196 + 9 9426 9427 9468 9467 9197 + 9 9427 9428 9469 9468 9198 + 9 9428 9429 9470 9469 9199 + 9 9430 9431 9472 9471 9200 + 9 9431 9432 9473 9472 9201 + 9 9432 9433 9474 9473 9202 + 9 9433 9434 9475 9474 9203 + 9 9434 9435 9476 9475 9204 + 9 9435 9436 9477 9476 9205 + 9 9436 9437 9478 9477 9206 + 9 9437 9438 9479 9478 9207 + 9 9438 9439 9480 9479 9208 + 9 9439 9440 9481 9480 9209 + 9 9440 9441 9482 9481 9210 + 9 9441 9442 9483 9482 9211 + 9 9442 9443 9484 9483 9212 + 9 9443 9444 9485 9484 9213 + 9 9444 9445 9486 9485 9214 + 9 9445 9446 9487 9486 9215 + 9 9446 9447 9488 9487 9216 + 9 9447 9448 9489 9488 9217 + 9 9448 9449 9490 9489 9218 + 9 9449 9450 9491 9490 9219 + 9 9450 9451 9492 9491 9220 + 9 9451 9452 9493 9492 9221 + 9 9452 9453 9494 9493 9222 + 9 9453 9454 9495 9494 9223 + 9 9454 9455 9496 9495 9224 + 9 9455 9456 9497 9496 9225 + 9 9456 9457 9498 9497 9226 + 9 9457 9458 9499 9498 9227 + 9 9458 9459 9500 9499 9228 + 9 9459 9460 9501 9500 9229 + 9 9460 9461 9502 9501 9230 + 9 9461 9462 9503 9502 9231 + 9 9462 9463 9504 9503 9232 + 9 9463 9464 9505 9504 9233 + 9 9464 9465 9506 9505 9234 + 9 9465 9466 9507 9506 9235 + 9 9466 9467 9508 9507 9236 + 9 9467 9468 9509 9508 9237 + 9 9468 9469 9510 9509 9238 + 9 9469 9470 9511 9510 9239 + 9 9471 9472 9513 9512 9240 + 9 9472 9473 9514 9513 9241 + 9 9473 9474 9515 9514 9242 + 9 9474 9475 9516 9515 9243 + 9 9475 9476 9517 9516 9244 + 9 9476 9477 9518 9517 9245 + 9 9477 9478 9519 9518 9246 + 9 9478 9479 9520 9519 9247 + 9 9479 9480 9521 9520 9248 + 9 9480 9481 9522 9521 9249 + 9 9481 9482 9523 9522 9250 + 9 9482 9483 9524 9523 9251 + 9 9483 9484 9525 9524 9252 + 9 9484 9485 9526 9525 9253 + 9 9485 9486 9527 9526 9254 + 9 9486 9487 9528 9527 9255 + 9 9487 9488 9529 9528 9256 + 9 9488 9489 9530 9529 9257 + 9 9489 9490 9531 9530 9258 + 9 9490 9491 9532 9531 9259 + 9 9491 9492 9533 9532 9260 + 9 9492 9493 9534 9533 9261 + 9 9493 9494 9535 9534 9262 + 9 9494 9495 9536 9535 9263 + 9 9495 9496 9537 9536 9264 + 9 9496 9497 9538 9537 9265 + 9 9497 9498 9539 9538 9266 + 9 9498 9499 9540 9539 9267 + 9 9499 9500 9541 9540 9268 + 9 9500 9501 9542 9541 9269 + 9 9501 9502 9543 9542 9270 + 9 9502 9503 9544 9543 9271 + 9 9503 9504 9545 9544 9272 + 9 9504 9505 9546 9545 9273 + 9 9505 9506 9547 9546 9274 + 9 9506 9507 9548 9547 9275 + 9 9507 9508 9549 9548 9276 + 9 9508 9509 9550 9549 9277 + 9 9509 9510 9551 9550 9278 + 9 9510 9511 9552 9551 9279 + 9 9512 9513 9554 9553 9280 + 9 9513 9514 9555 9554 9281 + 9 9514 9515 9556 9555 9282 + 9 9515 9516 9557 9556 9283 + 9 9516 9517 9558 9557 9284 + 9 9517 9518 9559 9558 9285 + 9 9518 9519 9560 9559 9286 + 9 9519 9520 9561 9560 9287 + 9 9520 9521 9562 9561 9288 + 9 9521 9522 9563 9562 9289 + 9 9522 9523 9564 9563 9290 + 9 9523 9524 9565 9564 9291 + 9 9524 9525 9566 9565 9292 + 9 9525 9526 9567 9566 9293 + 9 9526 9527 9568 9567 9294 + 9 9527 9528 9569 9568 9295 + 9 9528 9529 9570 9569 9296 + 9 9529 9530 9571 9570 9297 + 9 9530 9531 9572 9571 9298 + 9 9531 9532 9573 9572 9299 + 9 9532 9533 9574 9573 9300 + 9 9533 9534 9575 9574 9301 + 9 9534 9535 9576 9575 9302 + 9 9535 9536 9577 9576 9303 + 9 9536 9537 9578 9577 9304 + 9 9537 9538 9579 9578 9305 + 9 9538 9539 9580 9579 9306 + 9 9539 9540 9581 9580 9307 + 9 9540 9541 9582 9581 9308 + 9 9541 9542 9583 9582 9309 + 9 9542 9543 9584 9583 9310 + 9 9543 9544 9585 9584 9311 + 9 9544 9545 9586 9585 9312 + 9 9545 9546 9587 9586 9313 + 9 9546 9547 9588 9587 9314 + 9 9547 9548 9589 9588 9315 + 9 9548 9549 9590 9589 9316 + 9 9549 9550 9591 9590 9317 + 9 9550 9551 9592 9591 9318 + 9 9551 9552 9593 9592 9319 + 9 9553 9554 9595 9594 9320 + 9 9554 9555 9596 9595 9321 + 9 9555 9556 9597 9596 9322 + 9 9556 9557 9598 9597 9323 + 9 9557 9558 9599 9598 9324 + 9 9558 9559 9600 9599 9325 + 9 9559 9560 9601 9600 9326 + 9 9560 9561 9602 9601 9327 + 9 9561 9562 9603 9602 9328 + 9 9562 9563 9604 9603 9329 + 9 9563 9564 9605 9604 9330 + 9 9564 9565 9606 9605 9331 + 9 9565 9566 9607 9606 9332 + 9 9566 9567 9608 9607 9333 + 9 9567 9568 9609 9608 9334 + 9 9568 9569 9610 9609 9335 + 9 9569 9570 9611 9610 9336 + 9 9570 9571 9612 9611 9337 + 9 9571 9572 9613 9612 9338 + 9 9572 9573 9614 9613 9339 + 9 9573 9574 9615 9614 9340 + 9 9574 9575 9616 9615 9341 + 9 9575 9576 9617 9616 9342 + 9 9576 9577 9618 9617 9343 + 9 9577 9578 9619 9618 9344 + 9 9578 9579 9620 9619 9345 + 9 9579 9580 9621 9620 9346 + 9 9580 9581 9622 9621 9347 + 9 9581 9582 9623 9622 9348 + 9 9582 9583 9624 9623 9349 + 9 9583 9584 9625 9624 9350 + 9 9584 9585 9626 9625 9351 + 9 9585 9586 9627 9626 9352 + 9 9586 9587 9628 9627 9353 + 9 9587 9588 9629 9628 9354 + 9 9588 9589 9630 9629 9355 + 9 9589 9590 9631 9630 9356 + 9 9590 9591 9632 9631 9357 + 9 9591 9592 9633 9632 9358 + 9 9592 9593 9634 9633 9359 + 9 9594 9595 9636 9635 9360 + 9 9595 9596 9637 9636 9361 + 9 9596 9597 9638 9637 9362 + 9 9597 9598 9639 9638 9363 + 9 9598 9599 9640 9639 9364 + 9 9599 9600 9641 9640 9365 + 9 9600 9601 9642 9641 9366 + 9 9601 9602 9643 9642 9367 + 9 9602 9603 9644 9643 9368 + 9 9603 9604 9645 9644 9369 + 9 9604 9605 9646 9645 9370 + 9 9605 9606 9647 9646 9371 + 9 9606 9607 9648 9647 9372 + 9 9607 9608 9649 9648 9373 + 9 9608 9609 9650 9649 9374 + 9 9609 9610 9651 9650 9375 + 9 9610 9611 9652 9651 9376 + 9 9611 9612 9653 9652 9377 + 9 9612 9613 9654 9653 9378 + 9 9613 9614 9655 9654 9379 + 9 9614 9615 9656 9655 9380 + 9 9615 9616 9657 9656 9381 + 9 9616 9617 9658 9657 9382 + 9 9617 9618 9659 9658 9383 + 9 9618 9619 9660 9659 9384 + 9 9619 9620 9661 9660 9385 + 9 9620 9621 9662 9661 9386 + 9 9621 9622 9663 9662 9387 + 9 9622 9623 9664 9663 9388 + 9 9623 9624 9665 9664 9389 + 9 9624 9625 9666 9665 9390 + 9 9625 9626 9667 9666 9391 + 9 9626 9627 9668 9667 9392 + 9 9627 9628 9669 9668 9393 + 9 9628 9629 9670 9669 9394 + 9 9629 9630 9671 9670 9395 + 9 9630 9631 9672 9671 9396 + 9 9631 9632 9673 9672 9397 + 9 9632 9633 9674 9673 9398 + 9 9633 9634 9675 9674 9399 + 9 9635 9636 9677 9676 9400 + 9 9636 9637 9678 9677 9401 + 9 9637 9638 9679 9678 9402 + 9 9638 9639 9680 9679 9403 + 9 9639 9640 9681 9680 9404 + 9 9640 9641 9682 9681 9405 + 9 9641 9642 9683 9682 9406 + 9 9642 9643 9684 9683 9407 + 9 9643 9644 9685 9684 9408 + 9 9644 9645 9686 9685 9409 + 9 9645 9646 9687 9686 9410 + 9 9646 9647 9688 9687 9411 + 9 9647 9648 9689 9688 9412 + 9 9648 9649 9690 9689 9413 + 9 9649 9650 9691 9690 9414 + 9 9650 9651 9692 9691 9415 + 9 9651 9652 9693 9692 9416 + 9 9652 9653 9694 9693 9417 + 9 9653 9654 9695 9694 9418 + 9 9654 9655 9696 9695 9419 + 9 9655 9656 9697 9696 9420 + 9 9656 9657 9698 9697 9421 + 9 9657 9658 9699 9698 9422 + 9 9658 9659 9700 9699 9423 + 9 9659 9660 9701 9700 9424 + 9 9660 9661 9702 9701 9425 + 9 9661 9662 9703 9702 9426 + 9 9662 9663 9704 9703 9427 + 9 9663 9664 9705 9704 9428 + 9 9664 9665 9706 9705 9429 + 9 9665 9666 9707 9706 9430 + 9 9666 9667 9708 9707 9431 + 9 9667 9668 9709 9708 9432 + 9 9668 9669 9710 9709 9433 + 9 9669 9670 9711 9710 9434 + 9 9670 9671 9712 9711 9435 + 9 9671 9672 9713 9712 9436 + 9 9672 9673 9714 9713 9437 + 9 9673 9674 9715 9714 9438 + 9 9674 9675 9716 9715 9439 + 9 9676 9677 9718 9717 9440 + 9 9677 9678 9719 9718 9441 + 9 9678 9679 9720 9719 9442 + 9 9679 9680 9721 9720 9443 + 9 9680 9681 9722 9721 9444 + 9 9681 9682 9723 9722 9445 + 9 9682 9683 9724 9723 9446 + 9 9683 9684 9725 9724 9447 + 9 9684 9685 9726 9725 9448 + 9 9685 9686 9727 9726 9449 + 9 9686 9687 9728 9727 9450 + 9 9687 9688 9729 9728 9451 + 9 9688 9689 9730 9729 9452 + 9 9689 9690 9731 9730 9453 + 9 9690 9691 9732 9731 9454 + 9 9691 9692 9733 9732 9455 + 9 9692 9693 9734 9733 9456 + 9 9693 9694 9735 9734 9457 + 9 9694 9695 9736 9735 9458 + 9 9695 9696 9737 9736 9459 + 9 9696 9697 9738 9737 9460 + 9 9697 9698 9739 9738 9461 + 9 9698 9699 9740 9739 9462 + 9 9699 9700 9741 9740 9463 + 9 9700 9701 9742 9741 9464 + 9 9701 9702 9743 9742 9465 + 9 9702 9703 9744 9743 9466 + 9 9703 9704 9745 9744 9467 + 9 9704 9705 9746 9745 9468 + 9 9705 9706 9747 9746 9469 + 9 9706 9707 9748 9747 9470 + 9 9707 9708 9749 9748 9471 + 9 9708 9709 9750 9749 9472 + 9 9709 9710 9751 9750 9473 + 9 9710 9711 9752 9751 9474 + 9 9711 9712 9753 9752 9475 + 9 9712 9713 9754 9753 9476 + 9 9713 9714 9755 9754 9477 + 9 9714 9715 9756 9755 9478 + 9 9715 9716 9757 9756 9479 + 9 9717 9718 9759 9758 9480 + 9 9718 9719 9760 9759 9481 + 9 9719 9720 9761 9760 9482 + 9 9720 9721 9762 9761 9483 + 9 9721 9722 9763 9762 9484 + 9 9722 9723 9764 9763 9485 + 9 9723 9724 9765 9764 9486 + 9 9724 9725 9766 9765 9487 + 9 9725 9726 9767 9766 9488 + 9 9726 9727 9768 9767 9489 + 9 9727 9728 9769 9768 9490 + 9 9728 9729 9770 9769 9491 + 9 9729 9730 9771 9770 9492 + 9 9730 9731 9772 9771 9493 + 9 9731 9732 9773 9772 9494 + 9 9732 9733 9774 9773 9495 + 9 9733 9734 9775 9774 9496 + 9 9734 9735 9776 9775 9497 + 9 9735 9736 9777 9776 9498 + 9 9736 9737 9778 9777 9499 + 9 9737 9738 9779 9778 9500 + 9 9738 9739 9780 9779 9501 + 9 9739 9740 9781 9780 9502 + 9 9740 9741 9782 9781 9503 + 9 9741 9742 9783 9782 9504 + 9 9742 9743 9784 9783 9505 + 9 9743 9744 9785 9784 9506 + 9 9744 9745 9786 9785 9507 + 9 9745 9746 9787 9786 9508 + 9 9746 9747 9788 9787 9509 + 9 9747 9748 9789 9788 9510 + 9 9748 9749 9790 9789 9511 + 9 9749 9750 9791 9790 9512 + 9 9750 9751 9792 9791 9513 + 9 9751 9752 9793 9792 9514 + 9 9752 9753 9794 9793 9515 + 9 9753 9754 9795 9794 9516 + 9 9754 9755 9796 9795 9517 + 9 9755 9756 9797 9796 9518 + 9 9756 9757 9798 9797 9519 + 9 9758 9759 9800 9799 9520 + 9 9759 9760 9801 9800 9521 + 9 9760 9761 9802 9801 9522 + 9 9761 9762 9803 9802 9523 + 9 9762 9763 9804 9803 9524 + 9 9763 9764 9805 9804 9525 + 9 9764 9765 9806 9805 9526 + 9 9765 9766 9807 9806 9527 + 9 9766 9767 9808 9807 9528 + 9 9767 9768 9809 9808 9529 + 9 9768 9769 9810 9809 9530 + 9 9769 9770 9811 9810 9531 + 9 9770 9771 9812 9811 9532 + 9 9771 9772 9813 9812 9533 + 9 9772 9773 9814 9813 9534 + 9 9773 9774 9815 9814 9535 + 9 9774 9775 9816 9815 9536 + 9 9775 9776 9817 9816 9537 + 9 9776 9777 9818 9817 9538 + 9 9777 9778 9819 9818 9539 + 9 9778 9779 9820 9819 9540 + 9 9779 9780 9821 9820 9541 + 9 9780 9781 9822 9821 9542 + 9 9781 9782 9823 9822 9543 + 9 9782 9783 9824 9823 9544 + 9 9783 9784 9825 9824 9545 + 9 9784 9785 9826 9825 9546 + 9 9785 9786 9827 9826 9547 + 9 9786 9787 9828 9827 9548 + 9 9787 9788 9829 9828 9549 + 9 9788 9789 9830 9829 9550 + 9 9789 9790 9831 9830 9551 + 9 9790 9791 9832 9831 9552 + 9 9791 9792 9833 9832 9553 + 9 9792 9793 9834 9833 9554 + 9 9793 9794 9835 9834 9555 + 9 9794 9795 9836 9835 9556 + 9 9795 9796 9837 9836 9557 + 9 9796 9797 9838 9837 9558 + 9 9797 9798 9839 9838 9559 + 9 9799 9800 9841 9840 9560 + 9 9800 9801 9842 9841 9561 + 9 9801 9802 9843 9842 9562 + 9 9802 9803 9844 9843 9563 + 9 9803 9804 9845 9844 9564 + 9 9804 9805 9846 9845 9565 + 9 9805 9806 9847 9846 9566 + 9 9806 9807 9848 9847 9567 + 9 9807 9808 9849 9848 9568 + 9 9808 9809 9850 9849 9569 + 9 9809 9810 9851 9850 9570 + 9 9810 9811 9852 9851 9571 + 9 9811 9812 9853 9852 9572 + 9 9812 9813 9854 9853 9573 + 9 9813 9814 9855 9854 9574 + 9 9814 9815 9856 9855 9575 + 9 9815 9816 9857 9856 9576 + 9 9816 9817 9858 9857 9577 + 9 9817 9818 9859 9858 9578 + 9 9818 9819 9860 9859 9579 + 9 9819 9820 9861 9860 9580 + 9 9820 9821 9862 9861 9581 + 9 9821 9822 9863 9862 9582 + 9 9822 9823 9864 9863 9583 + 9 9823 9824 9865 9864 9584 + 9 9824 9825 9866 9865 9585 + 9 9825 9826 9867 9866 9586 + 9 9826 9827 9868 9867 9587 + 9 9827 9828 9869 9868 9588 + 9 9828 9829 9870 9869 9589 + 9 9829 9830 9871 9870 9590 + 9 9830 9831 9872 9871 9591 + 9 9831 9832 9873 9872 9592 + 9 9832 9833 9874 9873 9593 + 9 9833 9834 9875 9874 9594 + 9 9834 9835 9876 9875 9595 + 9 9835 9836 9877 9876 9596 + 9 9836 9837 9878 9877 9597 + 9 9837 9838 9879 9878 9598 + 9 9838 9839 9880 9879 9599 + 9 9840 9841 9882 9881 9600 + 9 9841 9842 9883 9882 9601 + 9 9842 9843 9884 9883 9602 + 9 9843 9844 9885 9884 9603 + 9 9844 9845 9886 9885 9604 + 9 9845 9846 9887 9886 9605 + 9 9846 9847 9888 9887 9606 + 9 9847 9848 9889 9888 9607 + 9 9848 9849 9890 9889 9608 + 9 9849 9850 9891 9890 9609 + 9 9850 9851 9892 9891 9610 + 9 9851 9852 9893 9892 9611 + 9 9852 9853 9894 9893 9612 + 9 9853 9854 9895 9894 9613 + 9 9854 9855 9896 9895 9614 + 9 9855 9856 9897 9896 9615 + 9 9856 9857 9898 9897 9616 + 9 9857 9858 9899 9898 9617 + 9 9858 9859 9900 9899 9618 + 9 9859 9860 9901 9900 9619 + 9 9860 9861 9902 9901 9620 + 9 9861 9862 9903 9902 9621 + 9 9862 9863 9904 9903 9622 + 9 9863 9864 9905 9904 9623 + 9 9864 9865 9906 9905 9624 + 9 9865 9866 9907 9906 9625 + 9 9866 9867 9908 9907 9626 + 9 9867 9868 9909 9908 9627 + 9 9868 9869 9910 9909 9628 + 9 9869 9870 9911 9910 9629 + 9 9870 9871 9912 9911 9630 + 9 9871 9872 9913 9912 9631 + 9 9872 9873 9914 9913 9632 + 9 9873 9874 9915 9914 9633 + 9 9874 9875 9916 9915 9634 + 9 9875 9876 9917 9916 9635 + 9 9876 9877 9918 9917 9636 + 9 9877 9878 9919 9918 9637 + 9 9878 9879 9920 9919 9638 + 9 9879 9880 9921 9920 9639 + 9 9881 9882 9923 9922 9640 + 9 9882 9883 9924 9923 9641 + 9 9883 9884 9925 9924 9642 + 9 9884 9885 9926 9925 9643 + 9 9885 9886 9927 9926 9644 + 9 9886 9887 9928 9927 9645 + 9 9887 9888 9929 9928 9646 + 9 9888 9889 9930 9929 9647 + 9 9889 9890 9931 9930 9648 + 9 9890 9891 9932 9931 9649 + 9 9891 9892 9933 9932 9650 + 9 9892 9893 9934 9933 9651 + 9 9893 9894 9935 9934 9652 + 9 9894 9895 9936 9935 9653 + 9 9895 9896 9937 9936 9654 + 9 9896 9897 9938 9937 9655 + 9 9897 9898 9939 9938 9656 + 9 9898 9899 9940 9939 9657 + 9 9899 9900 9941 9940 9658 + 9 9900 9901 9942 9941 9659 + 9 9901 9902 9943 9942 9660 + 9 9902 9903 9944 9943 9661 + 9 9903 9904 9945 9944 9662 + 9 9904 9905 9946 9945 9663 + 9 9905 9906 9947 9946 9664 + 9 9906 9907 9948 9947 9665 + 9 9907 9908 9949 9948 9666 + 9 9908 9909 9950 9949 9667 + 9 9909 9910 9951 9950 9668 + 9 9910 9911 9952 9951 9669 + 9 9911 9912 9953 9952 9670 + 9 9912 9913 9954 9953 9671 + 9 9913 9914 9955 9954 9672 + 9 9914 9915 9956 9955 9673 + 9 9915 9916 9957 9956 9674 + 9 9916 9917 9958 9957 9675 + 9 9917 9918 9959 9958 9676 + 9 9918 9919 9960 9959 9677 + 9 9919 9920 9961 9960 9678 + 9 9920 9921 9962 9961 9679 + 9 9922 9923 9964 9963 9680 + 9 9923 9924 9965 9964 9681 + 9 9924 9925 9966 9965 9682 + 9 9925 9926 9967 9966 9683 + 9 9926 9927 9968 9967 9684 + 9 9927 9928 9969 9968 9685 + 9 9928 9929 9970 9969 9686 + 9 9929 9930 9971 9970 9687 + 9 9930 9931 9972 9971 9688 + 9 9931 9932 9973 9972 9689 + 9 9932 9933 9974 9973 9690 + 9 9933 9934 9975 9974 9691 + 9 9934 9935 9976 9975 9692 + 9 9935 9936 9977 9976 9693 + 9 9936 9937 9978 9977 9694 + 9 9937 9938 9979 9978 9695 + 9 9938 9939 9980 9979 9696 + 9 9939 9940 9981 9980 9697 + 9 9940 9941 9982 9981 9698 + 9 9941 9942 9983 9982 9699 + 9 9942 9943 9984 9983 9700 + 9 9943 9944 9985 9984 9701 + 9 9944 9945 9986 9985 9702 + 9 9945 9946 9987 9986 9703 + 9 9946 9947 9988 9987 9704 + 9 9947 9948 9989 9988 9705 + 9 9948 9949 9990 9989 9706 + 9 9949 9950 9991 9990 9707 + 9 9950 9951 9992 9991 9708 + 9 9951 9952 9993 9992 9709 + 9 9952 9953 9994 9993 9710 + 9 9953 9954 9995 9994 9711 + 9 9954 9955 9996 9995 9712 + 9 9955 9956 9997 9996 9713 + 9 9956 9957 9998 9997 9714 + 9 9957 9958 9999 9998 9715 + 9 9958 9959 10000 9999 9716 + 9 9959 9960 10001 10000 9717 + 9 9960 9961 10002 10001 9718 + 9 9961 9962 10003 10002 9719 + 9 9963 9964 10005 10004 9720 + 9 9964 9965 10006 10005 9721 + 9 9965 9966 10007 10006 9722 + 9 9966 9967 10008 10007 9723 + 9 9967 9968 10009 10008 9724 + 9 9968 9969 10010 10009 9725 + 9 9969 9970 10011 10010 9726 + 9 9970 9971 10012 10011 9727 + 9 9971 9972 10013 10012 9728 + 9 9972 9973 10014 10013 9729 + 9 9973 9974 10015 10014 9730 + 9 9974 9975 10016 10015 9731 + 9 9975 9976 10017 10016 9732 + 9 9976 9977 10018 10017 9733 + 9 9977 9978 10019 10018 9734 + 9 9978 9979 10020 10019 9735 + 9 9979 9980 10021 10020 9736 + 9 9980 9981 10022 10021 9737 + 9 9981 9982 10023 10022 9738 + 9 9982 9983 10024 10023 9739 + 9 9983 9984 10025 10024 9740 + 9 9984 9985 10026 10025 9741 + 9 9985 9986 10027 10026 9742 + 9 9986 9987 10028 10027 9743 + 9 9987 9988 10029 10028 9744 + 9 9988 9989 10030 10029 9745 + 9 9989 9990 10031 10030 9746 + 9 9990 9991 10032 10031 9747 + 9 9991 9992 10033 10032 9748 + 9 9992 9993 10034 10033 9749 + 9 9993 9994 10035 10034 9750 + 9 9994 9995 10036 10035 9751 + 9 9995 9996 10037 10036 9752 + 9 9996 9997 10038 10037 9753 + 9 9997 9998 10039 10038 9754 + 9 9998 9999 10040 10039 9755 + 9 9999 10000 10041 10040 9756 + 9 10000 10001 10042 10041 9757 + 9 10001 10002 10043 10042 9758 + 9 10002 10003 10044 10043 9759 + 9 10004 10005 10046 10045 9760 + 9 10005 10006 10047 10046 9761 + 9 10006 10007 10048 10047 9762 + 9 10007 10008 10049 10048 9763 + 9 10008 10009 10050 10049 9764 + 9 10009 10010 10051 10050 9765 + 9 10010 10011 10052 10051 9766 + 9 10011 10012 10053 10052 9767 + 9 10012 10013 10054 10053 9768 + 9 10013 10014 10055 10054 9769 + 9 10014 10015 10056 10055 9770 + 9 10015 10016 10057 10056 9771 + 9 10016 10017 10058 10057 9772 + 9 10017 10018 10059 10058 9773 + 9 10018 10019 10060 10059 9774 + 9 10019 10020 10061 10060 9775 + 9 10020 10021 10062 10061 9776 + 9 10021 10022 10063 10062 9777 + 9 10022 10023 10064 10063 9778 + 9 10023 10024 10065 10064 9779 + 9 10024 10025 10066 10065 9780 + 9 10025 10026 10067 10066 9781 + 9 10026 10027 10068 10067 9782 + 9 10027 10028 10069 10068 9783 + 9 10028 10029 10070 10069 9784 + 9 10029 10030 10071 10070 9785 + 9 10030 10031 10072 10071 9786 + 9 10031 10032 10073 10072 9787 + 9 10032 10033 10074 10073 9788 + 9 10033 10034 10075 10074 9789 + 9 10034 10035 10076 10075 9790 + 9 10035 10036 10077 10076 9791 + 9 10036 10037 10078 10077 9792 + 9 10037 10038 10079 10078 9793 + 9 10038 10039 10080 10079 9794 + 9 10039 10040 10081 10080 9795 + 9 10040 10041 10082 10081 9796 + 9 10041 10042 10083 10082 9797 + 9 10042 10043 10084 10083 9798 + 9 10043 10044 10085 10084 9799 + 9 10045 10046 10087 10086 9800 + 9 10046 10047 10088 10087 9801 + 9 10047 10048 10089 10088 9802 + 9 10048 10049 10090 10089 9803 + 9 10049 10050 10091 10090 9804 + 9 10050 10051 10092 10091 9805 + 9 10051 10052 10093 10092 9806 + 9 10052 10053 10094 10093 9807 + 9 10053 10054 10095 10094 9808 + 9 10054 10055 10096 10095 9809 + 9 10055 10056 10097 10096 9810 + 9 10056 10057 10098 10097 9811 + 9 10057 10058 10099 10098 9812 + 9 10058 10059 10100 10099 9813 + 9 10059 10060 10101 10100 9814 + 9 10060 10061 10102 10101 9815 + 9 10061 10062 10103 10102 9816 + 9 10062 10063 10104 10103 9817 + 9 10063 10064 10105 10104 9818 + 9 10064 10065 10106 10105 9819 + 9 10065 10066 10107 10106 9820 + 9 10066 10067 10108 10107 9821 + 9 10067 10068 10109 10108 9822 + 9 10068 10069 10110 10109 9823 + 9 10069 10070 10111 10110 9824 + 9 10070 10071 10112 10111 9825 + 9 10071 10072 10113 10112 9826 + 9 10072 10073 10114 10113 9827 + 9 10073 10074 10115 10114 9828 + 9 10074 10075 10116 10115 9829 + 9 10075 10076 10117 10116 9830 + 9 10076 10077 10118 10117 9831 + 9 10077 10078 10119 10118 9832 + 9 10078 10079 10120 10119 9833 + 9 10079 10080 10121 10120 9834 + 9 10080 10081 10122 10121 9835 + 9 10081 10082 10123 10122 9836 + 9 10082 10083 10124 10123 9837 + 9 10083 10084 10125 10124 9838 + 9 10084 10085 10126 10125 9839 + 9 10086 10087 10128 10127 9840 + 9 10087 10088 10129 10128 9841 + 9 10088 10089 10130 10129 9842 + 9 10089 10090 10131 10130 9843 + 9 10090 10091 10132 10131 9844 + 9 10091 10092 10133 10132 9845 + 9 10092 10093 10134 10133 9846 + 9 10093 10094 10135 10134 9847 + 9 10094 10095 10136 10135 9848 + 9 10095 10096 10137 10136 9849 + 9 10096 10097 10138 10137 9850 + 9 10097 10098 10139 10138 9851 + 9 10098 10099 10140 10139 9852 + 9 10099 10100 10141 10140 9853 + 9 10100 10101 10142 10141 9854 + 9 10101 10102 10143 10142 9855 + 9 10102 10103 10144 10143 9856 + 9 10103 10104 10145 10144 9857 + 9 10104 10105 10146 10145 9858 + 9 10105 10106 10147 10146 9859 + 9 10106 10107 10148 10147 9860 + 9 10107 10108 10149 10148 9861 + 9 10108 10109 10150 10149 9862 + 9 10109 10110 10151 10150 9863 + 9 10110 10111 10152 10151 9864 + 9 10111 10112 10153 10152 9865 + 9 10112 10113 10154 10153 9866 + 9 10113 10114 10155 10154 9867 + 9 10114 10115 10156 10155 9868 + 9 10115 10116 10157 10156 9869 + 9 10116 10117 10158 10157 9870 + 9 10117 10118 10159 10158 9871 + 9 10118 10119 10160 10159 9872 + 9 10119 10120 10161 10160 9873 + 9 10120 10121 10162 10161 9874 + 9 10121 10122 10163 10162 9875 + 9 10122 10123 10164 10163 9876 + 9 10123 10124 10165 10164 9877 + 9 10124 10125 10166 10165 9878 + 9 10125 10126 10167 10166 9879 + 9 10127 10128 10169 10168 9880 + 9 10128 10129 10170 10169 9881 + 9 10129 10130 10171 10170 9882 + 9 10130 10131 10172 10171 9883 + 9 10131 10132 10173 10172 9884 + 9 10132 10133 10174 10173 9885 + 9 10133 10134 10175 10174 9886 + 9 10134 10135 10176 10175 9887 + 9 10135 10136 10177 10176 9888 + 9 10136 10137 10178 10177 9889 + 9 10137 10138 10179 10178 9890 + 9 10138 10139 10180 10179 9891 + 9 10139 10140 10181 10180 9892 + 9 10140 10141 10182 10181 9893 + 9 10141 10142 10183 10182 9894 + 9 10142 10143 10184 10183 9895 + 9 10143 10144 10185 10184 9896 + 9 10144 10145 10186 10185 9897 + 9 10145 10146 10187 10186 9898 + 9 10146 10147 10188 10187 9899 + 9 10147 10148 10189 10188 9900 + 9 10148 10149 10190 10189 9901 + 9 10149 10150 10191 10190 9902 + 9 10150 10151 10192 10191 9903 + 9 10151 10152 10193 10192 9904 + 9 10152 10153 10194 10193 9905 + 9 10153 10154 10195 10194 9906 + 9 10154 10155 10196 10195 9907 + 9 10155 10156 10197 10196 9908 + 9 10156 10157 10198 10197 9909 + 9 10157 10158 10199 10198 9910 + 9 10158 10159 10200 10199 9911 + 9 10159 10160 10201 10200 9912 + 9 10160 10161 10202 10201 9913 + 9 10161 10162 10203 10202 9914 + 9 10162 10163 10204 10203 9915 + 9 10163 10164 10205 10204 9916 + 9 10164 10165 10206 10205 9917 + 9 10165 10166 10207 10206 9918 + 9 10166 10167 10208 10207 9919 + 9 10168 10169 10210 10209 9920 + 9 10169 10170 10211 10210 9921 + 9 10170 10171 10212 10211 9922 + 9 10171 10172 10213 10212 9923 + 9 10172 10173 10214 10213 9924 + 9 10173 10174 10215 10214 9925 + 9 10174 10175 10216 10215 9926 + 9 10175 10176 10217 10216 9927 + 9 10176 10177 10218 10217 9928 + 9 10177 10178 10219 10218 9929 + 9 10178 10179 10220 10219 9930 + 9 10179 10180 10221 10220 9931 + 9 10180 10181 10222 10221 9932 + 9 10181 10182 10223 10222 9933 + 9 10182 10183 10224 10223 9934 + 9 10183 10184 10225 10224 9935 + 9 10184 10185 10226 10225 9936 + 9 10185 10186 10227 10226 9937 + 9 10186 10187 10228 10227 9938 + 9 10187 10188 10229 10228 9939 + 9 10188 10189 10230 10229 9940 + 9 10189 10190 10231 10230 9941 + 9 10190 10191 10232 10231 9942 + 9 10191 10192 10233 10232 9943 + 9 10192 10193 10234 10233 9944 + 9 10193 10194 10235 10234 9945 + 9 10194 10195 10236 10235 9946 + 9 10195 10196 10237 10236 9947 + 9 10196 10197 10238 10237 9948 + 9 10197 10198 10239 10238 9949 + 9 10198 10199 10240 10239 9950 + 9 10199 10200 10241 10240 9951 + 9 10200 10201 10242 10241 9952 + 9 10201 10202 10243 10242 9953 + 9 10202 10203 10244 10243 9954 + 9 10203 10204 10245 10244 9955 + 9 10204 10205 10246 10245 9956 + 9 10205 10206 10247 10246 9957 + 9 10206 10207 10248 10247 9958 + 9 10207 10208 10249 10248 9959 + 9 10209 10210 10251 10250 9960 + 9 10210 10211 10252 10251 9961 + 9 10211 10212 10253 10252 9962 + 9 10212 10213 10254 10253 9963 + 9 10213 10214 10255 10254 9964 + 9 10214 10215 10256 10255 9965 + 9 10215 10216 10257 10256 9966 + 9 10216 10217 10258 10257 9967 + 9 10217 10218 10259 10258 9968 + 9 10218 10219 10260 10259 9969 + 9 10219 10220 10261 10260 9970 + 9 10220 10221 10262 10261 9971 + 9 10221 10222 10263 10262 9972 + 9 10222 10223 10264 10263 9973 + 9 10223 10224 10265 10264 9974 + 9 10224 10225 10266 10265 9975 + 9 10225 10226 10267 10266 9976 + 9 10226 10227 10268 10267 9977 + 9 10227 10228 10269 10268 9978 + 9 10228 10229 10270 10269 9979 + 9 10229 10230 10271 10270 9980 + 9 10230 10231 10272 10271 9981 + 9 10231 10232 10273 10272 9982 + 9 10232 10233 10274 10273 9983 + 9 10233 10234 10275 10274 9984 + 9 10234 10235 10276 10275 9985 + 9 10235 10236 10277 10276 9986 + 9 10236 10237 10278 10277 9987 + 9 10237 10238 10279 10278 9988 + 9 10238 10239 10280 10279 9989 + 9 10239 10240 10281 10280 9990 + 9 10240 10241 10282 10281 9991 + 9 10241 10242 10283 10282 9992 + 9 10242 10243 10284 10283 9993 + 9 10243 10244 10285 10284 9994 + 9 10244 10245 10286 10285 9995 + 9 10245 10246 10287 10286 9996 + 9 10246 10247 10288 10287 9997 + 9 10247 10248 10289 10288 9998 + 9 10248 10249 10290 10289 9999 + 9 10250 10251 10292 10291 10000 + 9 10251 10252 10293 10292 10001 + 9 10252 10253 10294 10293 10002 + 9 10253 10254 10295 10294 10003 + 9 10254 10255 10296 10295 10004 + 9 10255 10256 10297 10296 10005 + 9 10256 10257 10298 10297 10006 + 9 10257 10258 10299 10298 10007 + 9 10258 10259 10300 10299 10008 + 9 10259 10260 10301 10300 10009 + 9 10260 10261 10302 10301 10010 + 9 10261 10262 10303 10302 10011 + 9 10262 10263 10304 10303 10012 + 9 10263 10264 10305 10304 10013 + 9 10264 10265 10306 10305 10014 + 9 10265 10266 10307 10306 10015 + 9 10266 10267 10308 10307 10016 + 9 10267 10268 10309 10308 10017 + 9 10268 10269 10310 10309 10018 + 9 10269 10270 10311 10310 10019 + 9 10270 10271 10312 10311 10020 + 9 10271 10272 10313 10312 10021 + 9 10272 10273 10314 10313 10022 + 9 10273 10274 10315 10314 10023 + 9 10274 10275 10316 10315 10024 + 9 10275 10276 10317 10316 10025 + 9 10276 10277 10318 10317 10026 + 9 10277 10278 10319 10318 10027 + 9 10278 10279 10320 10319 10028 + 9 10279 10280 10321 10320 10029 + 9 10280 10281 10322 10321 10030 + 9 10281 10282 10323 10322 10031 + 9 10282 10283 10324 10323 10032 + 9 10283 10284 10325 10324 10033 + 9 10284 10285 10326 10325 10034 + 9 10285 10286 10327 10326 10035 + 9 10286 10287 10328 10327 10036 + 9 10287 10288 10329 10328 10037 + 9 10288 10289 10330 10329 10038 + 9 10289 10290 10331 10330 10039 + 9 10291 10292 10333 10332 10040 + 9 10292 10293 10334 10333 10041 + 9 10293 10294 10335 10334 10042 + 9 10294 10295 10336 10335 10043 + 9 10295 10296 10337 10336 10044 + 9 10296 10297 10338 10337 10045 + 9 10297 10298 10339 10338 10046 + 9 10298 10299 10340 10339 10047 + 9 10299 10300 10341 10340 10048 + 9 10300 10301 10342 10341 10049 + 9 10301 10302 10343 10342 10050 + 9 10302 10303 10344 10343 10051 + 9 10303 10304 10345 10344 10052 + 9 10304 10305 10346 10345 10053 + 9 10305 10306 10347 10346 10054 + 9 10306 10307 10348 10347 10055 + 9 10307 10308 10349 10348 10056 + 9 10308 10309 10350 10349 10057 + 9 10309 10310 10351 10350 10058 + 9 10310 10311 10352 10351 10059 + 9 10311 10312 10353 10352 10060 + 9 10312 10313 10354 10353 10061 + 9 10313 10314 10355 10354 10062 + 9 10314 10315 10356 10355 10063 + 9 10315 10316 10357 10356 10064 + 9 10316 10317 10358 10357 10065 + 9 10317 10318 10359 10358 10066 + 9 10318 10319 10360 10359 10067 + 9 10319 10320 10361 10360 10068 + 9 10320 10321 10362 10361 10069 + 9 10321 10322 10363 10362 10070 + 9 10322 10323 10364 10363 10071 + 9 10323 10324 10365 10364 10072 + 9 10324 10325 10366 10365 10073 + 9 10325 10326 10367 10366 10074 + 9 10326 10327 10368 10367 10075 + 9 10327 10328 10369 10368 10076 + 9 10328 10329 10370 10369 10077 + 9 10329 10330 10371 10370 10078 + 9 10330 10331 10372 10371 10079 + 9 10332 10333 10374 10373 10080 + 9 10333 10334 10375 10374 10081 + 9 10334 10335 10376 10375 10082 + 9 10335 10336 10377 10376 10083 + 9 10336 10337 10378 10377 10084 + 9 10337 10338 10379 10378 10085 + 9 10338 10339 10380 10379 10086 + 9 10339 10340 10381 10380 10087 + 9 10340 10341 10382 10381 10088 + 9 10341 10342 10383 10382 10089 + 9 10342 10343 10384 10383 10090 + 9 10343 10344 10385 10384 10091 + 9 10344 10345 10386 10385 10092 + 9 10345 10346 10387 10386 10093 + 9 10346 10347 10388 10387 10094 + 9 10347 10348 10389 10388 10095 + 9 10348 10349 10390 10389 10096 + 9 10349 10350 10391 10390 10097 + 9 10350 10351 10392 10391 10098 + 9 10351 10352 10393 10392 10099 + 9 10352 10353 10394 10393 10100 + 9 10353 10354 10395 10394 10101 + 9 10354 10355 10396 10395 10102 + 9 10355 10356 10397 10396 10103 + 9 10356 10357 10398 10397 10104 + 9 10357 10358 10399 10398 10105 + 9 10358 10359 10400 10399 10106 + 9 10359 10360 10401 10400 10107 + 9 10360 10361 10402 10401 10108 + 9 10361 10362 10403 10402 10109 + 9 10362 10363 10404 10403 10110 + 9 10363 10364 10405 10404 10111 + 9 10364 10365 10406 10405 10112 + 9 10365 10366 10407 10406 10113 + 9 10366 10367 10408 10407 10114 + 9 10367 10368 10409 10408 10115 + 9 10368 10369 10410 10409 10116 + 9 10369 10370 10411 10410 10117 + 9 10370 10371 10412 10411 10118 + 9 10371 10372 10413 10412 10119 + 9 10373 10374 10415 10414 10120 + 9 10374 10375 10416 10415 10121 + 9 10375 10376 10417 10416 10122 + 9 10376 10377 10418 10417 10123 + 9 10377 10378 10419 10418 10124 + 9 10378 10379 10420 10419 10125 + 9 10379 10380 10421 10420 10126 + 9 10380 10381 10422 10421 10127 + 9 10381 10382 10423 10422 10128 + 9 10382 10383 10424 10423 10129 + 9 10383 10384 10425 10424 10130 + 9 10384 10385 10426 10425 10131 + 9 10385 10386 10427 10426 10132 + 9 10386 10387 10428 10427 10133 + 9 10387 10388 10429 10428 10134 + 9 10388 10389 10430 10429 10135 + 9 10389 10390 10431 10430 10136 + 9 10390 10391 10432 10431 10137 + 9 10391 10392 10433 10432 10138 + 9 10392 10393 10434 10433 10139 + 9 10393 10394 10435 10434 10140 + 9 10394 10395 10436 10435 10141 + 9 10395 10396 10437 10436 10142 + 9 10396 10397 10438 10437 10143 + 9 10397 10398 10439 10438 10144 + 9 10398 10399 10440 10439 10145 + 9 10399 10400 10441 10440 10146 + 9 10400 10401 10442 10441 10147 + 9 10401 10402 10443 10442 10148 + 9 10402 10403 10444 10443 10149 + 9 10403 10404 10445 10444 10150 + 9 10404 10405 10446 10445 10151 + 9 10405 10406 10447 10446 10152 + 9 10406 10407 10448 10447 10153 + 9 10407 10408 10449 10448 10154 + 9 10408 10409 10450 10449 10155 + 9 10409 10410 10451 10450 10156 + 9 10410 10411 10452 10451 10157 + 9 10411 10412 10453 10452 10158 + 9 10412 10413 10454 10453 10159 + 9 10414 10415 10456 10455 10160 + 9 10415 10416 10457 10456 10161 + 9 10416 10417 10458 10457 10162 + 9 10417 10418 10459 10458 10163 + 9 10418 10419 10460 10459 10164 + 9 10419 10420 10461 10460 10165 + 9 10420 10421 10462 10461 10166 + 9 10421 10422 10463 10462 10167 + 9 10422 10423 10464 10463 10168 + 9 10423 10424 10465 10464 10169 + 9 10424 10425 10466 10465 10170 + 9 10425 10426 10467 10466 10171 + 9 10426 10427 10468 10467 10172 + 9 10427 10428 10469 10468 10173 + 9 10428 10429 10470 10469 10174 + 9 10429 10430 10471 10470 10175 + 9 10430 10431 10472 10471 10176 + 9 10431 10432 10473 10472 10177 + 9 10432 10433 10474 10473 10178 + 9 10433 10434 10475 10474 10179 + 9 10434 10435 10476 10475 10180 + 9 10435 10436 10477 10476 10181 + 9 10436 10437 10478 10477 10182 + 9 10437 10438 10479 10478 10183 + 9 10438 10439 10480 10479 10184 + 9 10439 10440 10481 10480 10185 + 9 10440 10441 10482 10481 10186 + 9 10441 10442 10483 10482 10187 + 9 10442 10443 10484 10483 10188 + 9 10443 10444 10485 10484 10189 + 9 10444 10445 10486 10485 10190 + 9 10445 10446 10487 10486 10191 + 9 10446 10447 10488 10487 10192 + 9 10447 10448 10489 10488 10193 + 9 10448 10449 10490 10489 10194 + 9 10449 10450 10491 10490 10195 + 9 10450 10451 10492 10491 10196 + 9 10451 10452 10493 10492 10197 + 9 10452 10453 10494 10493 10198 + 9 10453 10454 10495 10494 10199 + 9 10455 10456 10497 10496 10200 + 9 10456 10457 10498 10497 10201 + 9 10457 10458 10499 10498 10202 + 9 10458 10459 10500 10499 10203 + 9 10459 10460 10501 10500 10204 + 9 10460 10461 10502 10501 10205 + 9 10461 10462 10503 10502 10206 + 9 10462 10463 10504 10503 10207 + 9 10463 10464 10505 10504 10208 + 9 10464 10465 10506 10505 10209 + 9 10465 10466 10507 10506 10210 + 9 10466 10467 10508 10507 10211 + 9 10467 10468 10509 10508 10212 + 9 10468 10469 10510 10509 10213 + 9 10469 10470 10511 10510 10214 + 9 10470 10471 10512 10511 10215 + 9 10471 10472 10513 10512 10216 + 9 10472 10473 10514 10513 10217 + 9 10473 10474 10515 10514 10218 + 9 10474 10475 10516 10515 10219 + 9 10475 10476 10517 10516 10220 + 9 10476 10477 10518 10517 10221 + 9 10477 10478 10519 10518 10222 + 9 10478 10479 10520 10519 10223 + 9 10479 10480 10521 10520 10224 + 9 10480 10481 10522 10521 10225 + 9 10481 10482 10523 10522 10226 + 9 10482 10483 10524 10523 10227 + 9 10483 10484 10525 10524 10228 + 9 10484 10485 10526 10525 10229 + 9 10485 10486 10527 10526 10230 + 9 10486 10487 10528 10527 10231 + 9 10487 10488 10529 10528 10232 + 9 10488 10489 10530 10529 10233 + 9 10489 10490 10531 10530 10234 + 9 10490 10491 10532 10531 10235 + 9 10491 10492 10533 10532 10236 + 9 10492 10493 10534 10533 10237 + 9 10493 10494 10535 10534 10238 + 9 10494 10495 10536 10535 10239 + 9 10496 10497 10538 10537 10240 + 9 10497 10498 10539 10538 10241 + 9 10498 10499 10540 10539 10242 + 9 10499 10500 10541 10540 10243 + 9 10500 10501 10542 10541 10244 + 9 10501 10502 10543 10542 10245 + 9 10502 10503 10544 10543 10246 + 9 10503 10504 10545 10544 10247 + 9 10504 10505 10546 10545 10248 + 9 10505 10506 10547 10546 10249 + 9 10506 10507 10548 10547 10250 + 9 10507 10508 10549 10548 10251 + 9 10508 10509 10550 10549 10252 + 9 10509 10510 10551 10550 10253 + 9 10510 10511 10552 10551 10254 + 9 10511 10512 10553 10552 10255 + 9 10512 10513 10554 10553 10256 + 9 10513 10514 10555 10554 10257 + 9 10514 10515 10556 10555 10258 + 9 10515 10516 10557 10556 10259 + 9 10516 10517 10558 10557 10260 + 9 10517 10518 10559 10558 10261 + 9 10518 10519 10560 10559 10262 + 9 10519 10520 10561 10560 10263 + 9 10520 10521 10562 10561 10264 + 9 10521 10522 10563 10562 10265 + 9 10522 10523 10564 10563 10266 + 9 10523 10524 10565 10564 10267 + 9 10524 10525 10566 10565 10268 + 9 10525 10526 10567 10566 10269 + 9 10526 10527 10568 10567 10270 + 9 10527 10528 10569 10568 10271 + 9 10528 10529 10570 10569 10272 + 9 10529 10530 10571 10570 10273 + 9 10530 10531 10572 10571 10274 + 9 10531 10532 10573 10572 10275 + 9 10532 10533 10574 10573 10276 + 9 10533 10534 10575 10574 10277 + 9 10534 10535 10576 10575 10278 + 9 10535 10536 10577 10576 10279 + 9 10537 10538 10579 10578 10280 + 9 10538 10539 10580 10579 10281 + 9 10539 10540 10581 10580 10282 + 9 10540 10541 10582 10581 10283 + 9 10541 10542 10583 10582 10284 + 9 10542 10543 10584 10583 10285 + 9 10543 10544 10585 10584 10286 + 9 10544 10545 10586 10585 10287 + 9 10545 10546 10587 10586 10288 + 9 10546 10547 10588 10587 10289 + 9 10547 10548 10589 10588 10290 + 9 10548 10549 10590 10589 10291 + 9 10549 10550 10591 10590 10292 + 9 10550 10551 10592 10591 10293 + 9 10551 10552 10593 10592 10294 + 9 10552 10553 10594 10593 10295 + 9 10553 10554 10595 10594 10296 + 9 10554 10555 10596 10595 10297 + 9 10555 10556 10597 10596 10298 + 9 10556 10557 10598 10597 10299 + 9 10557 10558 10599 10598 10300 + 9 10558 10559 10600 10599 10301 + 9 10559 10560 10601 10600 10302 + 9 10560 10561 10602 10601 10303 + 9 10561 10562 10603 10602 10304 + 9 10562 10563 10604 10603 10305 + 9 10563 10564 10605 10604 10306 + 9 10564 10565 10606 10605 10307 + 9 10565 10566 10607 10606 10308 + 9 10566 10567 10608 10607 10309 + 9 10567 10568 10609 10608 10310 + 9 10568 10569 10610 10609 10311 + 9 10569 10570 10611 10610 10312 + 9 10570 10571 10612 10611 10313 + 9 10571 10572 10613 10612 10314 + 9 10572 10573 10614 10613 10315 + 9 10573 10574 10615 10614 10316 + 9 10574 10575 10616 10615 10317 + 9 10575 10576 10617 10616 10318 + 9 10576 10577 10618 10617 10319 + 9 10578 10579 10620 10619 10320 + 9 10579 10580 10621 10620 10321 + 9 10580 10581 10622 10621 10322 + 9 10581 10582 10623 10622 10323 + 9 10582 10583 10624 10623 10324 + 9 10583 10584 10625 10624 10325 + 9 10584 10585 10626 10625 10326 + 9 10585 10586 10627 10626 10327 + 9 10586 10587 10628 10627 10328 + 9 10587 10588 10629 10628 10329 + 9 10588 10589 10630 10629 10330 + 9 10589 10590 10631 10630 10331 + 9 10590 10591 10632 10631 10332 + 9 10591 10592 10633 10632 10333 + 9 10592 10593 10634 10633 10334 + 9 10593 10594 10635 10634 10335 + 9 10594 10595 10636 10635 10336 + 9 10595 10596 10637 10636 10337 + 9 10596 10597 10638 10637 10338 + 9 10597 10598 10639 10638 10339 + 9 10598 10599 10640 10639 10340 + 9 10599 10600 10641 10640 10341 + 9 10600 10601 10642 10641 10342 + 9 10601 10602 10643 10642 10343 + 9 10602 10603 10644 10643 10344 + 9 10603 10604 10645 10644 10345 + 9 10604 10605 10646 10645 10346 + 9 10605 10606 10647 10646 10347 + 9 10606 10607 10648 10647 10348 + 9 10607 10608 10649 10648 10349 + 9 10608 10609 10650 10649 10350 + 9 10609 10610 10651 10650 10351 + 9 10610 10611 10652 10651 10352 + 9 10611 10612 10653 10652 10353 + 9 10612 10613 10654 10653 10354 + 9 10613 10614 10655 10654 10355 + 9 10614 10615 10656 10655 10356 + 9 10615 10616 10657 10656 10357 + 9 10616 10617 10658 10657 10358 + 9 10617 10618 10659 10658 10359 + 9 10619 10620 10661 10660 10360 + 9 10620 10621 10662 10661 10361 + 9 10621 10622 10663 10662 10362 + 9 10622 10623 10664 10663 10363 + 9 10623 10624 10665 10664 10364 + 9 10624 10625 10666 10665 10365 + 9 10625 10626 10667 10666 10366 + 9 10626 10627 10668 10667 10367 + 9 10627 10628 10669 10668 10368 + 9 10628 10629 10670 10669 10369 + 9 10629 10630 10671 10670 10370 + 9 10630 10631 10672 10671 10371 + 9 10631 10632 10673 10672 10372 + 9 10632 10633 10674 10673 10373 + 9 10633 10634 10675 10674 10374 + 9 10634 10635 10676 10675 10375 + 9 10635 10636 10677 10676 10376 + 9 10636 10637 10678 10677 10377 + 9 10637 10638 10679 10678 10378 + 9 10638 10639 10680 10679 10379 + 9 10639 10640 10681 10680 10380 + 9 10640 10641 10682 10681 10381 + 9 10641 10642 10683 10682 10382 + 9 10642 10643 10684 10683 10383 + 9 10643 10644 10685 10684 10384 + 9 10644 10645 10686 10685 10385 + 9 10645 10646 10687 10686 10386 + 9 10646 10647 10688 10687 10387 + 9 10647 10648 10689 10688 10388 + 9 10648 10649 10690 10689 10389 + 9 10649 10650 10691 10690 10390 + 9 10650 10651 10692 10691 10391 + 9 10651 10652 10693 10692 10392 + 9 10652 10653 10694 10693 10393 + 9 10653 10654 10695 10694 10394 + 9 10654 10655 10696 10695 10395 + 9 10655 10656 10697 10696 10396 + 9 10656 10657 10698 10697 10397 + 9 10657 10658 10699 10698 10398 + 9 10658 10659 10700 10699 10399 + 9 10660 10661 10702 10701 10400 + 9 10661 10662 10703 10702 10401 + 9 10662 10663 10704 10703 10402 + 9 10663 10664 10705 10704 10403 + 9 10664 10665 10706 10705 10404 + 9 10665 10666 10707 10706 10405 + 9 10666 10667 10708 10707 10406 + 9 10667 10668 10709 10708 10407 + 9 10668 10669 10710 10709 10408 + 9 10669 10670 10711 10710 10409 + 9 10670 10671 10712 10711 10410 + 9 10671 10672 10713 10712 10411 + 9 10672 10673 10714 10713 10412 + 9 10673 10674 10715 10714 10413 + 9 10674 10675 10716 10715 10414 + 9 10675 10676 10717 10716 10415 + 9 10676 10677 10718 10717 10416 + 9 10677 10678 10719 10718 10417 + 9 10678 10679 10720 10719 10418 + 9 10679 10680 10721 10720 10419 + 9 10680 10681 10722 10721 10420 + 9 10681 10682 10723 10722 10421 + 9 10682 10683 10724 10723 10422 + 9 10683 10684 10725 10724 10423 + 9 10684 10685 10726 10725 10424 + 9 10685 10686 10727 10726 10425 + 9 10686 10687 10728 10727 10426 + 9 10687 10688 10729 10728 10427 + 9 10688 10689 10730 10729 10428 + 9 10689 10690 10731 10730 10429 + 9 10690 10691 10732 10731 10430 + 9 10691 10692 10733 10732 10431 + 9 10692 10693 10734 10733 10432 + 9 10693 10694 10735 10734 10433 + 9 10694 10695 10736 10735 10434 + 9 10695 10696 10737 10736 10435 + 9 10696 10697 10738 10737 10436 + 9 10697 10698 10739 10738 10437 + 9 10698 10699 10740 10739 10438 + 9 10699 10700 10741 10740 10439 + 9 10701 10702 10743 10742 10440 + 9 10702 10703 10744 10743 10441 + 9 10703 10704 10745 10744 10442 + 9 10704 10705 10746 10745 10443 + 9 10705 10706 10747 10746 10444 + 9 10706 10707 10748 10747 10445 + 9 10707 10708 10749 10748 10446 + 9 10708 10709 10750 10749 10447 + 9 10709 10710 10751 10750 10448 + 9 10710 10711 10752 10751 10449 + 9 10711 10712 10753 10752 10450 + 9 10712 10713 10754 10753 10451 + 9 10713 10714 10755 10754 10452 + 9 10714 10715 10756 10755 10453 + 9 10715 10716 10757 10756 10454 + 9 10716 10717 10758 10757 10455 + 9 10717 10718 10759 10758 10456 + 9 10718 10719 10760 10759 10457 + 9 10719 10720 10761 10760 10458 + 9 10720 10721 10762 10761 10459 + 9 10721 10722 10763 10762 10460 + 9 10722 10723 10764 10763 10461 + 9 10723 10724 10765 10764 10462 + 9 10724 10725 10766 10765 10463 + 9 10725 10726 10767 10766 10464 + 9 10726 10727 10768 10767 10465 + 9 10727 10728 10769 10768 10466 + 9 10728 10729 10770 10769 10467 + 9 10729 10730 10771 10770 10468 + 9 10730 10731 10772 10771 10469 + 9 10731 10732 10773 10772 10470 + 9 10732 10733 10774 10773 10471 + 9 10733 10734 10775 10774 10472 + 9 10734 10735 10776 10775 10473 + 9 10735 10736 10777 10776 10474 + 9 10736 10737 10778 10777 10475 + 9 10737 10738 10779 10778 10476 + 9 10738 10739 10780 10779 10477 + 9 10739 10740 10781 10780 10478 + 9 10740 10741 10782 10781 10479 + 9 10742 10743 10784 10783 10480 + 9 10743 10744 10785 10784 10481 + 9 10744 10745 10786 10785 10482 + 9 10745 10746 10787 10786 10483 + 9 10746 10747 10788 10787 10484 + 9 10747 10748 10789 10788 10485 + 9 10748 10749 10790 10789 10486 + 9 10749 10750 10791 10790 10487 + 9 10750 10751 10792 10791 10488 + 9 10751 10752 10793 10792 10489 + 9 10752 10753 10794 10793 10490 + 9 10753 10754 10795 10794 10491 + 9 10754 10755 10796 10795 10492 + 9 10755 10756 10797 10796 10493 + 9 10756 10757 10798 10797 10494 + 9 10757 10758 10799 10798 10495 + 9 10758 10759 10800 10799 10496 + 9 10759 10760 10801 10800 10497 + 9 10760 10761 10802 10801 10498 + 9 10761 10762 10803 10802 10499 + 9 10762 10763 10804 10803 10500 + 9 10763 10764 10805 10804 10501 + 9 10764 10765 10806 10805 10502 + 9 10765 10766 10807 10806 10503 + 9 10766 10767 10808 10807 10504 + 9 10767 10768 10809 10808 10505 + 9 10768 10769 10810 10809 10506 + 9 10769 10770 10811 10810 10507 + 9 10770 10771 10812 10811 10508 + 9 10771 10772 10813 10812 10509 + 9 10772 10773 10814 10813 10510 + 9 10773 10774 10815 10814 10511 + 9 10774 10775 10816 10815 10512 + 9 10775 10776 10817 10816 10513 + 9 10776 10777 10818 10817 10514 + 9 10777 10778 10819 10818 10515 + 9 10778 10779 10820 10819 10516 + 9 10779 10780 10821 10820 10517 + 9 10780 10781 10822 10821 10518 + 9 10781 10782 10823 10822 10519 + 9 10783 10784 10825 10824 10520 + 9 10784 10785 10826 10825 10521 + 9 10785 10786 10827 10826 10522 + 9 10786 10787 10828 10827 10523 + 9 10787 10788 10829 10828 10524 + 9 10788 10789 10830 10829 10525 + 9 10789 10790 10831 10830 10526 + 9 10790 10791 10832 10831 10527 + 9 10791 10792 10833 10832 10528 + 9 10792 10793 10834 10833 10529 + 9 10793 10794 10835 10834 10530 + 9 10794 10795 10836 10835 10531 + 9 10795 10796 10837 10836 10532 + 9 10796 10797 10838 10837 10533 + 9 10797 10798 10839 10838 10534 + 9 10798 10799 10840 10839 10535 + 9 10799 10800 10841 10840 10536 + 9 10800 10801 10842 10841 10537 + 9 10801 10802 10843 10842 10538 + 9 10802 10803 10844 10843 10539 + 9 10803 10804 10845 10844 10540 + 9 10804 10805 10846 10845 10541 + 9 10805 10806 10847 10846 10542 + 9 10806 10807 10848 10847 10543 + 9 10807 10808 10849 10848 10544 + 9 10808 10809 10850 10849 10545 + 9 10809 10810 10851 10850 10546 + 9 10810 10811 10852 10851 10547 + 9 10811 10812 10853 10852 10548 + 9 10812 10813 10854 10853 10549 + 9 10813 10814 10855 10854 10550 + 9 10814 10815 10856 10855 10551 + 9 10815 10816 10857 10856 10552 + 9 10816 10817 10858 10857 10553 + 9 10817 10818 10859 10858 10554 + 9 10818 10819 10860 10859 10555 + 9 10819 10820 10861 10860 10556 + 9 10820 10821 10862 10861 10557 + 9 10821 10822 10863 10862 10558 + 9 10822 10823 10864 10863 10559 + 9 10824 10825 10866 10865 10560 + 9 10825 10826 10867 10866 10561 + 9 10826 10827 10868 10867 10562 + 9 10827 10828 10869 10868 10563 + 9 10828 10829 10870 10869 10564 + 9 10829 10830 10871 10870 10565 + 9 10830 10831 10872 10871 10566 + 9 10831 10832 10873 10872 10567 + 9 10832 10833 10874 10873 10568 + 9 10833 10834 10875 10874 10569 + 9 10834 10835 10876 10875 10570 + 9 10835 10836 10877 10876 10571 + 9 10836 10837 10878 10877 10572 + 9 10837 10838 10879 10878 10573 + 9 10838 10839 10880 10879 10574 + 9 10839 10840 10881 10880 10575 + 9 10840 10841 10882 10881 10576 + 9 10841 10842 10883 10882 10577 + 9 10842 10843 10884 10883 10578 + 9 10843 10844 10885 10884 10579 + 9 10844 10845 10886 10885 10580 + 9 10845 10846 10887 10886 10581 + 9 10846 10847 10888 10887 10582 + 9 10847 10848 10889 10888 10583 + 9 10848 10849 10890 10889 10584 + 9 10849 10850 10891 10890 10585 + 9 10850 10851 10892 10891 10586 + 9 10851 10852 10893 10892 10587 + 9 10852 10853 10894 10893 10588 + 9 10853 10854 10895 10894 10589 + 9 10854 10855 10896 10895 10590 + 9 10855 10856 10897 10896 10591 + 9 10856 10857 10898 10897 10592 + 9 10857 10858 10899 10898 10593 + 9 10858 10859 10900 10899 10594 + 9 10859 10860 10901 10900 10595 + 9 10860 10861 10902 10901 10596 + 9 10861 10862 10903 10902 10597 + 9 10862 10863 10904 10903 10598 + 9 10863 10864 10905 10904 10599 + 9 10865 10866 10907 10906 10600 + 9 10866 10867 10908 10907 10601 + 9 10867 10868 10909 10908 10602 + 9 10868 10869 10910 10909 10603 + 9 10869 10870 10911 10910 10604 + 9 10870 10871 10912 10911 10605 + 9 10871 10872 10913 10912 10606 + 9 10872 10873 10914 10913 10607 + 9 10873 10874 10915 10914 10608 + 9 10874 10875 10916 10915 10609 + 9 10875 10876 10917 10916 10610 + 9 10876 10877 10918 10917 10611 + 9 10877 10878 10919 10918 10612 + 9 10878 10879 10920 10919 10613 + 9 10879 10880 10921 10920 10614 + 9 10880 10881 10922 10921 10615 + 9 10881 10882 10923 10922 10616 + 9 10882 10883 10924 10923 10617 + 9 10883 10884 10925 10924 10618 + 9 10884 10885 10926 10925 10619 + 9 10885 10886 10927 10926 10620 + 9 10886 10887 10928 10927 10621 + 9 10887 10888 10929 10928 10622 + 9 10888 10889 10930 10929 10623 + 9 10889 10890 10931 10930 10624 + 9 10890 10891 10932 10931 10625 + 9 10891 10892 10933 10932 10626 + 9 10892 10893 10934 10933 10627 + 9 10893 10894 10935 10934 10628 + 9 10894 10895 10936 10935 10629 + 9 10895 10896 10937 10936 10630 + 9 10896 10897 10938 10937 10631 + 9 10897 10898 10939 10938 10632 + 9 10898 10899 10940 10939 10633 + 9 10899 10900 10941 10940 10634 + 9 10900 10901 10942 10941 10635 + 9 10901 10902 10943 10942 10636 + 9 10902 10903 10944 10943 10637 + 9 10903 10904 10945 10944 10638 + 9 10904 10905 10946 10945 10639 + 9 10906 10907 10948 10947 10640 + 9 10907 10908 10949 10948 10641 + 9 10908 10909 10950 10949 10642 + 9 10909 10910 10951 10950 10643 + 9 10910 10911 10952 10951 10644 + 9 10911 10912 10953 10952 10645 + 9 10912 10913 10954 10953 10646 + 9 10913 10914 10955 10954 10647 + 9 10914 10915 10956 10955 10648 + 9 10915 10916 10957 10956 10649 + 9 10916 10917 10958 10957 10650 + 9 10917 10918 10959 10958 10651 + 9 10918 10919 10960 10959 10652 + 9 10919 10920 10961 10960 10653 + 9 10920 10921 10962 10961 10654 + 9 10921 10922 10963 10962 10655 + 9 10922 10923 10964 10963 10656 + 9 10923 10924 10965 10964 10657 + 9 10924 10925 10966 10965 10658 + 9 10925 10926 10967 10966 10659 + 9 10926 10927 10968 10967 10660 + 9 10927 10928 10969 10968 10661 + 9 10928 10929 10970 10969 10662 + 9 10929 10930 10971 10970 10663 + 9 10930 10931 10972 10971 10664 + 9 10931 10932 10973 10972 10665 + 9 10932 10933 10974 10973 10666 + 9 10933 10934 10975 10974 10667 + 9 10934 10935 10976 10975 10668 + 9 10935 10936 10977 10976 10669 + 9 10936 10937 10978 10977 10670 + 9 10937 10938 10979 10978 10671 + 9 10938 10939 10980 10979 10672 + 9 10939 10940 10981 10980 10673 + 9 10940 10941 10982 10981 10674 + 9 10941 10942 10983 10982 10675 + 9 10942 10943 10984 10983 10676 + 9 10943 10944 10985 10984 10677 + 9 10944 10945 10986 10985 10678 + 9 10945 10946 10987 10986 10679 + 9 10947 10948 10989 10988 10680 + 9 10948 10949 10990 10989 10681 + 9 10949 10950 10991 10990 10682 + 9 10950 10951 10992 10991 10683 + 9 10951 10952 10993 10992 10684 + 9 10952 10953 10994 10993 10685 + 9 10953 10954 10995 10994 10686 + 9 10954 10955 10996 10995 10687 + 9 10955 10956 10997 10996 10688 + 9 10956 10957 10998 10997 10689 + 9 10957 10958 10999 10998 10690 + 9 10958 10959 11000 10999 10691 + 9 10959 10960 11001 11000 10692 + 9 10960 10961 11002 11001 10693 + 9 10961 10962 11003 11002 10694 + 9 10962 10963 11004 11003 10695 + 9 10963 10964 11005 11004 10696 + 9 10964 10965 11006 11005 10697 + 9 10965 10966 11007 11006 10698 + 9 10966 10967 11008 11007 10699 + 9 10967 10968 11009 11008 10700 + 9 10968 10969 11010 11009 10701 + 9 10969 10970 11011 11010 10702 + 9 10970 10971 11012 11011 10703 + 9 10971 10972 11013 11012 10704 + 9 10972 10973 11014 11013 10705 + 9 10973 10974 11015 11014 10706 + 9 10974 10975 11016 11015 10707 + 9 10975 10976 11017 11016 10708 + 9 10976 10977 11018 11017 10709 + 9 10977 10978 11019 11018 10710 + 9 10978 10979 11020 11019 10711 + 9 10979 10980 11021 11020 10712 + 9 10980 10981 11022 11021 10713 + 9 10981 10982 11023 11022 10714 + 9 10982 10983 11024 11023 10715 + 9 10983 10984 11025 11024 10716 + 9 10984 10985 11026 11025 10717 + 9 10985 10986 11027 11026 10718 + 9 10986 10987 11028 11027 10719 + 9 10988 10989 11030 11029 10720 + 9 10989 10990 11031 11030 10721 + 9 10990 10991 11032 11031 10722 + 9 10991 10992 11033 11032 10723 + 9 10992 10993 11034 11033 10724 + 9 10993 10994 11035 11034 10725 + 9 10994 10995 11036 11035 10726 + 9 10995 10996 11037 11036 10727 + 9 10996 10997 11038 11037 10728 + 9 10997 10998 11039 11038 10729 + 9 10998 10999 11040 11039 10730 + 9 10999 11000 11041 11040 10731 + 9 11000 11001 11042 11041 10732 + 9 11001 11002 11043 11042 10733 + 9 11002 11003 11044 11043 10734 + 9 11003 11004 11045 11044 10735 + 9 11004 11005 11046 11045 10736 + 9 11005 11006 11047 11046 10737 + 9 11006 11007 11048 11047 10738 + 9 11007 11008 11049 11048 10739 + 9 11008 11009 11050 11049 10740 + 9 11009 11010 11051 11050 10741 + 9 11010 11011 11052 11051 10742 + 9 11011 11012 11053 11052 10743 + 9 11012 11013 11054 11053 10744 + 9 11013 11014 11055 11054 10745 + 9 11014 11015 11056 11055 10746 + 9 11015 11016 11057 11056 10747 + 9 11016 11017 11058 11057 10748 + 9 11017 11018 11059 11058 10749 + 9 11018 11019 11060 11059 10750 + 9 11019 11020 11061 11060 10751 + 9 11020 11021 11062 11061 10752 + 9 11021 11022 11063 11062 10753 + 9 11022 11023 11064 11063 10754 + 9 11023 11024 11065 11064 10755 + 9 11024 11025 11066 11065 10756 + 9 11025 11026 11067 11066 10757 + 9 11026 11027 11068 11067 10758 + 9 11027 11028 11069 11068 10759 + 9 11029 11030 11071 11070 10760 + 9 11030 11031 11072 11071 10761 + 9 11031 11032 11073 11072 10762 + 9 11032 11033 11074 11073 10763 + 9 11033 11034 11075 11074 10764 + 9 11034 11035 11076 11075 10765 + 9 11035 11036 11077 11076 10766 + 9 11036 11037 11078 11077 10767 + 9 11037 11038 11079 11078 10768 + 9 11038 11039 11080 11079 10769 + 9 11039 11040 11081 11080 10770 + 9 11040 11041 11082 11081 10771 + 9 11041 11042 11083 11082 10772 + 9 11042 11043 11084 11083 10773 + 9 11043 11044 11085 11084 10774 + 9 11044 11045 11086 11085 10775 + 9 11045 11046 11087 11086 10776 + 9 11046 11047 11088 11087 10777 + 9 11047 11048 11089 11088 10778 + 9 11048 11049 11090 11089 10779 + 9 11049 11050 11091 11090 10780 + 9 11050 11051 11092 11091 10781 + 9 11051 11052 11093 11092 10782 + 9 11052 11053 11094 11093 10783 + 9 11053 11054 11095 11094 10784 + 9 11054 11055 11096 11095 10785 + 9 11055 11056 11097 11096 10786 + 9 11056 11057 11098 11097 10787 + 9 11057 11058 11099 11098 10788 + 9 11058 11059 11100 11099 10789 + 9 11059 11060 11101 11100 10790 + 9 11060 11061 11102 11101 10791 + 9 11061 11062 11103 11102 10792 + 9 11062 11063 11104 11103 10793 + 9 11063 11064 11105 11104 10794 + 9 11064 11065 11106 11105 10795 + 9 11065 11066 11107 11106 10796 + 9 11066 11067 11108 11107 10797 + 9 11067 11068 11109 11108 10798 + 9 11068 11069 11110 11109 10799 + 9 11070 11071 11112 11111 10800 + 9 11071 11072 11113 11112 10801 + 9 11072 11073 11114 11113 10802 + 9 11073 11074 11115 11114 10803 + 9 11074 11075 11116 11115 10804 + 9 11075 11076 11117 11116 10805 + 9 11076 11077 11118 11117 10806 + 9 11077 11078 11119 11118 10807 + 9 11078 11079 11120 11119 10808 + 9 11079 11080 11121 11120 10809 + 9 11080 11081 11122 11121 10810 + 9 11081 11082 11123 11122 10811 + 9 11082 11083 11124 11123 10812 + 9 11083 11084 11125 11124 10813 + 9 11084 11085 11126 11125 10814 + 9 11085 11086 11127 11126 10815 + 9 11086 11087 11128 11127 10816 + 9 11087 11088 11129 11128 10817 + 9 11088 11089 11130 11129 10818 + 9 11089 11090 11131 11130 10819 + 9 11090 11091 11132 11131 10820 + 9 11091 11092 11133 11132 10821 + 9 11092 11093 11134 11133 10822 + 9 11093 11094 11135 11134 10823 + 9 11094 11095 11136 11135 10824 + 9 11095 11096 11137 11136 10825 + 9 11096 11097 11138 11137 10826 + 9 11097 11098 11139 11138 10827 + 9 11098 11099 11140 11139 10828 + 9 11099 11100 11141 11140 10829 + 9 11100 11101 11142 11141 10830 + 9 11101 11102 11143 11142 10831 + 9 11102 11103 11144 11143 10832 + 9 11103 11104 11145 11144 10833 + 9 11104 11105 11146 11145 10834 + 9 11105 11106 11147 11146 10835 + 9 11106 11107 11148 11147 10836 + 9 11107 11108 11149 11148 10837 + 9 11108 11109 11150 11149 10838 + 9 11109 11110 11151 11150 10839 + 9 11111 11112 11153 11152 10840 + 9 11112 11113 11154 11153 10841 + 9 11113 11114 11155 11154 10842 + 9 11114 11115 11156 11155 10843 + 9 11115 11116 11157 11156 10844 + 9 11116 11117 11158 11157 10845 + 9 11117 11118 11159 11158 10846 + 9 11118 11119 11160 11159 10847 + 9 11119 11120 11161 11160 10848 + 9 11120 11121 11162 11161 10849 + 9 11121 11122 11163 11162 10850 + 9 11122 11123 11164 11163 10851 + 9 11123 11124 11165 11164 10852 + 9 11124 11125 11166 11165 10853 + 9 11125 11126 11167 11166 10854 + 9 11126 11127 11168 11167 10855 + 9 11127 11128 11169 11168 10856 + 9 11128 11129 11170 11169 10857 + 9 11129 11130 11171 11170 10858 + 9 11130 11131 11172 11171 10859 + 9 11131 11132 11173 11172 10860 + 9 11132 11133 11174 11173 10861 + 9 11133 11134 11175 11174 10862 + 9 11134 11135 11176 11175 10863 + 9 11135 11136 11177 11176 10864 + 9 11136 11137 11178 11177 10865 + 9 11137 11138 11179 11178 10866 + 9 11138 11139 11180 11179 10867 + 9 11139 11140 11181 11180 10868 + 9 11140 11141 11182 11181 10869 + 9 11141 11142 11183 11182 10870 + 9 11142 11143 11184 11183 10871 + 9 11143 11144 11185 11184 10872 + 9 11144 11145 11186 11185 10873 + 9 11145 11146 11187 11186 10874 + 9 11146 11147 11188 11187 10875 + 9 11147 11148 11189 11188 10876 + 9 11148 11149 11190 11189 10877 + 9 11149 11150 11191 11190 10878 + 9 11150 11151 11192 11191 10879 + 9 11152 11153 11194 11193 10880 + 9 11153 11154 11195 11194 10881 + 9 11154 11155 11196 11195 10882 + 9 11155 11156 11197 11196 10883 + 9 11156 11157 11198 11197 10884 + 9 11157 11158 11199 11198 10885 + 9 11158 11159 11200 11199 10886 + 9 11159 11160 11201 11200 10887 + 9 11160 11161 11202 11201 10888 + 9 11161 11162 11203 11202 10889 + 9 11162 11163 11204 11203 10890 + 9 11163 11164 11205 11204 10891 + 9 11164 11165 11206 11205 10892 + 9 11165 11166 11207 11206 10893 + 9 11166 11167 11208 11207 10894 + 9 11167 11168 11209 11208 10895 + 9 11168 11169 11210 11209 10896 + 9 11169 11170 11211 11210 10897 + 9 11170 11171 11212 11211 10898 + 9 11171 11172 11213 11212 10899 + 9 11172 11173 11214 11213 10900 + 9 11173 11174 11215 11214 10901 + 9 11174 11175 11216 11215 10902 + 9 11175 11176 11217 11216 10903 + 9 11176 11177 11218 11217 10904 + 9 11177 11178 11219 11218 10905 + 9 11178 11179 11220 11219 10906 + 9 11179 11180 11221 11220 10907 + 9 11180 11181 11222 11221 10908 + 9 11181 11182 11223 11222 10909 + 9 11182 11183 11224 11223 10910 + 9 11183 11184 11225 11224 10911 + 9 11184 11185 11226 11225 10912 + 9 11185 11186 11227 11226 10913 + 9 11186 11187 11228 11227 10914 + 9 11187 11188 11229 11228 10915 + 9 11188 11189 11230 11229 10916 + 9 11189 11190 11231 11230 10917 + 9 11190 11191 11232 11231 10918 + 9 11191 11192 11233 11232 10919 + 9 11193 11194 11235 11234 10920 + 9 11194 11195 11236 11235 10921 + 9 11195 11196 11237 11236 10922 + 9 11196 11197 11238 11237 10923 + 9 11197 11198 11239 11238 10924 + 9 11198 11199 11240 11239 10925 + 9 11199 11200 11241 11240 10926 + 9 11200 11201 11242 11241 10927 + 9 11201 11202 11243 11242 10928 + 9 11202 11203 11244 11243 10929 + 9 11203 11204 11245 11244 10930 + 9 11204 11205 11246 11245 10931 + 9 11205 11206 11247 11246 10932 + 9 11206 11207 11248 11247 10933 + 9 11207 11208 11249 11248 10934 + 9 11208 11209 11250 11249 10935 + 9 11209 11210 11251 11250 10936 + 9 11210 11211 11252 11251 10937 + 9 11211 11212 11253 11252 10938 + 9 11212 11213 11254 11253 10939 + 9 11213 11214 11255 11254 10940 + 9 11214 11215 11256 11255 10941 + 9 11215 11216 11257 11256 10942 + 9 11216 11217 11258 11257 10943 + 9 11217 11218 11259 11258 10944 + 9 11218 11219 11260 11259 10945 + 9 11219 11220 11261 11260 10946 + 9 11220 11221 11262 11261 10947 + 9 11221 11222 11263 11262 10948 + 9 11222 11223 11264 11263 10949 + 9 11223 11224 11265 11264 10950 + 9 11224 11225 11266 11265 10951 + 9 11225 11226 11267 11266 10952 + 9 11226 11227 11268 11267 10953 + 9 11227 11228 11269 11268 10954 + 9 11228 11229 11270 11269 10955 + 9 11229 11230 11271 11270 10956 + 9 11230 11231 11272 11271 10957 + 9 11231 11232 11273 11272 10958 + 9 11232 11233 11274 11273 10959 + 9 11234 11235 11276 11275 10960 + 9 11235 11236 11277 11276 10961 + 9 11236 11237 11278 11277 10962 + 9 11237 11238 11279 11278 10963 + 9 11238 11239 11280 11279 10964 + 9 11239 11240 11281 11280 10965 + 9 11240 11241 11282 11281 10966 + 9 11241 11242 11283 11282 10967 + 9 11242 11243 11284 11283 10968 + 9 11243 11244 11285 11284 10969 + 9 11244 11245 11286 11285 10970 + 9 11245 11246 11287 11286 10971 + 9 11246 11247 11288 11287 10972 + 9 11247 11248 11289 11288 10973 + 9 11248 11249 11290 11289 10974 + 9 11249 11250 11291 11290 10975 + 9 11250 11251 11292 11291 10976 + 9 11251 11252 11293 11292 10977 + 9 11252 11253 11294 11293 10978 + 9 11253 11254 11295 11294 10979 + 9 11254 11255 11296 11295 10980 + 9 11255 11256 11297 11296 10981 + 9 11256 11257 11298 11297 10982 + 9 11257 11258 11299 11298 10983 + 9 11258 11259 11300 11299 10984 + 9 11259 11260 11301 11300 10985 + 9 11260 11261 11302 11301 10986 + 9 11261 11262 11303 11302 10987 + 9 11262 11263 11304 11303 10988 + 9 11263 11264 11305 11304 10989 + 9 11264 11265 11306 11305 10990 + 9 11265 11266 11307 11306 10991 + 9 11266 11267 11308 11307 10992 + 9 11267 11268 11309 11308 10993 + 9 11268 11269 11310 11309 10994 + 9 11269 11270 11311 11310 10995 + 9 11270 11271 11312 11311 10996 + 9 11271 11272 11313 11312 10997 + 9 11272 11273 11314 11313 10998 + 9 11273 11274 11315 11314 10999 + 9 11275 11276 11317 11316 11000 + 9 11276 11277 11318 11317 11001 + 9 11277 11278 11319 11318 11002 + 9 11278 11279 11320 11319 11003 + 9 11279 11280 11321 11320 11004 + 9 11280 11281 11322 11321 11005 + 9 11281 11282 11323 11322 11006 + 9 11282 11283 11324 11323 11007 + 9 11283 11284 11325 11324 11008 + 9 11284 11285 11326 11325 11009 + 9 11285 11286 11327 11326 11010 + 9 11286 11287 11328 11327 11011 + 9 11287 11288 11329 11328 11012 + 9 11288 11289 11330 11329 11013 + 9 11289 11290 11331 11330 11014 + 9 11290 11291 11332 11331 11015 + 9 11291 11292 11333 11332 11016 + 9 11292 11293 11334 11333 11017 + 9 11293 11294 11335 11334 11018 + 9 11294 11295 11336 11335 11019 + 9 11295 11296 11337 11336 11020 + 9 11296 11297 11338 11337 11021 + 9 11297 11298 11339 11338 11022 + 9 11298 11299 11340 11339 11023 + 9 11299 11300 11341 11340 11024 + 9 11300 11301 11342 11341 11025 + 9 11301 11302 11343 11342 11026 + 9 11302 11303 11344 11343 11027 + 9 11303 11304 11345 11344 11028 + 9 11304 11305 11346 11345 11029 + 9 11305 11306 11347 11346 11030 + 9 11306 11307 11348 11347 11031 + 9 11307 11308 11349 11348 11032 + 9 11308 11309 11350 11349 11033 + 9 11309 11310 11351 11350 11034 + 9 11310 11311 11352 11351 11035 + 9 11311 11312 11353 11352 11036 + 9 11312 11313 11354 11353 11037 + 9 11313 11314 11355 11354 11038 + 9 11314 11315 11356 11355 11039 + 9 11316 11317 11358 11357 11040 + 9 11317 11318 11359 11358 11041 + 9 11318 11319 11360 11359 11042 + 9 11319 11320 11361 11360 11043 + 9 11320 11321 11362 11361 11044 + 9 11321 11322 11363 11362 11045 + 9 11322 11323 11364 11363 11046 + 9 11323 11324 11365 11364 11047 + 9 11324 11325 11366 11365 11048 + 9 11325 11326 11367 11366 11049 + 9 11326 11327 11368 11367 11050 + 9 11327 11328 11369 11368 11051 + 9 11328 11329 11370 11369 11052 + 9 11329 11330 11371 11370 11053 + 9 11330 11331 11372 11371 11054 + 9 11331 11332 11373 11372 11055 + 9 11332 11333 11374 11373 11056 + 9 11333 11334 11375 11374 11057 + 9 11334 11335 11376 11375 11058 + 9 11335 11336 11377 11376 11059 + 9 11336 11337 11378 11377 11060 + 9 11337 11338 11379 11378 11061 + 9 11338 11339 11380 11379 11062 + 9 11339 11340 11381 11380 11063 + 9 11340 11341 11382 11381 11064 + 9 11341 11342 11383 11382 11065 + 9 11342 11343 11384 11383 11066 + 9 11343 11344 11385 11384 11067 + 9 11344 11345 11386 11385 11068 + 9 11345 11346 11387 11386 11069 + 9 11346 11347 11388 11387 11070 + 9 11347 11348 11389 11388 11071 + 9 11348 11349 11390 11389 11072 + 9 11349 11350 11391 11390 11073 + 9 11350 11351 11392 11391 11074 + 9 11351 11352 11393 11392 11075 + 9 11352 11353 11394 11393 11076 + 9 11353 11354 11395 11394 11077 + 9 11354 11355 11396 11395 11078 + 9 11355 11356 11397 11396 11079 + 9 11357 11358 11399 11398 11080 + 9 11358 11359 11400 11399 11081 + 9 11359 11360 11401 11400 11082 + 9 11360 11361 11402 11401 11083 + 9 11361 11362 11403 11402 11084 + 9 11362 11363 11404 11403 11085 + 9 11363 11364 11405 11404 11086 + 9 11364 11365 11406 11405 11087 + 9 11365 11366 11407 11406 11088 + 9 11366 11367 11408 11407 11089 + 9 11367 11368 11409 11408 11090 + 9 11368 11369 11410 11409 11091 + 9 11369 11370 11411 11410 11092 + 9 11370 11371 11412 11411 11093 + 9 11371 11372 11413 11412 11094 + 9 11372 11373 11414 11413 11095 + 9 11373 11374 11415 11414 11096 + 9 11374 11375 11416 11415 11097 + 9 11375 11376 11417 11416 11098 + 9 11376 11377 11418 11417 11099 + 9 11377 11378 11419 11418 11100 + 9 11378 11379 11420 11419 11101 + 9 11379 11380 11421 11420 11102 + 9 11380 11381 11422 11421 11103 + 9 11381 11382 11423 11422 11104 + 9 11382 11383 11424 11423 11105 + 9 11383 11384 11425 11424 11106 + 9 11384 11385 11426 11425 11107 + 9 11385 11386 11427 11426 11108 + 9 11386 11387 11428 11427 11109 + 9 11387 11388 11429 11428 11110 + 9 11388 11389 11430 11429 11111 + 9 11389 11390 11431 11430 11112 + 9 11390 11391 11432 11431 11113 + 9 11391 11392 11433 11432 11114 + 9 11392 11393 11434 11433 11115 + 9 11393 11394 11435 11434 11116 + 9 11394 11395 11436 11435 11117 + 9 11395 11396 11437 11436 11118 + 9 11396 11397 11438 11437 11119 + 9 11398 11399 11440 11439 11120 + 9 11399 11400 11441 11440 11121 + 9 11400 11401 11442 11441 11122 + 9 11401 11402 11443 11442 11123 + 9 11402 11403 11444 11443 11124 + 9 11403 11404 11445 11444 11125 + 9 11404 11405 11446 11445 11126 + 9 11405 11406 11447 11446 11127 + 9 11406 11407 11448 11447 11128 + 9 11407 11408 11449 11448 11129 + 9 11408 11409 11450 11449 11130 + 9 11409 11410 11451 11450 11131 + 9 11410 11411 11452 11451 11132 + 9 11411 11412 11453 11452 11133 + 9 11412 11413 11454 11453 11134 + 9 11413 11414 11455 11454 11135 + 9 11414 11415 11456 11455 11136 + 9 11415 11416 11457 11456 11137 + 9 11416 11417 11458 11457 11138 + 9 11417 11418 11459 11458 11139 + 9 11418 11419 11460 11459 11140 + 9 11419 11420 11461 11460 11141 + 9 11420 11421 11462 11461 11142 + 9 11421 11422 11463 11462 11143 + 9 11422 11423 11464 11463 11144 + 9 11423 11424 11465 11464 11145 + 9 11424 11425 11466 11465 11146 + 9 11425 11426 11467 11466 11147 + 9 11426 11427 11468 11467 11148 + 9 11427 11428 11469 11468 11149 + 9 11428 11429 11470 11469 11150 + 9 11429 11430 11471 11470 11151 + 9 11430 11431 11472 11471 11152 + 9 11431 11432 11473 11472 11153 + 9 11432 11433 11474 11473 11154 + 9 11433 11434 11475 11474 11155 + 9 11434 11435 11476 11475 11156 + 9 11435 11436 11477 11476 11157 + 9 11436 11437 11478 11477 11158 + 9 11437 11438 11479 11478 11159 + 9 11439 11440 11481 11480 11160 + 9 11440 11441 11482 11481 11161 + 9 11441 11442 11483 11482 11162 + 9 11442 11443 11484 11483 11163 + 9 11443 11444 11485 11484 11164 + 9 11444 11445 11486 11485 11165 + 9 11445 11446 11487 11486 11166 + 9 11446 11447 11488 11487 11167 + 9 11447 11448 11489 11488 11168 + 9 11448 11449 11490 11489 11169 + 9 11449 11450 11491 11490 11170 + 9 11450 11451 11492 11491 11171 + 9 11451 11452 11493 11492 11172 + 9 11452 11453 11494 11493 11173 + 9 11453 11454 11495 11494 11174 + 9 11454 11455 11496 11495 11175 + 9 11455 11456 11497 11496 11176 + 9 11456 11457 11498 11497 11177 + 9 11457 11458 11499 11498 11178 + 9 11458 11459 11500 11499 11179 + 9 11459 11460 11501 11500 11180 + 9 11460 11461 11502 11501 11181 + 9 11461 11462 11503 11502 11182 + 9 11462 11463 11504 11503 11183 + 9 11463 11464 11505 11504 11184 + 9 11464 11465 11506 11505 11185 + 9 11465 11466 11507 11506 11186 + 9 11466 11467 11508 11507 11187 + 9 11467 11468 11509 11508 11188 + 9 11468 11469 11510 11509 11189 + 9 11469 11470 11511 11510 11190 + 9 11470 11471 11512 11511 11191 + 9 11471 11472 11513 11512 11192 + 9 11472 11473 11514 11513 11193 + 9 11473 11474 11515 11514 11194 + 9 11474 11475 11516 11515 11195 + 9 11475 11476 11517 11516 11196 + 9 11476 11477 11518 11517 11197 + 9 11477 11478 11519 11518 11198 + 9 11478 11479 11520 11519 11199 +% +% Node coordinates +% +NPOIN= 11521 + 3.000000000000000 0.000000000000000 0 + 3.000000000000000 0.01250000000000000 1 + 3.000000000000000 0.02500000000000000 2 + 3.000000000000000 0.03750000000000001 3 + 3.000000000000000 0.05000000000000000 4 + 3.000000000000000 0.06250000000000000 5 + 3.000000000000000 0.07500000000000001 6 + 3.000000000000000 0.08750000000000001 7 + 3.000000000000000 0.1000000000000000 8 + 3.000000000000000 0.1125000000000000 9 + 3.000000000000000 0.1250000000000000 10 + 3.000000000000000 0.1375000000000000 11 + 3.000000000000000 0.1500000000000000 12 + 3.000000000000000 0.1625000000000000 13 + 3.000000000000000 0.1750000000000000 14 + 3.000000000000000 0.1875000000000000 15 + 3.000000000000000 0.2000000000000000 16 + 3.000000000000000 0.2125000000000000 17 + 3.000000000000000 0.2250000000000000 18 + 3.000000000000000 0.2375000000000000 19 + 3.000000000000000 0.2500000000000000 20 + 3.000000000000000 0.2625000000000000 21 + 3.000000000000000 0.2750000000000000 22 + 3.000000000000000 0.2875000000000000 23 + 3.000000000000000 0.3000000000000000 24 + 3.000000000000000 0.3125000000000000 25 + 3.000000000000000 0.3250000000000000 26 + 3.000000000000000 0.3375000000000000 27 + 3.000000000000000 0.3500000000000000 28 + 3.000000000000000 0.3625000000000000 29 + 3.000000000000000 0.3750000000000000 30 + 3.000000000000000 0.3875000000000000 31 + 3.000000000000000 0.4000000000000000 32 + 3.000000000000000 0.4125000000000000 33 + 3.000000000000000 0.4250000000000000 34 + 3.000000000000000 0.4375000000000000 35 + 3.000000000000000 0.4500000000000000 36 + 3.000000000000000 0.4625000000000000 37 + 3.000000000000000 0.4750000000000000 38 + 3.000000000000000 0.4875000000000000 39 + 3.000000000000000 0.5000000000000000 40 + 2.987500000000000 0.000000000000000 41 + 2.987500000000000 0.01250000000000000 42 + 2.987500000000000 0.02500000000000001 43 + 2.987500000000000 0.03749999999999999 44 + 2.987500000000000 0.05000000000000002 45 + 2.987500000000000 0.06250000000000000 46 + 2.987500000000000 0.07499999999999998 47 + 2.987500000000000 0.08750000000000001 48 + 2.987500000000000 0.1000000000000000 49 + 2.987500000000000 0.1125000000000000 50 + 2.987500000000000 0.1250000000000000 51 + 2.987500000000000 0.1375000000000000 52 + 2.987500000000000 0.1500000000000000 53 + 2.987500000000001 0.1625000000000000 54 + 2.987500000000000 0.1750000000000000 55 + 2.987500000000000 0.1874999999999999 56 + 2.987500000000000 0.2000000000000000 57 + 2.987500000000000 0.2125000000000000 58 + 2.987500000000000 0.2250000000000000 59 + 2.987500000000000 0.2375000000000000 60 + 2.987500000000000 0.2500000000000000 61 + 2.987500000000000 0.2625000000000001 62 + 2.987500000000000 0.2750000000000000 63 + 2.987500000000000 0.2875000000000000 64 + 2.987500000000001 0.3000000000000000 65 + 2.987500000000001 0.3124999999999999 66 + 2.987500000000001 0.3250000000000000 67 + 2.987500000000001 0.3375000000000000 68 + 2.987500000000001 0.3500000000000000 69 + 2.987500000000001 0.3625000000000000 70 + 2.987500000000001 0.3750000000000000 71 + 2.987500000000001 0.3875000000000000 72 + 2.987500000000001 0.4000000000000000 73 + 2.987500000000001 0.4125000000000001 74 + 2.987500000000001 0.4250000000000000 75 + 2.987500000000001 0.4375000000000000 76 + 2.987500000000001 0.4500000000000001 77 + 2.987500000000001 0.4625000000000000 78 + 2.987500000000001 0.4750000000000000 79 + 2.987500000000001 0.4875000000000000 80 + 2.987500000000000 0.5000000000000000 81 + 2.975000000000001 0.000000000000000 82 + 2.975000000000001 0.01250000000000000 83 + 2.975000000000001 0.02500000000000000 84 + 2.975000000000001 0.03750000000000001 85 + 2.975000000000001 0.05000000000000000 86 + 2.975000000000001 0.06249999999999999 87 + 2.975000000000001 0.07500000000000001 88 + 2.975000000000001 0.08750000000000001 89 + 2.975000000000001 0.1000000000000000 90 + 2.975000000000001 0.1125000000000000 91 + 2.975000000000001 0.1250000000000000 92 + 2.975000000000001 0.1375000000000000 93 + 2.975000000000001 0.1500000000000000 94 + 2.975000000000001 0.1625000000000000 95 + 2.975000000000001 0.1750000000000000 96 + 2.975000000000001 0.1875000000000001 97 + 2.975000000000001 0.2000000000000000 98 + 2.975000000000001 0.2125000000000000 99 + 2.975000000000001 0.2250000000000000 100 + 2.975000000000001 0.2375000000000000 101 + 2.975000000000001 0.2500000000000000 102 + 2.975000000000001 0.2625000000000000 103 + 2.975000000000001 0.2750000000000000 104 + 2.975000000000001 0.2875000000000001 105 + 2.975000000000001 0.3000000000000000 106 + 2.975000000000001 0.3124999999999999 107 + 2.975000000000001 0.3250000000000001 108 + 2.975000000000001 0.3375000000000000 109 + 2.975000000000001 0.3500000000000000 110 + 2.975000000000001 0.3625000000000000 111 + 2.975000000000001 0.3750000000000000 112 + 2.975000000000001 0.3875000000000000 113 + 2.975000000000001 0.3999999999999999 114 + 2.975000000000001 0.4125000000000001 115 + 2.975000000000001 0.4250000000000000 116 + 2.975000000000001 0.4374999999999999 117 + 2.975000000000001 0.4500000000000001 118 + 2.975000000000001 0.4625000000000000 119 + 2.975000000000001 0.4750000000000000 120 + 2.975000000000001 0.4875000000000002 121 + 2.975000000000000 0.5000000000000000 122 + 2.962500000000000 0.000000000000000 123 + 2.962499999999999 0.01250000000000000 124 + 2.962499999999999 0.02500000000000000 125 + 2.962500000000000 0.03750000000000001 126 + 2.962500000000000 0.05000000000000000 127 + 2.962500000000000 0.06250000000000000 128 + 2.962500000000000 0.07500000000000001 129 + 2.962499999999999 0.08750000000000001 130 + 2.962500000000000 0.1000000000000000 131 + 2.962500000000000 0.1125000000000000 132 + 2.962500000000000 0.1250000000000000 133 + 2.962499999999999 0.1375000000000000 134 + 2.962500000000001 0.1500000000000000 135 + 2.962500000000000 0.1625000000000000 136 + 2.962499999999999 0.1750000000000000 137 + 2.962500000000000 0.1875000000000001 138 + 2.962500000000000 0.2000000000000000 139 + 2.962500000000000 0.2125000000000000 140 + 2.962500000000000 0.2250000000000000 141 + 2.962499999999999 0.2375000000000000 142 + 2.962500000000000 0.2500000000000000 143 + 2.962500000000000 0.2625000000000000 144 + 2.962500000000000 0.2750000000000000 145 + 2.962500000000000 0.2875000000000000 146 + 2.962500000000000 0.3000000000000000 147 + 2.962500000000000 0.3125000000000000 148 + 2.962500000000000 0.3250000000000000 149 + 2.962500000000000 0.3375000000000001 150 + 2.962500000000000 0.3500000000000000 151 + 2.962500000000000 0.3625000000000002 152 + 2.962500000000000 0.3750000000000001 153 + 2.962500000000000 0.3875000000000000 154 + 2.962500000000000 0.4000000000000001 155 + 2.962500000000000 0.4124999999999999 156 + 2.962500000000001 0.4250000000000000 157 + 2.962500000000000 0.4374999999999999 158 + 2.962499999999999 0.4500000000000000 159 + 2.962500000000000 0.4625000000000000 160 + 2.962500000000000 0.4750000000000000 161 + 2.962500000000000 0.4875000000000000 162 + 2.962500000000000 0.5000000000000000 163 + 2.950000000000000 0.000000000000000 164 + 2.950000000000001 0.01250000000000000 165 + 2.950000000000000 0.02500000000000000 166 + 2.950000000000000 0.03750000000000001 167 + 2.950000000000001 0.05000000000000000 168 + 2.950000000000001 0.06250000000000000 169 + 2.950000000000001 0.07500000000000001 170 + 2.950000000000000 0.08750000000000001 171 + 2.950000000000000 0.1000000000000000 172 + 2.950000000000001 0.1125000000000000 173 + 2.950000000000001 0.1250000000000000 174 + 2.950000000000001 0.1375000000000000 175 + 2.950000000000001 0.1500000000000000 176 + 2.950000000000000 0.1625000000000000 177 + 2.950000000000001 0.1750000000000000 178 + 2.950000000000001 0.1875000000000000 179 + 2.950000000000001 0.2000000000000000 180 + 2.950000000000001 0.2125000000000000 181 + 2.950000000000001 0.2250000000000000 182 + 2.950000000000001 0.2375000000000000 183 + 2.950000000000000 0.2500000000000000 184 + 2.950000000000000 0.2624999999999999 185 + 2.950000000000000 0.2750000000000000 186 + 2.950000000000000 0.2875000000000001 187 + 2.950000000000000 0.3000000000000000 188 + 2.950000000000000 0.3125000000000000 189 + 2.950000000000000 0.3250000000000000 190 + 2.950000000000000 0.3375000000000000 191 + 2.950000000000000 0.3500000000000001 192 + 2.950000000000000 0.3624999999999999 193 + 2.950000000000000 0.3750000000000000 194 + 2.950000000000000 0.3874999999999999 195 + 2.950000000000000 0.4000000000000000 196 + 2.950000000000000 0.4125000000000001 197 + 2.950000000000000 0.4250000000000000 198 + 2.950000000000000 0.4375000000000000 199 + 2.950000000000000 0.4500000000000000 200 + 2.950000000000000 0.4625000000000000 201 + 2.950000000000000 0.4750000000000001 202 + 2.950000000000000 0.4874999999999999 203 + 2.950000000000000 0.5000000000000000 204 + 2.937500000000000 0.000000000000000 205 + 2.937500000000000 0.01250000000000000 206 + 2.937500000000000 0.02500000000000000 207 + 2.937500000000000 0.03750000000000001 208 + 2.937500000000000 0.05000000000000000 209 + 2.937500000000000 0.06250000000000000 210 + 2.937500000000000 0.07500000000000001 211 + 2.937500000000000 0.08750000000000001 212 + 2.937500000000000 0.1000000000000000 213 + 2.937500000000000 0.1125000000000000 214 + 2.937500000000000 0.1250000000000000 215 + 2.937500000000000 0.1375000000000000 216 + 2.937500000000000 0.1500000000000000 217 + 2.937500000000000 0.1625000000000000 218 + 2.937500000000000 0.1750000000000000 219 + 2.937500000000000 0.1875000000000000 220 + 2.937500000000000 0.2000000000000000 221 + 2.937500000000000 0.2125000000000001 222 + 2.937500000000000 0.2250000000000000 223 + 2.937500000000000 0.2375000000000001 224 + 2.937500000000000 0.2500000000000000 225 + 2.937500000000000 0.2624999999999999 226 + 2.937500000000000 0.2750000000000001 227 + 2.937500000000000 0.2875000000000000 228 + 2.937500000000000 0.3000000000000001 229 + 2.937500000000000 0.3124999999999999 230 + 2.937500000000000 0.3250000000000000 231 + 2.937500000000000 0.3375000000000000 232 + 2.937500000000000 0.3500000000000000 233 + 2.937500000000000 0.3625000000000002 234 + 2.937500000000000 0.3750000000000000 235 + 2.937500000000000 0.3875000000000000 236 + 2.937500000000000 0.4000000000000000 237 + 2.937500000000000 0.4125000000000001 238 + 2.937500000000000 0.4250000000000000 239 + 2.937500000000000 0.4374999999999999 240 + 2.937500000000000 0.4500000000000001 241 + 2.937500000000000 0.4625000000000001 242 + 2.937500000000000 0.4750000000000000 243 + 2.937500000000000 0.4875000000000000 244 + 2.937500000000000 0.5000000000000000 245 + 2.925000000000000 0.000000000000000 246 + 2.925000000000001 0.01250000000000000 247 + 2.925000000000000 0.02500000000000000 248 + 2.925000000000001 0.03749999999999999 249 + 2.925000000000001 0.05000000000000000 250 + 2.925000000000001 0.06250000000000000 251 + 2.925000000000001 0.07499999999999998 252 + 2.925000000000000 0.08750000000000001 253 + 2.925000000000001 0.1000000000000000 254 + 2.925000000000001 0.1125000000000000 255 + 2.925000000000000 0.1250000000000000 256 + 2.925000000000000 0.1375000000000000 257 + 2.925000000000000 0.1500000000000000 258 + 2.925000000000001 0.1625000000000000 259 + 2.925000000000000 0.1750000000000000 260 + 2.925000000000000 0.1875000000000000 261 + 2.925000000000000 0.2000000000000000 262 + 2.925000000000000 0.2125000000000000 263 + 2.925000000000000 0.2250000000000000 264 + 2.925000000000000 0.2375000000000000 265 + 2.925000000000000 0.2500000000000000 266 + 2.925000000000000 0.2625000000000000 267 + 2.925000000000000 0.2750000000000000 268 + 2.925000000000000 0.2875000000000001 269 + 2.924999999999999 0.3000000000000000 270 + 2.924999999999999 0.3125000000000000 271 + 2.924999999999999 0.3250000000000000 272 + 2.924999999999999 0.3374999999999999 273 + 2.924999999999999 0.3500000000000000 274 + 2.924999999999999 0.3625000000000000 275 + 2.924999999999999 0.3750000000000000 276 + 2.924999999999999 0.3875000000000000 277 + 2.924999999999999 0.4000000000000000 278 + 2.924999999999999 0.4125000000000000 279 + 2.924999999999999 0.4250000000000001 280 + 2.925000000000000 0.4375000000000001 281 + 2.925000000000000 0.4500000000000001 282 + 2.925000000000000 0.4625000000000001 283 + 2.925000000000000 0.4750000000000000 284 + 2.925000000000000 0.4875000000000000 285 + 2.925000000000000 0.5000000000000000 286 + 2.912500000000001 0.000000000000000 287 + 2.912500000000000 0.01250000000000000 288 + 2.912499999999999 0.02500000000000000 289 + 2.912500000000001 0.03750000000000002 290 + 2.912500000000000 0.05000000000000000 291 + 2.912500000000000 0.06250000000000000 292 + 2.912500000000000 0.07500000000000001 293 + 2.912500000000000 0.08750000000000001 294 + 2.912500000000001 0.1000000000000000 295 + 2.912500000000000 0.1125000000000000 296 + 2.912499999999999 0.1250000000000000 297 + 2.912499999999999 0.1375000000000000 298 + 2.912500000000000 0.1500000000000000 299 + 2.912500000000001 0.1625000000000000 300 + 2.912499999999999 0.1750000000000000 301 + 2.912500000000000 0.1875000000000000 302 + 2.912499999999999 0.2000000000000000 303 + 2.912499999999999 0.2125000000000000 304 + 2.912500000000000 0.2250000000000000 305 + 2.912500000000000 0.2375000000000000 306 + 2.912500000000000 0.2500000000000000 307 + 2.912500000000000 0.2625000000000000 308 + 2.912500000000000 0.2750000000000000 309 + 2.912500000000000 0.2875000000000000 310 + 2.912500000000000 0.3000000000000000 311 + 2.912500000000000 0.3125000000000000 312 + 2.912500000000000 0.3249999999999999 313 + 2.912500000000000 0.3375000000000000 314 + 2.912500000000000 0.3500000000000001 315 + 2.912500000000000 0.3625000000000000 316 + 2.912500000000000 0.3750000000000001 317 + 2.912500000000000 0.3875000000000000 318 + 2.912500000000000 0.4000000000000000 319 + 2.912500000000000 0.4124999999999999 320 + 2.912500000000000 0.4250000000000000 321 + 2.912500000000000 0.4375000000000000 322 + 2.912500000000000 0.4500000000000000 323 + 2.912500000000000 0.4625000000000000 324 + 2.912500000000000 0.4750000000000000 325 + 2.912500000000000 0.4875000000000000 326 + 2.912500000000000 0.5000000000000000 327 + 2.900000000000000 0.000000000000000 328 + 2.899999999999999 0.01250000000000000 329 + 2.900000000000000 0.02500000000000000 330 + 2.900000000000000 0.03750000000000001 331 + 2.900000000000000 0.05000000000000000 332 + 2.900000000000000 0.06250000000000000 333 + 2.900000000000000 0.07500000000000002 334 + 2.899999999999999 0.08750000000000004 335 + 2.900000000000000 0.1000000000000000 336 + 2.900000000000000 0.1125000000000000 337 + 2.900000000000000 0.1250000000000000 338 + 2.900000000000000 0.1375000000000000 339 + 2.900000000000000 0.1500000000000000 340 + 2.900000000000000 0.1625000000000000 341 + 2.900000000000000 0.1750000000000001 342 + 2.900000000000000 0.1875000000000000 343 + 2.900000000000000 0.2000000000000000 344 + 2.900000000000000 0.2125000000000000 345 + 2.900000000000000 0.2250000000000000 346 + 2.899999999999999 0.2375000000000001 347 + 2.900000000000000 0.2500000000000000 348 + 2.900000000000000 0.2625000000000000 349 + 2.900000000000000 0.2750000000000000 350 + 2.900000000000000 0.2875000000000001 351 + 2.900000000000000 0.3000000000000000 352 + 2.900000000000000 0.3125000000000000 353 + 2.900000000000000 0.3250000000000000 354 + 2.900000000000000 0.3375000000000001 355 + 2.900000000000000 0.3500000000000001 356 + 2.900000000000000 0.3625000000000000 357 + 2.900000000000000 0.3750000000000000 358 + 2.900000000000000 0.3875000000000000 359 + 2.899999999999999 0.4000000000000001 360 + 2.900000000000000 0.4125000000000001 361 + 2.900000000000000 0.4250000000000000 362 + 2.900000000000000 0.4375000000000000 363 + 2.900000000000000 0.4500000000000000 364 + 2.900000000000000 0.4625000000000001 365 + 2.899999999999999 0.4750000000000000 366 + 2.900000000000000 0.4875000000000000 367 + 2.900000000000000 0.5000000000000000 368 + 2.887500000000000 0.000000000000000 369 + 2.887500000000000 0.01250000000000000 370 + 2.887500000000001 0.02500000000000000 371 + 2.887500000000001 0.03750000000000001 372 + 2.887500000000000 0.05000000000000000 373 + 2.887500000000000 0.06250000000000000 374 + 2.887500000000000 0.07500000000000001 375 + 2.887500000000001 0.08750000000000004 376 + 2.887500000000000 0.1000000000000000 377 + 2.887500000000000 0.1125000000000000 378 + 2.887500000000000 0.1250000000000000 379 + 2.887500000000000 0.1375000000000001 380 + 2.887500000000001 0.1500000000000000 381 + 2.887500000000000 0.1625000000000000 382 + 2.887500000000001 0.1750000000000000 383 + 2.887500000000001 0.1874999999999999 384 + 2.887500000000001 0.2000000000000000 385 + 2.887500000000001 0.2125000000000000 386 + 2.887500000000001 0.2250000000000000 387 + 2.887500000000001 0.2375000000000000 388 + 2.887500000000001 0.2500000000000000 389 + 2.887500000000001 0.2625000000000000 390 + 2.887500000000001 0.2750000000000001 391 + 2.887500000000001 0.2875000000000000 392 + 2.887500000000001 0.3000000000000000 393 + 2.887500000000001 0.3124999999999999 394 + 2.887500000000001 0.3250000000000000 395 + 2.887500000000000 0.3375000000000000 396 + 2.887500000000001 0.3500000000000000 397 + 2.887500000000001 0.3625000000000000 398 + 2.887500000000001 0.3750000000000001 399 + 2.887500000000001 0.3875000000000001 400 + 2.887500000000001 0.3999999999999999 401 + 2.887500000000001 0.4125000000000000 402 + 2.887500000000001 0.4249999999999999 403 + 2.887500000000000 0.4375000000000000 404 + 2.887500000000000 0.4500000000000000 405 + 2.887500000000000 0.4625000000000000 406 + 2.887500000000000 0.4750000000000000 407 + 2.887500000000000 0.4875000000000002 408 + 2.887500000000000 0.5000000000000000 409 + 2.875000000000000 0.000000000000000 410 + 2.875000000000001 0.01250000000000000 411 + 2.875000000000000 0.02500000000000000 412 + 2.875000000000000 0.03750000000000000 413 + 2.875000000000001 0.05000000000000000 414 + 2.875000000000001 0.06250000000000000 415 + 2.875000000000001 0.07500000000000000 416 + 2.875000000000000 0.08750000000000002 417 + 2.875000000000000 0.09999999999999999 418 + 2.875000000000000 0.1125000000000000 419 + 2.875000000000000 0.1250000000000000 420 + 2.875000000000000 0.1375000000000000 421 + 2.875000000000000 0.1500000000000000 422 + 2.875000000000001 0.1625000000000000 423 + 2.875000000000000 0.1750000000000000 424 + 2.875000000000000 0.1875000000000000 425 + 2.875000000000000 0.2000000000000000 426 + 2.875000000000000 0.2125000000000000 427 + 2.875000000000000 0.2250000000000000 428 + 2.875000000000000 0.2375000000000000 429 + 2.875000000000000 0.2500000000000000 430 + 2.875000000000000 0.2624999999999999 431 + 2.875000000000000 0.2750000000000000 432 + 2.875000000000000 0.2875000000000001 433 + 2.875000000000000 0.3000000000000000 434 + 2.875000000000000 0.3125000000000001 435 + 2.875000000000000 0.3250000000000000 436 + 2.875000000000000 0.3375000000000000 437 + 2.875000000000000 0.3500000000000000 438 + 2.875000000000000 0.3625000000000002 439 + 2.875000000000000 0.3750000000000000 440 + 2.875000000000000 0.3875000000000001 441 + 2.875000000000000 0.4000000000000000 442 + 2.875000000000000 0.4125000000000000 443 + 2.875000000000000 0.4250000000000000 444 + 2.875000000000000 0.4375000000000000 445 + 2.875000000000000 0.4500000000000000 446 + 2.875000000000000 0.4625000000000001 447 + 2.875000000000000 0.4750000000000000 448 + 2.875000000000000 0.4875000000000000 449 + 2.875000000000000 0.5000000000000000 450 + 2.862500000000000 0.000000000000000 451 + 2.862500000000000 0.01250000000000000 452 + 2.862500000000000 0.02500000000000000 453 + 2.862500000000000 0.03750000000000000 454 + 2.862500000000000 0.05000000000000000 455 + 2.862500000000000 0.06249999999999999 456 + 2.862499999999999 0.07499999999999998 457 + 2.862500000000000 0.08750000000000001 458 + 2.862500000000000 0.1000000000000000 459 + 2.862500000000000 0.1125000000000000 460 + 2.862499999999999 0.1250000000000000 461 + 2.862500000000000 0.1375000000000000 462 + 2.862500000000000 0.1500000000000000 463 + 2.862500000000000 0.1625000000000001 464 + 2.862499999999999 0.1750000000000000 465 + 2.862499999999999 0.1875000000000000 466 + 2.862499999999999 0.2000000000000000 467 + 2.862499999999999 0.2125000000000000 468 + 2.862500000000000 0.2250000000000000 469 + 2.862499999999999 0.2375000000000001 470 + 2.862499999999999 0.2500000000000000 471 + 2.862499999999999 0.2625000000000000 472 + 2.862499999999999 0.2749999999999999 473 + 2.862499999999999 0.2874999999999999 474 + 2.862499999999999 0.3000000000000000 475 + 2.862499999999999 0.3125000000000000 476 + 2.862499999999999 0.3250000000000000 477 + 2.862499999999999 0.3375000000000000 478 + 2.862499999999999 0.3500000000000000 479 + 2.862500000000000 0.3624999999999999 480 + 2.862499999999999 0.3750000000000001 481 + 2.862499999999999 0.3875000000000001 482 + 2.862500000000000 0.4000000000000000 483 + 2.862500000000000 0.4125000000000000 484 + 2.862500000000000 0.4249999999999999 485 + 2.862500000000000 0.4375000000000001 486 + 2.862500000000000 0.4500000000000000 487 + 2.862500000000000 0.4625000000000000 488 + 2.862500000000000 0.4750000000000000 489 + 2.862500000000000 0.4874999999999999 490 + 2.862500000000000 0.5000000000000000 491 + 2.850000000000001 0.000000000000000 492 + 2.850000000000001 0.01250000000000000 493 + 2.850000000000001 0.02500000000000000 494 + 2.850000000000001 0.03750000000000002 495 + 2.850000000000001 0.05000000000000000 496 + 2.850000000000001 0.06250000000000000 497 + 2.850000000000001 0.07500000000000004 498 + 2.850000000000001 0.08750000000000002 499 + 2.850000000000001 0.1000000000000000 500 + 2.850000000000001 0.1125000000000000 501 + 2.850000000000001 0.1250000000000000 502 + 2.850000000000001 0.1375000000000000 503 + 2.850000000000001 0.1500000000000000 504 + 2.850000000000001 0.1625000000000000 505 + 2.850000000000000 0.1750000000000000 506 + 2.850000000000001 0.1875000000000000 507 + 2.850000000000001 0.2000000000000000 508 + 2.850000000000001 0.2125000000000000 509 + 2.850000000000001 0.2250000000000000 510 + 2.850000000000001 0.2375000000000000 511 + 2.850000000000001 0.2500000000000000 512 + 2.850000000000001 0.2625000000000001 513 + 2.850000000000001 0.2749999999999999 514 + 2.850000000000000 0.2875000000000000 515 + 2.850000000000001 0.3000000000000000 516 + 2.850000000000000 0.3125000000000001 517 + 2.850000000000000 0.3250000000000000 518 + 2.850000000000001 0.3375000000000000 519 + 2.850000000000001 0.3499999999999999 520 + 2.850000000000000 0.3625000000000000 521 + 2.850000000000001 0.3750000000000000 522 + 2.850000000000001 0.3875000000000001 523 + 2.850000000000000 0.4000000000000000 524 + 2.850000000000000 0.4125000000000000 525 + 2.850000000000000 0.4250000000000000 526 + 2.850000000000000 0.4375000000000000 527 + 2.850000000000000 0.4500000000000000 528 + 2.850000000000001 0.4625000000000001 529 + 2.850000000000001 0.4750000000000000 530 + 2.850000000000000 0.4875000000000000 531 + 2.850000000000000 0.5000000000000000 532 + 2.837500000000000 0.000000000000000 533 + 2.837499999999999 0.01250000000000000 534 + 2.837500000000000 0.02500000000000000 535 + 2.837500000000000 0.03750000000000002 536 + 2.837499999999999 0.05000000000000000 537 + 2.837499999999999 0.06250000000000000 538 + 2.837499999999999 0.07500000000000004 539 + 2.837500000000000 0.08749999999999998 540 + 2.837499999999999 0.1000000000000000 541 + 2.837500000000000 0.1125000000000000 542 + 2.837500000000000 0.1250000000000000 543 + 2.837500000000000 0.1375000000000000 544 + 2.837500000000000 0.1500000000000000 545 + 2.837499999999999 0.1625000000000001 546 + 2.837500000000000 0.1750000000000000 547 + 2.837500000000000 0.1874999999999999 548 + 2.837500000000000 0.2000000000000000 549 + 2.837500000000000 0.2125000000000000 550 + 2.837500000000000 0.2250000000000000 551 + 2.837500000000000 0.2375000000000000 552 + 2.837500000000000 0.2500000000000000 553 + 2.837500000000000 0.2625000000000000 554 + 2.837500000000000 0.2750000000000000 555 + 2.837500000000000 0.2874999999999999 556 + 2.837500000000000 0.3000000000000000 557 + 2.837500000000000 0.3124999999999999 558 + 2.837500000000000 0.3250000000000001 559 + 2.837500000000000 0.3375000000000000 560 + 2.837500000000000 0.3500000000000000 561 + 2.837500000000000 0.3625000000000000 562 + 2.837500000000000 0.3750000000000000 563 + 2.837500000000001 0.3875000000000000 564 + 2.837500000000001 0.4000000000000001 565 + 2.837500000000001 0.4125000000000001 566 + 2.837500000000001 0.4250000000000000 567 + 2.837500000000001 0.4375000000000000 568 + 2.837500000000001 0.4500000000000000 569 + 2.837500000000001 0.4625000000000000 570 + 2.837500000000001 0.4750000000000001 571 + 2.837500000000001 0.4875000000000000 572 + 2.837500000000000 0.5000000000000000 573 + 2.825000000000000 0.000000000000000 574 + 2.825000000000001 0.01250000000000000 575 + 2.825000000000000 0.02500000000000001 576 + 2.825000000000001 0.03750000000000001 577 + 2.825000000000000 0.05000000000000001 578 + 2.825000000000000 0.06249999999999999 579 + 2.825000000000000 0.07500000000000001 580 + 2.825000000000001 0.08749999999999998 581 + 2.825000000000001 0.1000000000000000 582 + 2.825000000000000 0.1125000000000000 583 + 2.825000000000000 0.1250000000000000 584 + 2.825000000000000 0.1375000000000000 585 + 2.825000000000000 0.1500000000000000 586 + 2.825000000000001 0.1625000000000000 587 + 2.825000000000001 0.1750000000000000 588 + 2.825000000000001 0.1875000000000000 589 + 2.825000000000001 0.2000000000000000 590 + 2.825000000000001 0.2125000000000000 591 + 2.825000000000001 0.2250000000000001 592 + 2.825000000000001 0.2375000000000000 593 + 2.825000000000001 0.2500000000000000 594 + 2.825000000000000 0.2625000000000000 595 + 2.825000000000000 0.2750000000000000 596 + 2.825000000000000 0.2875000000000000 597 + 2.825000000000000 0.3000000000000000 598 + 2.825000000000000 0.3125000000000000 599 + 2.825000000000000 0.3250000000000000 600 + 2.825000000000000 0.3375000000000000 601 + 2.825000000000000 0.3500000000000000 602 + 2.825000000000000 0.3625000000000001 603 + 2.825000000000000 0.3749999999999999 604 + 2.825000000000000 0.3874999999999999 605 + 2.824999999999999 0.4000000000000000 606 + 2.824999999999999 0.4125000000000000 607 + 2.824999999999999 0.4250000000000000 608 + 2.824999999999999 0.4375000000000000 609 + 2.825000000000000 0.4500000000000000 610 + 2.824999999999999 0.4625000000000000 611 + 2.824999999999999 0.4749999999999999 612 + 2.824999999999999 0.4875000000000000 613 + 2.825000000000000 0.5000000000000000 614 + 2.812500000000000 0.000000000000000 615 + 2.812500000000000 0.01250000000000000 616 + 2.812500000000000 0.02500000000000000 617 + 2.812499999999999 0.03750000000000001 618 + 2.812500000000000 0.05000000000000000 619 + 2.812500000000000 0.06250000000000000 620 + 2.812500000000000 0.07500000000000001 621 + 2.812500000000000 0.08750000000000001 622 + 2.812499999999999 0.1000000000000000 623 + 2.812500000000000 0.1125000000000000 624 + 2.812500000000000 0.1250000000000000 625 + 2.812500000000000 0.1375000000000000 626 + 2.812500000000000 0.1500000000000000 627 + 2.812499999999999 0.1625000000000000 628 + 2.812500000000000 0.1750000000000000 629 + 2.812500000000000 0.1875000000000000 630 + 2.812500000000000 0.2000000000000000 631 + 2.812500000000000 0.2125000000000000 632 + 2.812500000000000 0.2250000000000000 633 + 2.812500000000000 0.2375000000000000 634 + 2.812500000000000 0.2500000000000000 635 + 2.812500000000000 0.2625000000000000 636 + 2.812500000000000 0.2750000000000000 637 + 2.812500000000000 0.2874999999999999 638 + 2.812500000000000 0.3000000000000000 639 + 2.812500000000000 0.3125000000000000 640 + 2.812500000000000 0.3250000000000001 641 + 2.812500000000000 0.3374999999999999 642 + 2.812500000000000 0.3500000000000000 643 + 2.812500000000000 0.3625000000000000 644 + 2.812500000000000 0.3750000000000001 645 + 2.812500000000000 0.3874999999999999 646 + 2.812500000000000 0.4000000000000000 647 + 2.812500000000000 0.4125000000000000 648 + 2.812500000000000 0.4250000000000000 649 + 2.812500000000000 0.4375000000000000 650 + 2.812500000000000 0.4500000000000000 651 + 2.812500000000000 0.4625000000000000 652 + 2.812500000000000 0.4750000000000000 653 + 2.812500000000000 0.4875000000000001 654 + 2.812500000000000 0.5000000000000000 655 + 2.800000000000000 0.000000000000000 656 + 2.800000000000000 0.01250000000000000 657 + 2.800000000000000 0.02500000000000000 658 + 2.800000000000000 0.03750000000000001 659 + 2.800000000000000 0.05000000000000000 660 + 2.800000000000000 0.06250000000000000 661 + 2.800000000000000 0.07500000000000001 662 + 2.800000000000000 0.08750000000000002 663 + 2.800000000000000 0.1000000000000000 664 + 2.800000000000000 0.1125000000000000 665 + 2.800000000000000 0.1250000000000000 666 + 2.800000000000000 0.1375000000000001 667 + 2.800000000000000 0.1500000000000000 668 + 2.800000000000000 0.1625000000000000 669 + 2.800000000000000 0.1750000000000000 670 + 2.800000000000000 0.1875000000000000 671 + 2.800000000000000 0.2000000000000001 672 + 2.800000000000000 0.2125000000000000 673 + 2.800000000000001 0.2250000000000000 674 + 2.800000000000000 0.2375000000000000 675 + 2.800000000000000 0.2500000000000000 676 + 2.800000000000000 0.2624999999999999 677 + 2.800000000000000 0.2750000000000000 678 + 2.800000000000000 0.2875000000000000 679 + 2.800000000000000 0.3000000000000000 680 + 2.800000000000000 0.3125000000000000 681 + 2.800000000000000 0.3249999999999999 682 + 2.800000000000000 0.3375000000000000 683 + 2.800000000000000 0.3500000000000000 684 + 2.800000000000000 0.3625000000000000 685 + 2.800000000000000 0.3750000000000000 686 + 2.799999999999999 0.3875000000000001 687 + 2.799999999999999 0.4000000000000000 688 + 2.799999999999999 0.4125000000000001 689 + 2.799999999999999 0.4250000000000000 690 + 2.799999999999999 0.4375000000000000 691 + 2.799999999999999 0.4500000000000000 692 + 2.799999999999999 0.4624999999999999 693 + 2.799999999999999 0.4750000000000001 694 + 2.799999999999999 0.4875000000000000 695 + 2.800000000000000 0.5000000000000000 696 + 2.787500000000001 0.000000000000000 697 + 2.787500000000000 0.01250000000000000 698 + 2.787500000000001 0.02500000000000001 699 + 2.787500000000000 0.03750000000000001 700 + 2.787500000000001 0.05000000000000001 701 + 2.787500000000001 0.06250000000000000 702 + 2.787500000000001 0.07500000000000004 703 + 2.787500000000001 0.08750000000000001 704 + 2.787500000000000 0.1000000000000000 705 + 2.787500000000001 0.1125000000000000 706 + 2.787500000000001 0.1250000000000000 707 + 2.787500000000001 0.1375000000000001 708 + 2.787500000000001 0.1500000000000001 709 + 2.787500000000000 0.1625000000000000 710 + 2.787500000000001 0.1750000000000000 711 + 2.787500000000001 0.1875000000000000 712 + 2.787500000000001 0.2000000000000000 713 + 2.787500000000001 0.2125000000000000 714 + 2.787500000000001 0.2250000000000000 715 + 2.787500000000001 0.2375000000000000 716 + 2.787500000000001 0.2500000000000000 717 + 2.787500000000001 0.2625000000000000 718 + 2.787500000000001 0.2750000000000000 719 + 2.787500000000001 0.2875000000000000 720 + 2.787500000000001 0.3000000000000000 721 + 2.787500000000001 0.3125000000000000 722 + 2.787500000000000 0.3250000000000001 723 + 2.787500000000001 0.3375000000000000 724 + 2.787500000000000 0.3500000000000000 725 + 2.787500000000001 0.3625000000000000 726 + 2.787500000000001 0.3749999999999999 727 + 2.787500000000001 0.3875000000000000 728 + 2.787500000000001 0.4000000000000000 729 + 2.787500000000001 0.4125000000000000 730 + 2.787500000000001 0.4250000000000000 731 + 2.787500000000001 0.4375000000000000 732 + 2.787500000000001 0.4500000000000000 733 + 2.787500000000001 0.4625000000000000 734 + 2.787500000000000 0.4750000000000000 735 + 2.787500000000000 0.4874999999999999 736 + 2.787500000000000 0.5000000000000000 737 + 2.775000000000000 0.000000000000000 738 + 2.775000000000000 0.01250000000000000 739 + 2.775000000000000 0.02500000000000000 740 + 2.775000000000001 0.03750000000000002 741 + 2.775000000000000 0.05000000000000000 742 + 2.775000000000000 0.06250000000000000 743 + 2.775000000000000 0.07500000000000004 744 + 2.775000000000000 0.08750000000000001 745 + 2.775000000000001 0.1000000000000000 746 + 2.775000000000000 0.1125000000000000 747 + 2.775000000000000 0.1250000000000000 748 + 2.775000000000000 0.1375000000000000 749 + 2.775000000000000 0.1500000000000000 750 + 2.775000000000001 0.1625000000000000 751 + 2.775000000000000 0.1750000000000001 752 + 2.775000000000000 0.1875000000000000 753 + 2.775000000000000 0.2000000000000000 754 + 2.775000000000000 0.2125000000000000 755 + 2.775000000000001 0.2250000000000000 756 + 2.775000000000000 0.2375000000000000 757 + 2.775000000000000 0.2500000000000000 758 + 2.775000000000000 0.2625000000000000 759 + 2.774999999999999 0.2749999999999999 760 + 2.774999999999999 0.2875000000000000 761 + 2.774999999999999 0.3000000000000000 762 + 2.774999999999999 0.3125000000000001 763 + 2.774999999999999 0.3250000000000000 764 + 2.774999999999999 0.3375000000000000 765 + 2.774999999999999 0.3500000000000001 766 + 2.774999999999999 0.3625000000000000 767 + 2.774999999999999 0.3749999999999999 768 + 2.774999999999999 0.3875000000000000 769 + 2.774999999999999 0.4000000000000001 770 + 2.774999999999999 0.4124999999999999 771 + 2.774999999999999 0.4250000000000001 772 + 2.774999999999999 0.4375000000000000 773 + 2.774999999999999 0.4500000000000001 774 + 2.774999999999999 0.4624999999999999 775 + 2.774999999999999 0.4750000000000000 776 + 2.774999999999999 0.4875000000000000 777 + 2.775000000000000 0.5000000000000000 778 + 2.762500000000000 0.000000000000000 779 + 2.762499999999999 0.01250000000000000 780 + 2.762500000000000 0.02500000000000000 781 + 2.762500000000000 0.03750000000000001 782 + 2.762500000000000 0.05000000000000000 783 + 2.762500000000000 0.06250000000000000 784 + 2.762500000000000 0.07500000000000001 785 + 2.762500000000000 0.08749999999999999 786 + 2.762500000000000 0.1000000000000000 787 + 2.762500000000000 0.1125000000000000 788 + 2.762500000000000 0.1250000000000000 789 + 2.762500000000000 0.1375000000000000 790 + 2.762500000000000 0.1500000000000000 791 + 2.762500000000000 0.1625000000000000 792 + 2.762500000000000 0.1750000000000000 793 + 2.762500000000000 0.1875000000000000 794 + 2.762500000000000 0.2000000000000000 795 + 2.762500000000000 0.2125000000000000 796 + 2.762500000000000 0.2250000000000000 797 + 2.762500000000000 0.2375000000000000 798 + 2.762500000000000 0.2500000000000000 799 + 2.762500000000000 0.2625000000000000 800 + 2.762499999999999 0.2750000000000000 801 + 2.762499999999999 0.2875000000000000 802 + 2.762499999999999 0.3000000000000000 803 + 2.762499999999999 0.3125000000000001 804 + 2.762499999999999 0.3250000000000000 805 + 2.762499999999999 0.3374999999999999 806 + 2.762499999999999 0.3500000000000000 807 + 2.762499999999999 0.3625000000000000 808 + 2.762499999999999 0.3750000000000000 809 + 2.762499999999999 0.3875000000000000 810 + 2.762500000000000 0.4000000000000000 811 + 2.762500000000000 0.4125000000000001 812 + 2.762500000000000 0.4250000000000000 813 + 2.762500000000000 0.4374999999999999 814 + 2.762500000000000 0.4500000000000000 815 + 2.762500000000000 0.4625000000000000 816 + 2.762500000000000 0.4750000000000001 817 + 2.762500000000000 0.4875000000000000 818 + 2.762500000000000 0.5000000000000000 819 + 2.750000000000000 0.000000000000000 820 + 2.750000000000000 0.01250000000000000 821 + 2.750000000000000 0.02500000000000000 822 + 2.750000000000000 0.03750000000000001 823 + 2.750000000000000 0.04999999999999999 824 + 2.750000000000000 0.06249999999999999 825 + 2.750000000000000 0.07500000000000001 826 + 2.750000000000000 0.08750000000000004 827 + 2.750000000000000 0.1000000000000000 828 + 2.750000000000000 0.1125000000000000 829 + 2.750000000000000 0.1250000000000000 830 + 2.750000000000000 0.1375000000000000 831 + 2.750000000000000 0.1500000000000000 832 + 2.750000000000000 0.1625000000000000 833 + 2.750000000000000 0.1750000000000000 834 + 2.750000000000000 0.1875000000000000 835 + 2.750000000000000 0.2000000000000000 836 + 2.750000000000000 0.2125000000000000 837 + 2.750000000000000 0.2250000000000000 838 + 2.750000000000000 0.2375000000000000 839 + 2.750000000000000 0.2500000000000000 840 + 2.750000000000000 0.2625000000000000 841 + 2.750000000000000 0.2750000000000000 842 + 2.750000000000000 0.2875000000000000 843 + 2.750000000000000 0.3000000000000000 844 + 2.750000000000000 0.3125000000000000 845 + 2.750000000000000 0.3250000000000000 846 + 2.750000000000000 0.3375000000000000 847 + 2.750000000000000 0.3500000000000000 848 + 2.750000000000000 0.3625000000000000 849 + 2.750000000000000 0.3750000000000000 850 + 2.750000000000000 0.3875000000000000 851 + 2.750000000000000 0.4000000000000000 852 + 2.750000000000000 0.4125000000000000 853 + 2.750000000000000 0.4250000000000000 854 + 2.750000000000000 0.4374999999999999 855 + 2.750000000000000 0.4499999999999999 856 + 2.750000000000000 0.4624999999999999 857 + 2.750000000000000 0.4749999999999999 858 + 2.750000000000000 0.4875000000000000 859 + 2.750000000000000 0.5000000000000000 860 + 2.737500000000000 0.000000000000000 861 + 2.737500000000000 0.01250000000000000 862 + 2.737500000000000 0.02500000000000000 863 + 2.737500000000001 0.03750000000000001 864 + 2.737500000000000 0.05000000000000000 865 + 2.737500000000000 0.06250000000000000 866 + 2.737500000000000 0.07500000000000001 867 + 2.737500000000000 0.08750000000000004 868 + 2.737500000000001 0.1000000000000000 869 + 2.737500000000001 0.1125000000000000 870 + 2.737500000000000 0.1250000000000000 871 + 2.737500000000000 0.1375000000000000 872 + 2.737500000000000 0.1500000000000000 873 + 2.737500000000000 0.1625000000000000 874 + 2.737500000000000 0.1750000000000000 875 + 2.737500000000000 0.1875000000000000 876 + 2.737500000000000 0.2000000000000000 877 + 2.737500000000000 0.2125000000000000 878 + 2.737500000000000 0.2250000000000000 879 + 2.737500000000000 0.2375000000000000 880 + 2.737500000000000 0.2500000000000000 881 + 2.737500000000000 0.2624999999999999 882 + 2.737500000000000 0.2750000000000000 883 + 2.737500000000000 0.2875000000000001 884 + 2.737500000000000 0.2999999999999999 885 + 2.737500000000000 0.3125000000000000 886 + 2.737500000000000 0.3250000000000001 887 + 2.737500000000000 0.3375000000000000 888 + 2.737500000000000 0.3500000000000000 889 + 2.737500000000000 0.3625000000000000 890 + 2.737500000000000 0.3749999999999999 891 + 2.737500000000000 0.3875000000000000 892 + 2.737500000000000 0.4000000000000000 893 + 2.737500000000001 0.4124999999999999 894 + 2.737500000000001 0.4250000000000000 895 + 2.737500000000001 0.4375000000000000 896 + 2.737500000000001 0.4500000000000001 897 + 2.737500000000001 0.4625000000000000 898 + 2.737500000000001 0.4750000000000000 899 + 2.737500000000001 0.4875000000000002 900 + 2.737500000000000 0.5000000000000000 901 + 2.725000000000001 0.000000000000000 902 + 2.725000000000001 0.01250000000000000 903 + 2.725000000000001 0.02500000000000000 904 + 2.725000000000001 0.03750000000000001 905 + 2.725000000000001 0.05000000000000000 906 + 2.725000000000001 0.06250000000000000 907 + 2.725000000000001 0.07500000000000001 908 + 2.725000000000001 0.08750000000000004 909 + 2.725000000000001 0.1000000000000000 910 + 2.725000000000001 0.1125000000000000 911 + 2.725000000000000 0.1250000000000000 912 + 2.725000000000001 0.1375000000000000 913 + 2.725000000000001 0.1500000000000001 914 + 2.725000000000001 0.1625000000000000 915 + 2.725000000000001 0.1750000000000000 916 + 2.725000000000001 0.1875000000000000 917 + 2.725000000000001 0.2000000000000000 918 + 2.725000000000001 0.2125000000000000 919 + 2.725000000000001 0.2250000000000000 920 + 2.725000000000001 0.2375000000000000 921 + 2.725000000000001 0.2500000000000000 922 + 2.725000000000001 0.2625000000000000 923 + 2.725000000000001 0.2750000000000000 924 + 2.725000000000001 0.2875000000000000 925 + 2.725000000000001 0.3000000000000000 926 + 2.725000000000001 0.3124999999999999 927 + 2.725000000000001 0.3250000000000001 928 + 2.725000000000001 0.3375000000000000 929 + 2.725000000000001 0.3499999999999999 930 + 2.725000000000001 0.3625000000000002 931 + 2.725000000000000 0.3750000000000000 932 + 2.725000000000000 0.3875000000000000 933 + 2.725000000000000 0.4000000000000000 934 + 2.725000000000000 0.4125000000000000 935 + 2.725000000000000 0.4250000000000000 936 + 2.725000000000000 0.4375000000000001 937 + 2.725000000000000 0.4500000000000001 938 + 2.725000000000000 0.4624999999999999 939 + 2.725000000000000 0.4750000000000001 940 + 2.725000000000000 0.4875000000000000 941 + 2.725000000000000 0.5000000000000000 942 + 2.712500000000000 0.000000000000000 943 + 2.712500000000000 0.01250000000000000 944 + 2.712500000000000 0.02500000000000000 945 + 2.712499999999999 0.03750000000000001 946 + 2.712500000000000 0.05000000000000000 947 + 2.712500000000000 0.06249999999999999 948 + 2.712500000000000 0.07500000000000001 949 + 2.712499999999999 0.08749999999999999 950 + 2.712499999999999 0.1000000000000000 951 + 2.712500000000000 0.1125000000000000 952 + 2.712500000000000 0.1250000000000000 953 + 2.712500000000000 0.1375000000000001 954 + 2.712500000000000 0.1500000000000001 955 + 2.712499999999999 0.1625000000000000 956 + 2.712499999999999 0.1750000000000000 957 + 2.712499999999999 0.1875000000000000 958 + 2.712499999999999 0.2000000000000000 959 + 2.712499999999999 0.2125000000000000 960 + 2.712500000000000 0.2250000000000000 961 + 2.712499999999999 0.2375000000000000 962 + 2.712499999999999 0.2500000000000000 963 + 2.712499999999999 0.2625000000000000 964 + 2.712500000000000 0.2750000000000000 965 + 2.712500000000000 0.2875000000000000 966 + 2.712500000000000 0.3000000000000000 967 + 2.712500000000000 0.3125000000000000 968 + 2.712500000000000 0.3250000000000000 969 + 2.712500000000000 0.3375000000000000 970 + 2.712500000000000 0.3500000000000000 971 + 2.712499999999999 0.3625000000000000 972 + 2.712499999999999 0.3750000000000000 973 + 2.712499999999999 0.3875000000000001 974 + 2.712499999999999 0.4000000000000000 975 + 2.712499999999999 0.4125000000000000 976 + 2.712499999999999 0.4250000000000000 977 + 2.712499999999999 0.4375000000000000 978 + 2.712499999999999 0.4500000000000000 979 + 2.712499999999999 0.4625000000000000 980 + 2.712499999999999 0.4750000000000000 981 + 2.712499999999999 0.4875000000000000 982 + 2.712500000000000 0.5000000000000000 983 + 2.700000000000000 0.000000000000000 984 + 2.700000000000000 0.01250000000000000 985 + 2.700000000000001 0.02500000000000000 986 + 2.700000000000000 0.03750000000000001 987 + 2.700000000000000 0.05000000000000000 988 + 2.700000000000000 0.06250000000000000 989 + 2.700000000000000 0.07500000000000001 990 + 2.700000000000001 0.08750000000000001 991 + 2.700000000000000 0.1000000000000000 992 + 2.700000000000000 0.1125000000000000 993 + 2.700000000000000 0.1250000000000000 994 + 2.700000000000000 0.1375000000000000 995 + 2.700000000000001 0.1500000000000000 996 + 2.700000000000000 0.1625000000000000 997 + 2.700000000000001 0.1750000000000000 998 + 2.700000000000001 0.1875000000000000 999 + 2.700000000000001 0.2000000000000000 1000 + 2.700000000000001 0.2125000000000000 1001 + 2.700000000000001 0.2250000000000000 1002 + 2.700000000000001 0.2375000000000000 1003 + 2.700000000000001 0.2500000000000000 1004 + 2.700000000000001 0.2625000000000000 1005 + 2.700000000000001 0.2750000000000000 1006 + 2.700000000000000 0.2875000000000001 1007 + 2.700000000000000 0.3000000000000000 1008 + 2.700000000000000 0.3125000000000000 1009 + 2.700000000000000 0.3250000000000001 1010 + 2.700000000000000 0.3375000000000000 1011 + 2.700000000000000 0.3500000000000000 1012 + 2.700000000000000 0.3625000000000000 1013 + 2.700000000000000 0.3750000000000000 1014 + 2.700000000000000 0.3875000000000001 1015 + 2.700000000000000 0.4000000000000000 1016 + 2.700000000000000 0.4125000000000000 1017 + 2.700000000000000 0.4250000000000002 1018 + 2.700000000000000 0.4375000000000000 1019 + 2.700000000000000 0.4500000000000001 1020 + 2.700000000000000 0.4625000000000000 1021 + 2.700000000000000 0.4750000000000001 1022 + 2.700000000000000 0.4875000000000000 1023 + 2.700000000000000 0.5000000000000000 1024 + 2.687500000000000 0.000000000000000 1025 + 2.687500000000000 0.01250000000000000 1026 + 2.687500000000000 0.02500000000000000 1027 + 2.687500000000000 0.03750000000000001 1028 + 2.687500000000000 0.05000000000000000 1029 + 2.687500000000000 0.06250000000000000 1030 + 2.687500000000000 0.07500000000000001 1031 + 2.687500000000000 0.08750000000000001 1032 + 2.687500000000000 0.09999999999999998 1033 + 2.687500000000000 0.1125000000000000 1034 + 2.687500000000000 0.1250000000000000 1035 + 2.687500000000000 0.1375000000000000 1036 + 2.687500000000000 0.1500000000000000 1037 + 2.687500000000000 0.1625000000000000 1038 + 2.687500000000000 0.1750000000000000 1039 + 2.687500000000000 0.1875000000000000 1040 + 2.687500000000000 0.2000000000000000 1041 + 2.687500000000000 0.2125000000000000 1042 + 2.687500000000000 0.2250000000000000 1043 + 2.687500000000000 0.2375000000000000 1044 + 2.687500000000000 0.2500000000000000 1045 + 2.687500000000000 0.2625000000000000 1046 + 2.687500000000000 0.2749999999999999 1047 + 2.687500000000000 0.2875000000000000 1048 + 2.687500000000000 0.3000000000000000 1049 + 2.687500000000000 0.3124999999999999 1050 + 2.687500000000000 0.3250000000000000 1051 + 2.687500000000000 0.3375000000000000 1052 + 2.687500000000000 0.3500000000000000 1053 + 2.687500000000000 0.3624999999999999 1054 + 2.687500000000000 0.3750000000000000 1055 + 2.687500000000000 0.3875000000000000 1056 + 2.687500000000000 0.4000000000000000 1057 + 2.687500000000000 0.4125000000000000 1058 + 2.687500000000000 0.4250000000000000 1059 + 2.687500000000000 0.4375000000000000 1060 + 2.687500000000000 0.4500000000000000 1061 + 2.687500000000000 0.4625000000000000 1062 + 2.687500000000000 0.4750000000000000 1063 + 2.687500000000000 0.4875000000000000 1064 + 2.687500000000000 0.5000000000000000 1065 + 2.675000000000000 0.000000000000000 1066 + 2.675000000000001 0.01250000000000000 1067 + 2.675000000000001 0.02500000000000000 1068 + 2.675000000000001 0.03750000000000001 1069 + 2.675000000000001 0.05000000000000000 1070 + 2.675000000000001 0.06250000000000000 1071 + 2.675000000000001 0.07500000000000001 1072 + 2.675000000000001 0.08749999999999998 1073 + 2.675000000000001 0.1000000000000000 1074 + 2.675000000000001 0.1125000000000000 1075 + 2.675000000000001 0.1250000000000000 1076 + 2.675000000000001 0.1375000000000000 1077 + 2.675000000000001 0.1500000000000000 1078 + 2.675000000000001 0.1625000000000000 1079 + 2.675000000000001 0.1750000000000000 1080 + 2.675000000000001 0.1875000000000000 1081 + 2.675000000000001 0.2000000000000000 1082 + 2.675000000000001 0.2125000000000000 1083 + 2.675000000000001 0.2250000000000000 1084 + 2.675000000000000 0.2375000000000000 1085 + 2.675000000000001 0.2500000000000000 1086 + 2.675000000000001 0.2625000000000000 1087 + 2.675000000000001 0.2750000000000000 1088 + 2.675000000000001 0.2874999999999999 1089 + 2.675000000000001 0.2999999999999999 1090 + 2.675000000000000 0.3125000000000000 1091 + 2.675000000000000 0.3250000000000001 1092 + 2.675000000000000 0.3375000000000001 1093 + 2.675000000000000 0.3500000000000000 1094 + 2.675000000000000 0.3625000000000000 1095 + 2.675000000000000 0.3750000000000000 1096 + 2.675000000000000 0.3875000000000000 1097 + 2.675000000000000 0.4000000000000000 1098 + 2.674999999999999 0.4125000000000001 1099 + 2.674999999999999 0.4250000000000002 1100 + 2.674999999999999 0.4375000000000000 1101 + 2.674999999999999 0.4500000000000000 1102 + 2.674999999999999 0.4625000000000000 1103 + 2.675000000000000 0.4749999999999999 1104 + 2.675000000000000 0.4874999999999999 1105 + 2.675000000000000 0.5000000000000000 1106 + 2.662500000000001 0.000000000000000 1107 + 2.662500000000000 0.01250000000000000 1108 + 2.662500000000000 0.02500000000000000 1109 + 2.662500000000000 0.03750000000000001 1110 + 2.662500000000001 0.05000000000000000 1111 + 2.662500000000001 0.06250000000000000 1112 + 2.662500000000001 0.07500000000000001 1113 + 2.662499999999999 0.08749999999999998 1114 + 2.662500000000000 0.1000000000000000 1115 + 2.662500000000000 0.1125000000000000 1116 + 2.662500000000000 0.1250000000000000 1117 + 2.662500000000000 0.1375000000000000 1118 + 2.662500000000000 0.1500000000000001 1119 + 2.662500000000001 0.1625000000000001 1120 + 2.662499999999999 0.1750000000000000 1121 + 2.662500000000000 0.1875000000000000 1122 + 2.662500000000000 0.2000000000000000 1123 + 2.662500000000000 0.2125000000000000 1124 + 2.662500000000000 0.2250000000000000 1125 + 2.662500000000000 0.2375000000000000 1126 + 2.662500000000000 0.2499999999999999 1127 + 2.662500000000000 0.2625000000000000 1128 + 2.662500000000000 0.2750000000000000 1129 + 2.662500000000000 0.2875000000000000 1130 + 2.662500000000000 0.3000000000000000 1131 + 2.662499999999999 0.3125000000000001 1132 + 2.662500000000000 0.3250000000000000 1133 + 2.662500000000000 0.3375000000000000 1134 + 2.662500000000000 0.3500000000000000 1135 + 2.662500000000000 0.3625000000000000 1136 + 2.662500000000000 0.3750000000000000 1137 + 2.662500000000000 0.3875000000000000 1138 + 2.662500000000000 0.4000000000000000 1139 + 2.662500000000000 0.4125000000000000 1140 + 2.662500000000000 0.4250000000000001 1141 + 2.662500000000001 0.4375000000000000 1142 + 2.662500000000001 0.4500000000000000 1143 + 2.662500000000001 0.4625000000000000 1144 + 2.662500000000001 0.4750000000000000 1145 + 2.662500000000001 0.4875000000000000 1146 + 2.662500000000000 0.5000000000000000 1147 + 2.650000000000000 0.000000000000000 1148 + 2.649999999999999 0.01250000000000000 1149 + 2.650000000000000 0.02500000000000000 1150 + 2.649999999999999 0.03750000000000000 1151 + 2.649999999999999 0.05000000000000000 1152 + 2.650000000000000 0.06250000000000000 1153 + 2.649999999999999 0.07500000000000000 1154 + 2.650000000000000 0.08750000000000001 1155 + 2.650000000000000 0.09999999999999999 1156 + 2.650000000000000 0.1125000000000000 1157 + 2.650000000000000 0.1250000000000000 1158 + 2.650000000000000 0.1375000000000000 1159 + 2.650000000000000 0.1500000000000000 1160 + 2.650000000000000 0.1625000000000000 1161 + 2.650000000000000 0.1750000000000000 1162 + 2.650000000000000 0.1875000000000000 1163 + 2.650000000000000 0.2000000000000000 1164 + 2.650000000000000 0.2125000000000000 1165 + 2.650000000000000 0.2250000000000000 1166 + 2.650000000000000 0.2375000000000000 1167 + 2.650000000000000 0.2500000000000000 1168 + 2.650000000000000 0.2625000000000000 1169 + 2.650000000000000 0.2750000000000000 1170 + 2.650000000000000 0.2874999999999999 1171 + 2.650000000000000 0.3000000000000001 1172 + 2.650000000000000 0.3125000000000000 1173 + 2.650000000000000 0.3250000000000000 1174 + 2.650000000000000 0.3374999999999999 1175 + 2.650000000000000 0.3500000000000001 1176 + 2.650000000000000 0.3625000000000000 1177 + 2.650000000000000 0.3750000000000000 1178 + 2.650000000000000 0.3875000000000000 1179 + 2.650000000000000 0.4000000000000000 1180 + 2.650000000000000 0.4125000000000000 1181 + 2.650000000000000 0.4250000000000000 1182 + 2.650000000000000 0.4375000000000000 1183 + 2.650000000000000 0.4500000000000000 1184 + 2.650000000000000 0.4625000000000000 1185 + 2.650000000000000 0.4750000000000001 1186 + 2.650000000000000 0.4875000000000000 1187 + 2.650000000000000 0.5000000000000000 1188 + 2.637500000000000 0.000000000000000 1189 + 2.637500000000000 0.01250000000000000 1190 + 2.637500000000000 0.02500000000000000 1191 + 2.637500000000000 0.03750000000000001 1192 + 2.637500000000000 0.05000000000000000 1193 + 2.637500000000000 0.06250000000000000 1194 + 2.637500000000000 0.07500000000000001 1195 + 2.637500000000000 0.08750000000000001 1196 + 2.637500000000000 0.1000000000000000 1197 + 2.637500000000000 0.1125000000000000 1198 + 2.637500000000000 0.1250000000000000 1199 + 2.637500000000000 0.1375000000000000 1200 + 2.637500000000000 0.1500000000000000 1201 + 2.637500000000000 0.1625000000000001 1202 + 2.637500000000000 0.1750000000000000 1203 + 2.637500000000000 0.1875000000000000 1204 + 2.637500000000000 0.2000000000000000 1205 + 2.637500000000000 0.2125000000000000 1206 + 2.637500000000000 0.2250000000000000 1207 + 2.637500000000000 0.2375000000000000 1208 + 2.637500000000000 0.2500000000000000 1209 + 2.637500000000000 0.2625000000000000 1210 + 2.637500000000000 0.2750000000000001 1211 + 2.637500000000000 0.2875000000000000 1212 + 2.637500000000001 0.3000000000000000 1213 + 2.637500000000001 0.3125000000000000 1214 + 2.637500000000001 0.3250000000000000 1215 + 2.637500000000001 0.3375000000000000 1216 + 2.637500000000001 0.3500000000000000 1217 + 2.637500000000001 0.3625000000000002 1218 + 2.637500000000001 0.3750000000000000 1219 + 2.637500000000001 0.3874999999999999 1220 + 2.637500000000001 0.4000000000000000 1221 + 2.637500000000001 0.4125000000000000 1222 + 2.637500000000001 0.4250000000000000 1223 + 2.637500000000001 0.4375000000000000 1224 + 2.637500000000001 0.4500000000000000 1225 + 2.637500000000001 0.4625000000000000 1226 + 2.637500000000001 0.4750000000000001 1227 + 2.637500000000001 0.4875000000000000 1228 + 2.637500000000000 0.5000000000000000 1229 + 2.625000000000000 0.000000000000000 1230 + 2.625000000000000 0.01250000000000000 1231 + 2.625000000000001 0.02500000000000000 1232 + 2.625000000000000 0.03749999999999999 1233 + 2.625000000000000 0.05000000000000000 1234 + 2.625000000000000 0.06250000000000000 1235 + 2.625000000000000 0.07499999999999998 1236 + 2.625000000000001 0.08750000000000001 1237 + 2.625000000000000 0.1000000000000000 1238 + 2.625000000000000 0.1125000000000000 1239 + 2.625000000000000 0.1250000000000000 1240 + 2.625000000000000 0.1375000000000001 1241 + 2.625000000000000 0.1500000000000000 1242 + 2.625000000000000 0.1625000000000000 1243 + 2.625000000000000 0.1750000000000001 1244 + 2.625000000000001 0.1875000000000000 1245 + 2.625000000000001 0.2000000000000000 1246 + 2.625000000000001 0.2125000000000000 1247 + 2.625000000000001 0.2250000000000001 1248 + 2.625000000000001 0.2375000000000000 1249 + 2.625000000000001 0.2500000000000000 1250 + 2.625000000000001 0.2625000000000000 1251 + 2.625000000000001 0.2750000000000000 1252 + 2.625000000000001 0.2875000000000000 1253 + 2.625000000000001 0.3000000000000000 1254 + 2.625000000000001 0.3124999999999999 1255 + 2.625000000000000 0.3250000000000000 1256 + 2.625000000000000 0.3375000000000000 1257 + 2.625000000000001 0.3500000000000000 1258 + 2.625000000000001 0.3624999999999999 1259 + 2.625000000000001 0.3750000000000000 1260 + 2.625000000000000 0.3874999999999999 1261 + 2.625000000000001 0.4000000000000000 1262 + 2.625000000000000 0.4125000000000001 1263 + 2.625000000000000 0.4250000000000000 1264 + 2.625000000000000 0.4375000000000001 1265 + 2.625000000000000 0.4500000000000000 1266 + 2.625000000000000 0.4625000000000000 1267 + 2.625000000000000 0.4750000000000000 1268 + 2.625000000000000 0.4875000000000002 1269 + 2.625000000000000 0.5000000000000000 1270 + 2.612500000000000 0.000000000000000 1271 + 2.612500000000000 0.01250000000000000 1272 + 2.612499999999999 0.02500000000000000 1273 + 2.612499999999999 0.03750000000000001 1274 + 2.612500000000000 0.05000000000000000 1275 + 2.612500000000000 0.06250000000000000 1276 + 2.612500000000000 0.07500000000000001 1277 + 2.612499999999999 0.08750000000000001 1278 + 2.612500000000000 0.1000000000000000 1279 + 2.612500000000000 0.1125000000000000 1280 + 2.612499999999999 0.1250000000000000 1281 + 2.612500000000000 0.1375000000000000 1282 + 2.612500000000000 0.1500000000000000 1283 + 2.612500000000000 0.1625000000000000 1284 + 2.612499999999999 0.1750000000000000 1285 + 2.612500000000000 0.1875000000000000 1286 + 2.612499999999999 0.2000000000000000 1287 + 2.612499999999999 0.2125000000000001 1288 + 2.612500000000000 0.2250000000000000 1289 + 2.612499999999999 0.2375000000000000 1290 + 2.612499999999999 0.2500000000000000 1291 + 2.612499999999999 0.2625000000000000 1292 + 2.612499999999999 0.2750000000000000 1293 + 2.612499999999999 0.2875000000000000 1294 + 2.612499999999999 0.3000000000000000 1295 + 2.612499999999999 0.3125000000000000 1296 + 2.612499999999999 0.3250000000000000 1297 + 2.612499999999999 0.3375000000000000 1298 + 2.612500000000000 0.3499999999999999 1299 + 2.612500000000000 0.3625000000000001 1300 + 2.612500000000000 0.3750000000000000 1301 + 2.612500000000000 0.3875000000000000 1302 + 2.612500000000000 0.4000000000000000 1303 + 2.612500000000000 0.4125000000000001 1304 + 2.612500000000000 0.4250000000000000 1305 + 2.612500000000000 0.4375000000000000 1306 + 2.612500000000000 0.4500000000000000 1307 + 2.612500000000000 0.4625000000000000 1308 + 2.612500000000000 0.4750000000000000 1309 + 2.612500000000000 0.4875000000000000 1310 + 2.612500000000000 0.5000000000000000 1311 + 2.600000000000001 0.000000000000000 1312 + 2.600000000000000 0.01250000000000000 1313 + 2.600000000000001 0.02500000000000000 1314 + 2.600000000000001 0.03750000000000001 1315 + 2.600000000000000 0.05000000000000000 1316 + 2.600000000000001 0.06250000000000000 1317 + 2.600000000000001 0.07500000000000001 1318 + 2.600000000000001 0.08750000000000001 1319 + 2.600000000000000 0.1000000000000000 1320 + 2.600000000000001 0.1125000000000000 1321 + 2.600000000000001 0.1250000000000000 1322 + 2.600000000000001 0.1375000000000000 1323 + 2.600000000000001 0.1500000000000001 1324 + 2.600000000000001 0.1625000000000000 1325 + 2.600000000000001 0.1750000000000000 1326 + 2.600000000000001 0.1875000000000000 1327 + 2.600000000000001 0.2000000000000000 1328 + 2.600000000000001 0.2125000000000001 1329 + 2.600000000000001 0.2250000000000000 1330 + 2.600000000000000 0.2375000000000000 1331 + 2.600000000000001 0.2499999999999999 1332 + 2.600000000000001 0.2625000000000000 1333 + 2.600000000000001 0.2750000000000000 1334 + 2.600000000000001 0.2875000000000000 1335 + 2.600000000000001 0.3000000000000000 1336 + 2.600000000000000 0.3125000000000000 1337 + 2.600000000000001 0.3250000000000001 1338 + 2.600000000000000 0.3375000000000000 1339 + 2.600000000000001 0.3499999999999999 1340 + 2.600000000000000 0.3625000000000000 1341 + 2.600000000000001 0.3750000000000000 1342 + 2.600000000000000 0.3875000000000000 1343 + 2.600000000000000 0.4000000000000000 1344 + 2.600000000000000 0.4125000000000001 1345 + 2.600000000000000 0.4250000000000000 1346 + 2.600000000000000 0.4375000000000000 1347 + 2.600000000000000 0.4500000000000001 1348 + 2.600000000000000 0.4625000000000000 1349 + 2.600000000000000 0.4750000000000000 1350 + 2.600000000000001 0.4875000000000000 1351 + 2.600000000000000 0.5000000000000000 1352 + 2.587500000000000 0.000000000000000 1353 + 2.587499999999999 0.01250000000000000 1354 + 2.587499999999999 0.02500000000000000 1355 + 2.587500000000001 0.03750000000000001 1356 + 2.587499999999999 0.05000000000000000 1357 + 2.587499999999999 0.06250000000000000 1358 + 2.587499999999999 0.07500000000000000 1359 + 2.587499999999999 0.08750000000000001 1360 + 2.587500000000000 0.1000000000000000 1361 + 2.587499999999999 0.1125000000000000 1362 + 2.587499999999999 0.1250000000000000 1363 + 2.587499999999999 0.1375000000000000 1364 + 2.587499999999999 0.1500000000000000 1365 + 2.587500000000000 0.1625000000000000 1366 + 2.587499999999999 0.1750000000000000 1367 + 2.587499999999999 0.1875000000000000 1368 + 2.587499999999999 0.2000000000000000 1369 + 2.587500000000000 0.2125000000000000 1370 + 2.587500000000000 0.2250000000000000 1371 + 2.587500000000000 0.2375000000000000 1372 + 2.587500000000000 0.2500000000000000 1373 + 2.587500000000000 0.2625000000000000 1374 + 2.587500000000000 0.2750000000000000 1375 + 2.587500000000000 0.2875000000000000 1376 + 2.587500000000000 0.3000000000000000 1377 + 2.587500000000000 0.3124999999999999 1378 + 2.587500000000000 0.3250000000000001 1379 + 2.587500000000001 0.3374999999999999 1380 + 2.587500000000001 0.3500000000000000 1381 + 2.587500000000001 0.3625000000000000 1382 + 2.587500000000001 0.3750000000000000 1383 + 2.587500000000001 0.3875000000000000 1384 + 2.587500000000000 0.4000000000000000 1385 + 2.587500000000001 0.4124999999999999 1386 + 2.587500000000001 0.4250000000000000 1387 + 2.587500000000001 0.4374999999999999 1388 + 2.587500000000001 0.4500000000000000 1389 + 2.587500000000001 0.4625000000000000 1390 + 2.587500000000001 0.4750000000000000 1391 + 2.587500000000001 0.4875000000000000 1392 + 2.587500000000000 0.5000000000000000 1393 + 2.575000000000000 0.000000000000000 1394 + 2.575000000000001 0.01250000000000000 1395 + 2.575000000000000 0.02500000000000000 1396 + 2.575000000000001 0.03750000000000001 1397 + 2.575000000000001 0.05000000000000000 1398 + 2.575000000000001 0.06250000000000000 1399 + 2.575000000000001 0.07500000000000002 1400 + 2.575000000000000 0.08750000000000001 1401 + 2.575000000000001 0.1000000000000000 1402 + 2.575000000000001 0.1125000000000000 1403 + 2.575000000000001 0.1250000000000000 1404 + 2.575000000000001 0.1375000000000000 1405 + 2.575000000000001 0.1500000000000000 1406 + 2.575000000000001 0.1625000000000000 1407 + 2.575000000000001 0.1750000000000000 1408 + 2.575000000000001 0.1875000000000000 1409 + 2.575000000000000 0.2000000000000000 1410 + 2.575000000000000 0.2125000000000000 1411 + 2.575000000000000 0.2250000000000000 1412 + 2.575000000000000 0.2375000000000000 1413 + 2.575000000000000 0.2500000000000000 1414 + 2.575000000000000 0.2625000000000000 1415 + 2.575000000000000 0.2750000000000000 1416 + 2.575000000000001 0.2875000000000000 1417 + 2.575000000000001 0.3000000000000000 1418 + 2.575000000000001 0.3125000000000000 1419 + 2.575000000000001 0.3250000000000000 1420 + 2.575000000000001 0.3375000000000001 1421 + 2.575000000000000 0.3500000000000000 1422 + 2.575000000000000 0.3625000000000000 1423 + 2.575000000000000 0.3750000000000000 1424 + 2.575000000000000 0.3875000000000000 1425 + 2.575000000000000 0.4000000000000000 1426 + 2.575000000000000 0.4125000000000001 1427 + 2.575000000000000 0.4250000000000000 1428 + 2.575000000000000 0.4375000000000000 1429 + 2.575000000000000 0.4500000000000000 1430 + 2.575000000000000 0.4625000000000000 1431 + 2.575000000000000 0.4749999999999999 1432 + 2.575000000000000 0.4875000000000002 1433 + 2.575000000000000 0.5000000000000000 1434 + 2.562500000000000 0.000000000000000 1435 + 2.562499999999999 0.01250000000000000 1436 + 2.562500000000000 0.02500000000000000 1437 + 2.562500000000000 0.03749999999999999 1438 + 2.562500000000000 0.05000000000000000 1439 + 2.562500000000000 0.06250000000000000 1440 + 2.562500000000000 0.07499999999999998 1441 + 2.562500000000000 0.08749999999999998 1442 + 2.562500000000000 0.1000000000000000 1443 + 2.562500000000000 0.1125000000000000 1444 + 2.562500000000000 0.1250000000000000 1445 + 2.562500000000000 0.1375000000000000 1446 + 2.562500000000000 0.1500000000000000 1447 + 2.562499999999999 0.1625000000000000 1448 + 2.562500000000000 0.1750000000000000 1449 + 2.562500000000000 0.1875000000000000 1450 + 2.562500000000000 0.2000000000000000 1451 + 2.562500000000000 0.2125000000000000 1452 + 2.562500000000000 0.2250000000000000 1453 + 2.562500000000000 0.2375000000000000 1454 + 2.562500000000000 0.2500000000000000 1455 + 2.562500000000000 0.2625000000000000 1456 + 2.562500000000000 0.2750000000000000 1457 + 2.562500000000000 0.2875000000000001 1458 + 2.562500000000000 0.3000000000000000 1459 + 2.562500000000000 0.3125000000000000 1460 + 2.562500000000000 0.3250000000000001 1461 + 2.562500000000000 0.3375000000000000 1462 + 2.562500000000000 0.3500000000000000 1463 + 2.562500000000000 0.3625000000000000 1464 + 2.562500000000000 0.3750000000000000 1465 + 2.562500000000000 0.3875000000000001 1466 + 2.562500000000000 0.4000000000000000 1467 + 2.562500000000000 0.4125000000000000 1468 + 2.562500000000000 0.4250000000000000 1469 + 2.562500000000000 0.4375000000000001 1470 + 2.562500000000000 0.4500000000000001 1471 + 2.562500000000000 0.4625000000000000 1472 + 2.562500000000000 0.4750000000000000 1473 + 2.562500000000000 0.4875000000000001 1474 + 2.562500000000000 0.5000000000000000 1475 + 2.550000000000000 0.000000000000000 1476 + 2.550000000000000 0.01250000000000000 1477 + 2.550000000000000 0.02500000000000000 1478 + 2.550000000000001 0.03750000000000001 1479 + 2.550000000000000 0.05000000000000000 1480 + 2.550000000000000 0.06250000000000000 1481 + 2.550000000000000 0.07500000000000001 1482 + 2.550000000000000 0.08749999999999998 1483 + 2.550000000000001 0.1000000000000000 1484 + 2.550000000000000 0.1125000000000000 1485 + 2.550000000000000 0.1250000000000000 1486 + 2.550000000000000 0.1375000000000000 1487 + 2.550000000000000 0.1500000000000000 1488 + 2.550000000000000 0.1625000000000000 1489 + 2.550000000000000 0.1750000000000000 1490 + 2.550000000000000 0.1875000000000000 1491 + 2.550000000000000 0.2000000000000000 1492 + 2.550000000000000 0.2125000000000000 1493 + 2.550000000000000 0.2250000000000000 1494 + 2.550000000000000 0.2375000000000000 1495 + 2.550000000000000 0.2500000000000000 1496 + 2.550000000000000 0.2625000000000000 1497 + 2.550000000000000 0.2750000000000000 1498 + 2.550000000000000 0.2875000000000000 1499 + 2.550000000000000 0.3000000000000000 1500 + 2.550000000000000 0.3125000000000000 1501 + 2.550000000000000 0.3250000000000000 1502 + 2.550000000000000 0.3375000000000000 1503 + 2.549999999999999 0.3500000000000001 1504 + 2.549999999999999 0.3625000000000000 1505 + 2.549999999999999 0.3750000000000000 1506 + 2.549999999999999 0.3875000000000000 1507 + 2.549999999999999 0.4000000000000000 1508 + 2.550000000000000 0.4125000000000000 1509 + 2.550000000000000 0.4250000000000000 1510 + 2.550000000000000 0.4375000000000000 1511 + 2.550000000000000 0.4500000000000000 1512 + 2.550000000000000 0.4625000000000000 1513 + 2.550000000000000 0.4750000000000000 1514 + 2.550000000000000 0.4875000000000000 1515 + 2.550000000000000 0.5000000000000000 1516 + 2.537500000000001 0.000000000000000 1517 + 2.537500000000001 0.01250000000000000 1518 + 2.537500000000000 0.02500000000000000 1519 + 2.537500000000001 0.03750000000000001 1520 + 2.537500000000001 0.05000000000000000 1521 + 2.537500000000001 0.06250000000000000 1522 + 2.537500000000001 0.07500000000000001 1523 + 2.537500000000000 0.08750000000000001 1524 + 2.537500000000001 0.1000000000000000 1525 + 2.537500000000000 0.1125000000000000 1526 + 2.537500000000000 0.1250000000000000 1527 + 2.537500000000000 0.1375000000000000 1528 + 2.537500000000001 0.1500000000000000 1529 + 2.537500000000000 0.1625000000000000 1530 + 2.537500000000001 0.1750000000000000 1531 + 2.537500000000001 0.1875000000000000 1532 + 2.537500000000001 0.2000000000000000 1533 + 2.537500000000001 0.2125000000000000 1534 + 2.537500000000001 0.2250000000000000 1535 + 2.537500000000001 0.2375000000000000 1536 + 2.537500000000001 0.2500000000000000 1537 + 2.537500000000001 0.2625000000000000 1538 + 2.537500000000001 0.2750000000000000 1539 + 2.537500000000001 0.2875000000000000 1540 + 2.537500000000001 0.3000000000000000 1541 + 2.537500000000000 0.3125000000000000 1542 + 2.537500000000000 0.3250000000000001 1543 + 2.537500000000000 0.3374999999999999 1544 + 2.537500000000001 0.3500000000000000 1545 + 2.537500000000001 0.3625000000000000 1546 + 2.537500000000001 0.3750000000000000 1547 + 2.537500000000001 0.3875000000000001 1548 + 2.537500000000001 0.4000000000000000 1549 + 2.537500000000000 0.4125000000000000 1550 + 2.537500000000000 0.4250000000000000 1551 + 2.537500000000000 0.4375000000000000 1552 + 2.537500000000000 0.4500000000000000 1553 + 2.537500000000000 0.4625000000000000 1554 + 2.537500000000001 0.4750000000000001 1555 + 2.537500000000000 0.4875000000000000 1556 + 2.537500000000000 0.5000000000000000 1557 + 2.525000000000000 0.000000000000000 1558 + 2.525000000000001 0.01250000000000000 1559 + 2.525000000000000 0.02499999999999999 1560 + 2.525000000000001 0.03750000000000001 1561 + 2.525000000000001 0.05000000000000000 1562 + 2.525000000000001 0.06250000000000000 1563 + 2.525000000000001 0.07500000000000001 1564 + 2.525000000000000 0.08750000000000001 1565 + 2.525000000000001 0.1000000000000000 1566 + 2.525000000000001 0.1125000000000000 1567 + 2.525000000000001 0.1250000000000000 1568 + 2.525000000000001 0.1375000000000000 1569 + 2.525000000000000 0.1500000000000000 1570 + 2.525000000000001 0.1625000000000000 1571 + 2.524999999999999 0.1750000000000000 1572 + 2.525000000000000 0.1875000000000001 1573 + 2.525000000000000 0.2000000000000000 1574 + 2.525000000000000 0.2125000000000000 1575 + 2.525000000000001 0.2250000000000000 1576 + 2.525000000000000 0.2375000000000000 1577 + 2.525000000000000 0.2500000000000000 1578 + 2.524999999999999 0.2625000000000000 1579 + 2.524999999999999 0.2749999999999999 1580 + 2.524999999999999 0.2875000000000000 1581 + 2.524999999999999 0.3000000000000000 1582 + 2.524999999999999 0.3125000000000000 1583 + 2.524999999999999 0.3250000000000000 1584 + 2.524999999999999 0.3375000000000000 1585 + 2.524999999999999 0.3500000000000000 1586 + 2.524999999999999 0.3625000000000002 1587 + 2.524999999999999 0.3749999999999999 1588 + 2.524999999999999 0.3875000000000000 1589 + 2.524999999999999 0.4000000000000000 1590 + 2.524999999999999 0.4125000000000001 1591 + 2.525000000000000 0.4250000000000000 1592 + 2.525000000000000 0.4374999999999999 1593 + 2.525000000000000 0.4500000000000000 1594 + 2.525000000000000 0.4625000000000000 1595 + 2.525000000000000 0.4750000000000001 1596 + 2.525000000000000 0.4875000000000000 1597 + 2.525000000000000 0.5000000000000000 1598 + 2.512500000000000 0.000000000000000 1599 + 2.512500000000000 0.01250000000000000 1600 + 2.512499999999999 0.02500000000000000 1601 + 2.512500000000000 0.03750000000000001 1602 + 2.512500000000000 0.05000000000000000 1603 + 2.512500000000000 0.06250000000000000 1604 + 2.512500000000000 0.07500000000000001 1605 + 2.512500000000000 0.08750000000000001 1606 + 2.512500000000000 0.1000000000000000 1607 + 2.512500000000000 0.1125000000000000 1608 + 2.512500000000000 0.1250000000000000 1609 + 2.512500000000000 0.1375000000000000 1610 + 2.512500000000000 0.1500000000000000 1611 + 2.512500000000000 0.1625000000000000 1612 + 2.512500000000000 0.1750000000000000 1613 + 2.512500000000000 0.1875000000000000 1614 + 2.512500000000000 0.2000000000000001 1615 + 2.512500000000000 0.2125000000000000 1616 + 2.512500000000000 0.2250000000000000 1617 + 2.512500000000000 0.2375000000000000 1618 + 2.512500000000000 0.2500000000000000 1619 + 2.512500000000000 0.2625000000000000 1620 + 2.512500000000000 0.2750000000000000 1621 + 2.512499999999999 0.2875000000000000 1622 + 2.512499999999999 0.3000000000000000 1623 + 2.512499999999999 0.3125000000000001 1624 + 2.512499999999999 0.3250000000000000 1625 + 2.512499999999999 0.3375000000000000 1626 + 2.512499999999999 0.3500000000000000 1627 + 2.512500000000000 0.3625000000000000 1628 + 2.512500000000000 0.3750000000000001 1629 + 2.512500000000000 0.3875000000000000 1630 + 2.512500000000000 0.4000000000000000 1631 + 2.512500000000000 0.4125000000000000 1632 + 2.512500000000000 0.4250000000000000 1633 + 2.512500000000000 0.4375000000000000 1634 + 2.512500000000000 0.4500000000000000 1635 + 2.512500000000000 0.4625000000000000 1636 + 2.512500000000000 0.4750000000000000 1637 + 2.512500000000000 0.4874999999999999 1638 + 2.512500000000000 0.5000000000000000 1639 + 2.500000000000000 0.000000000000000 1640 + 2.500000000000000 0.01250000000000000 1641 + 2.500000000000000 0.02500000000000000 1642 + 2.500000000000000 0.03750000000000001 1643 + 2.500000000000000 0.05000000000000000 1644 + 2.500000000000000 0.06250000000000000 1645 + 2.500000000000000 0.07499999999999998 1646 + 2.500000000000000 0.08750000000000002 1647 + 2.500000000000000 0.1000000000000000 1648 + 2.500000000000000 0.1125000000000000 1649 + 2.500000000000000 0.1250000000000000 1650 + 2.500000000000000 0.1375000000000000 1651 + 2.500000000000000 0.1500000000000000 1652 + 2.500000000000000 0.1625000000000001 1653 + 2.500000000000000 0.1750000000000001 1654 + 2.500000000000000 0.1875000000000000 1655 + 2.500000000000000 0.2000000000000000 1656 + 2.500000000000000 0.2125000000000000 1657 + 2.500000000000000 0.2250000000000001 1658 + 2.500000000000000 0.2375000000000001 1659 + 2.500000000000000 0.2500000000000000 1660 + 2.500000000000000 0.2625000000000000 1661 + 2.500000000000000 0.2750000000000000 1662 + 2.500000000000000 0.2875000000000000 1663 + 2.500000000000000 0.3000000000000000 1664 + 2.500000000000000 0.3125000000000000 1665 + 2.500000000000000 0.3250000000000000 1666 + 2.500000000000000 0.3375000000000000 1667 + 2.500000000000000 0.3500000000000000 1668 + 2.500000000000000 0.3625000000000000 1669 + 2.500000000000000 0.3750000000000000 1670 + 2.500000000000000 0.3874999999999999 1671 + 2.500000000000000 0.4000000000000000 1672 + 2.500000000000000 0.4125000000000000 1673 + 2.500000000000000 0.4250000000000001 1674 + 2.500000000000000 0.4375000000000001 1675 + 2.500000000000000 0.4500000000000001 1676 + 2.500000000000000 0.4625000000000000 1677 + 2.500000000000000 0.4750000000000000 1678 + 2.500000000000000 0.4875000000000000 1679 + 2.500000000000000 0.5000000000000000 1680 + 2.487500000000000 0.000000000000000 1681 + 2.487500000000001 0.01250000000000000 1682 + 2.487500000000000 0.02500000000000000 1683 + 2.487500000000000 0.03750000000000002 1684 + 2.487500000000000 0.05000000000000000 1685 + 2.487500000000000 0.06250000000000000 1686 + 2.487500000000000 0.07500000000000001 1687 + 2.487500000000000 0.08749999999999999 1688 + 2.487500000000001 0.1000000000000000 1689 + 2.487500000000000 0.1125000000000000 1690 + 2.487500000000000 0.1250000000000000 1691 + 2.487500000000000 0.1375000000000000 1692 + 2.487500000000000 0.1500000000000000 1693 + 2.487500000000000 0.1625000000000000 1694 + 2.487500000000000 0.1750000000000001 1695 + 2.487500000000000 0.1875000000000000 1696 + 2.487500000000000 0.2000000000000000 1697 + 2.487500000000000 0.2125000000000000 1698 + 2.487500000000000 0.2250000000000000 1699 + 2.487500000000000 0.2375000000000000 1700 + 2.487500000000000 0.2500000000000000 1701 + 2.487500000000000 0.2625000000000000 1702 + 2.487500000000000 0.2750000000000000 1703 + 2.487500000000001 0.2875000000000000 1704 + 2.487500000000001 0.3000000000000000 1705 + 2.487500000000001 0.3124999999999999 1706 + 2.487500000000001 0.3250000000000000 1707 + 2.487500000000001 0.3375000000000000 1708 + 2.487500000000000 0.3499999999999999 1709 + 2.487500000000000 0.3624999999999999 1710 + 2.487500000000000 0.3750000000000000 1711 + 2.487500000000000 0.3875000000000000 1712 + 2.487500000000000 0.3999999999999999 1713 + 2.487500000000000 0.4125000000000000 1714 + 2.487500000000000 0.4250000000000000 1715 + 2.487500000000000 0.4375000000000000 1716 + 2.487500000000000 0.4499999999999999 1717 + 2.487500000000000 0.4625000000000000 1718 + 2.487500000000000 0.4750000000000001 1719 + 2.487500000000000 0.4875000000000002 1720 + 2.487500000000000 0.5000000000000000 1721 + 2.475000000000001 0.000000000000000 1722 + 2.475000000000001 0.01250000000000000 1723 + 2.475000000000000 0.02500000000000000 1724 + 2.475000000000001 0.03750000000000001 1725 + 2.475000000000001 0.05000000000000000 1726 + 2.475000000000001 0.06250000000000000 1727 + 2.475000000000001 0.07500000000000001 1728 + 2.475000000000001 0.08750000000000001 1729 + 2.475000000000001 0.1000000000000000 1730 + 2.475000000000001 0.1125000000000000 1731 + 2.475000000000001 0.1250000000000000 1732 + 2.475000000000000 0.1375000000000000 1733 + 2.475000000000001 0.1500000000000001 1734 + 2.475000000000001 0.1625000000000000 1735 + 2.475000000000000 0.1750000000000000 1736 + 2.475000000000001 0.1875000000000000 1737 + 2.475000000000000 0.2000000000000000 1738 + 2.475000000000001 0.2125000000000000 1739 + 2.475000000000001 0.2250000000000000 1740 + 2.475000000000001 0.2375000000000000 1741 + 2.475000000000001 0.2500000000000000 1742 + 2.475000000000001 0.2625000000000000 1743 + 2.475000000000001 0.2750000000000000 1744 + 2.475000000000001 0.2875000000000000 1745 + 2.475000000000001 0.2999999999999999 1746 + 2.475000000000000 0.3125000000000001 1747 + 2.475000000000000 0.3250000000000000 1748 + 2.474999999999999 0.3374999999999999 1749 + 2.475000000000000 0.3500000000000001 1750 + 2.475000000000000 0.3625000000000000 1751 + 2.474999999999999 0.3750000000000000 1752 + 2.474999999999999 0.3875000000000000 1753 + 2.474999999999999 0.4000000000000000 1754 + 2.474999999999999 0.4125000000000001 1755 + 2.474999999999999 0.4250000000000000 1756 + 2.474999999999999 0.4375000000000000 1757 + 2.474999999999999 0.4500000000000001 1758 + 2.474999999999999 0.4624999999999999 1759 + 2.474999999999999 0.4750000000000001 1760 + 2.474999999999999 0.4875000000000000 1761 + 2.475000000000000 0.5000000000000000 1762 + 2.462500000000000 0.000000000000000 1763 + 2.462499999999999 0.01250000000000000 1764 + 2.462500000000000 0.02500000000000000 1765 + 2.462499999999999 0.03750000000000001 1766 + 2.462499999999999 0.05000000000000000 1767 + 2.462500000000000 0.06250000000000000 1768 + 2.462500000000000 0.07500000000000002 1769 + 2.462500000000000 0.08750000000000001 1770 + 2.462499999999999 0.1000000000000000 1771 + 2.462500000000000 0.1125000000000000 1772 + 2.462500000000000 0.1250000000000000 1773 + 2.462500000000000 0.1375000000000000 1774 + 2.462500000000000 0.1500000000000000 1775 + 2.462499999999999 0.1625000000000000 1776 + 2.462500000000000 0.1750000000000000 1777 + 2.462500000000000 0.1875000000000000 1778 + 2.462500000000000 0.2000000000000000 1779 + 2.462500000000000 0.2125000000000000 1780 + 2.462500000000000 0.2250000000000000 1781 + 2.462499999999999 0.2375000000000000 1782 + 2.462499999999999 0.2500000000000000 1783 + 2.462499999999999 0.2625000000000000 1784 + 2.462499999999999 0.2750000000000000 1785 + 2.462500000000000 0.2875000000000000 1786 + 2.462500000000000 0.3000000000000000 1787 + 2.462500000000000 0.3125000000000000 1788 + 2.462499999999999 0.3250000000000000 1789 + 2.462499999999999 0.3375000000000000 1790 + 2.462499999999999 0.3500000000000000 1791 + 2.462499999999999 0.3625000000000000 1792 + 2.462499999999999 0.3750000000000000 1793 + 2.462499999999999 0.3875000000000000 1794 + 2.462499999999999 0.4000000000000000 1795 + 2.462499999999999 0.4125000000000000 1796 + 2.462499999999999 0.4250000000000000 1797 + 2.462499999999999 0.4375000000000000 1798 + 2.462499999999999 0.4500000000000000 1799 + 2.462499999999999 0.4625000000000000 1800 + 2.462499999999999 0.4750000000000000 1801 + 2.462499999999999 0.4875000000000000 1802 + 2.462500000000000 0.5000000000000000 1803 + 2.450000000000000 0.000000000000000 1804 + 2.450000000000000 0.01250000000000000 1805 + 2.450000000000000 0.02500000000000000 1806 + 2.450000000000000 0.03749999999999999 1807 + 2.450000000000000 0.05000000000000000 1808 + 2.450000000000000 0.06250000000000000 1809 + 2.450000000000000 0.07500000000000001 1810 + 2.450000000000001 0.08750000000000001 1811 + 2.450000000000000 0.1000000000000000 1812 + 2.450000000000000 0.1125000000000000 1813 + 2.450000000000000 0.1250000000000000 1814 + 2.450000000000000 0.1375000000000000 1815 + 2.450000000000000 0.1500000000000000 1816 + 2.450000000000000 0.1625000000000000 1817 + 2.450000000000000 0.1750000000000000 1818 + 2.450000000000001 0.1875000000000000 1819 + 2.450000000000001 0.2000000000000000 1820 + 2.450000000000001 0.2125000000000000 1821 + 2.450000000000001 0.2250000000000000 1822 + 2.450000000000000 0.2375000000000000 1823 + 2.450000000000000 0.2500000000000000 1824 + 2.450000000000000 0.2625000000000000 1825 + 2.450000000000000 0.2750000000000000 1826 + 2.450000000000000 0.2875000000000000 1827 + 2.449999999999999 0.3000000000000002 1828 + 2.449999999999999 0.3125000000000000 1829 + 2.450000000000000 0.3250000000000000 1830 + 2.450000000000000 0.3375000000000001 1831 + 2.450000000000000 0.3500000000000000 1832 + 2.450000000000000 0.3625000000000000 1833 + 2.450000000000000 0.3750000000000001 1834 + 2.450000000000000 0.3875000000000001 1835 + 2.450000000000000 0.4000000000000000 1836 + 2.450000000000000 0.4125000000000000 1837 + 2.450000000000000 0.4249999999999999 1838 + 2.450000000000000 0.4375000000000000 1839 + 2.450000000000000 0.4500000000000000 1840 + 2.450000000000000 0.4625000000000000 1841 + 2.450000000000000 0.4750000000000000 1842 + 2.450000000000000 0.4875000000000000 1843 + 2.450000000000000 0.5000000000000000 1844 + 2.437500000000000 0.000000000000000 1845 + 2.437500000000000 0.01250000000000000 1846 + 2.437500000000000 0.02500000000000001 1847 + 2.437500000000000 0.03750000000000001 1848 + 2.437500000000000 0.05000000000000000 1849 + 2.437500000000000 0.06250000000000000 1850 + 2.437500000000000 0.07500000000000001 1851 + 2.437500000000000 0.08750000000000001 1852 + 2.437500000000000 0.1000000000000000 1853 + 2.437500000000000 0.1125000000000000 1854 + 2.437500000000000 0.1250000000000000 1855 + 2.437500000000000 0.1375000000000000 1856 + 2.437500000000000 0.1500000000000000 1857 + 2.437500000000000 0.1625000000000000 1858 + 2.437500000000000 0.1750000000000000 1859 + 2.437500000000000 0.1875000000000000 1860 + 2.437500000000000 0.2000000000000000 1861 + 2.437500000000000 0.2125000000000000 1862 + 2.437500000000000 0.2250000000000000 1863 + 2.437500000000000 0.2375000000000000 1864 + 2.437500000000000 0.2500000000000000 1865 + 2.437500000000000 0.2625000000000000 1866 + 2.437500000000000 0.2749999999999999 1867 + 2.437500000000000 0.2875000000000000 1868 + 2.437500000000000 0.3000000000000000 1869 + 2.437500000000000 0.3124999999999999 1870 + 2.437500000000000 0.3250000000000000 1871 + 2.437500000000000 0.3375000000000000 1872 + 2.437500000000000 0.3500000000000000 1873 + 2.437500000000000 0.3625000000000002 1874 + 2.437500000000000 0.3750000000000000 1875 + 2.437500000000000 0.3875000000000000 1876 + 2.437500000000000 0.4000000000000000 1877 + 2.437500000000000 0.4125000000000000 1878 + 2.437500000000000 0.4249999999999999 1879 + 2.437500000000000 0.4375000000000000 1880 + 2.437500000000000 0.4500000000000000 1881 + 2.437500000000000 0.4625000000000000 1882 + 2.437500000000000 0.4750000000000000 1883 + 2.437500000000000 0.4875000000000000 1884 + 2.437500000000000 0.5000000000000000 1885 + 2.425000000000000 0.000000000000000 1886 + 2.425000000000000 0.01250000000000000 1887 + 2.425000000000000 0.02500000000000000 1888 + 2.425000000000001 0.03750000000000001 1889 + 2.425000000000001 0.05000000000000000 1890 + 2.425000000000001 0.06250000000000000 1891 + 2.425000000000001 0.07500000000000002 1892 + 2.425000000000001 0.08750000000000001 1893 + 2.425000000000001 0.1000000000000000 1894 + 2.425000000000001 0.1125000000000000 1895 + 2.425000000000000 0.1250000000000000 1896 + 2.425000000000001 0.1375000000000000 1897 + 2.425000000000000 0.1500000000000000 1898 + 2.425000000000001 0.1625000000000000 1899 + 2.425000000000000 0.1750000000000000 1900 + 2.425000000000001 0.1875000000000000 1901 + 2.425000000000000 0.2000000000000000 1902 + 2.425000000000001 0.2125000000000000 1903 + 2.425000000000001 0.2250000000000000 1904 + 2.425000000000000 0.2375000000000000 1905 + 2.425000000000000 0.2500000000000000 1906 + 2.425000000000000 0.2625000000000000 1907 + 2.425000000000000 0.2750000000000000 1908 + 2.425000000000000 0.2875000000000000 1909 + 2.424999999999999 0.3000000000000000 1910 + 2.424999999999999 0.3125000000000000 1911 + 2.424999999999999 0.3250000000000001 1912 + 2.424999999999999 0.3375000000000000 1913 + 2.425000000000000 0.3500000000000001 1914 + 2.425000000000000 0.3625000000000000 1915 + 2.425000000000000 0.3749999999999999 1916 + 2.425000000000000 0.3875000000000000 1917 + 2.424999999999999 0.3999999999999999 1918 + 2.424999999999999 0.4125000000000001 1919 + 2.425000000000000 0.4250000000000000 1920 + 2.424999999999999 0.4374999999999999 1921 + 2.425000000000000 0.4500000000000000 1922 + 2.424999999999999 0.4625000000000000 1923 + 2.424999999999999 0.4750000000000001 1924 + 2.424999999999999 0.4875000000000000 1925 + 2.425000000000000 0.5000000000000000 1926 + 2.412500000000001 0.000000000000000 1927 + 2.412500000000001 0.01250000000000000 1928 + 2.412500000000001 0.02500000000000000 1929 + 2.412500000000001 0.03750000000000001 1930 + 2.412500000000001 0.05000000000000000 1931 + 2.412500000000001 0.06250000000000000 1932 + 2.412500000000001 0.07500000000000001 1933 + 2.412500000000001 0.08750000000000001 1934 + 2.412500000000000 0.1000000000000000 1935 + 2.412500000000001 0.1125000000000000 1936 + 2.412500000000001 0.1250000000000000 1937 + 2.412500000000001 0.1375000000000000 1938 + 2.412499999999999 0.1500000000000000 1939 + 2.412500000000001 0.1625000000000001 1940 + 2.412499999999999 0.1750000000000000 1941 + 2.412500000000000 0.1875000000000000 1942 + 2.412499999999999 0.2000000000000000 1943 + 2.412499999999999 0.2125000000000000 1944 + 2.412500000000000 0.2250000000000000 1945 + 2.412499999999999 0.2375000000000000 1946 + 2.412499999999999 0.2500000000000000 1947 + 2.412499999999999 0.2625000000000000 1948 + 2.412500000000000 0.2750000000000000 1949 + 2.412500000000000 0.2875000000000000 1950 + 2.412500000000000 0.3000000000000000 1951 + 2.412500000000000 0.3125000000000000 1952 + 2.412500000000000 0.3249999999999999 1953 + 2.412500000000000 0.3375000000000000 1954 + 2.412500000000001 0.3500000000000000 1955 + 2.412500000000000 0.3625000000000000 1956 + 2.412500000000000 0.3750000000000000 1957 + 2.412500000000000 0.3875000000000001 1958 + 2.412500000000000 0.4000000000000000 1959 + 2.412500000000000 0.4125000000000000 1960 + 2.412500000000000 0.4250000000000000 1961 + 2.412500000000000 0.4374999999999999 1962 + 2.412500000000000 0.4500000000000000 1963 + 2.412499999999999 0.4625000000000001 1964 + 2.412499999999999 0.4749999999999999 1965 + 2.412499999999999 0.4875000000000000 1966 + 2.412500000000000 0.5000000000000000 1967 + 2.400000000000000 0.000000000000000 1968 + 2.400000000000000 0.01250000000000000 1969 + 2.399999999999999 0.02500000000000000 1970 + 2.400000000000001 0.03750000000000001 1971 + 2.400000000000000 0.05000000000000000 1972 + 2.399999999999999 0.06250000000000000 1973 + 2.399999999999999 0.07500000000000001 1974 + 2.400000000000000 0.08750000000000002 1975 + 2.399999999999999 0.09999999999999998 1976 + 2.399999999999999 0.1125000000000000 1977 + 2.399999999999999 0.1250000000000000 1978 + 2.399999999999999 0.1375000000000000 1979 + 2.399999999999999 0.1500000000000000 1980 + 2.400000000000000 0.1625000000000000 1981 + 2.399999999999999 0.1750000000000000 1982 + 2.400000000000000 0.1875000000000000 1983 + 2.400000000000000 0.2000000000000000 1984 + 2.400000000000000 0.2125000000000000 1985 + 2.400000000000000 0.2250000000000000 1986 + 2.400000000000000 0.2375000000000000 1987 + 2.400000000000000 0.2500000000000000 1988 + 2.400000000000000 0.2625000000000000 1989 + 2.400000000000000 0.2750000000000000 1990 + 2.400000000000000 0.2875000000000000 1991 + 2.400000000000000 0.3000000000000000 1992 + 2.400000000000000 0.3125000000000000 1993 + 2.400000000000000 0.3250000000000000 1994 + 2.400000000000000 0.3375000000000001 1995 + 2.400000000000000 0.3500000000000000 1996 + 2.400000000000000 0.3625000000000000 1997 + 2.400000000000000 0.3750000000000000 1998 + 2.399999999999999 0.3875000000000001 1999 + 2.399999999999999 0.4000000000000000 2000 + 2.399999999999999 0.4124999999999999 2001 + 2.399999999999999 0.4250000000000000 2002 + 2.399999999999999 0.4375000000000000 2003 + 2.399999999999999 0.4500000000000000 2004 + 2.399999999999999 0.4625000000000000 2005 + 2.399999999999999 0.4750000000000000 2006 + 2.399999999999999 0.4875000000000000 2007 + 2.400000000000000 0.5000000000000000 2008 + 2.387500000000000 0.000000000000000 2009 + 2.387500000000000 0.01250000000000000 2010 + 2.387500000000000 0.02500000000000000 2011 + 2.387500000000001 0.03750000000000001 2012 + 2.387500000000000 0.05000000000000000 2013 + 2.387500000000000 0.06250000000000000 2014 + 2.387500000000000 0.07500000000000001 2015 + 2.387500000000000 0.08750000000000001 2016 + 2.387500000000000 0.1000000000000000 2017 + 2.387500000000000 0.1125000000000000 2018 + 2.387500000000000 0.1250000000000000 2019 + 2.387500000000000 0.1375000000000000 2020 + 2.387500000000000 0.1500000000000000 2021 + 2.387500000000000 0.1625000000000000 2022 + 2.387500000000000 0.1750000000000000 2023 + 2.387500000000000 0.1875000000000000 2024 + 2.387500000000000 0.2000000000000000 2025 + 2.387500000000000 0.2125000000000000 2026 + 2.387500000000000 0.2250000000000000 2027 + 2.387500000000000 0.2375000000000000 2028 + 2.387500000000001 0.2500000000000000 2029 + 2.387500000000001 0.2625000000000000 2030 + 2.387500000000001 0.2750000000000000 2031 + 2.387500000000001 0.2875000000000000 2032 + 2.387500000000001 0.3000000000000002 2033 + 2.387500000000000 0.3124999999999999 2034 + 2.387500000000001 0.3249999999999999 2035 + 2.387500000000001 0.3375000000000000 2036 + 2.387500000000000 0.3500000000000000 2037 + 2.387500000000000 0.3625000000000000 2038 + 2.387500000000001 0.3750000000000000 2039 + 2.387500000000000 0.3875000000000000 2040 + 2.387500000000000 0.4000000000000000 2041 + 2.387500000000000 0.4125000000000000 2042 + 2.387500000000000 0.4250000000000000 2043 + 2.387500000000000 0.4374999999999999 2044 + 2.387500000000000 0.4500000000000000 2045 + 2.387500000000000 0.4625000000000000 2046 + 2.387500000000000 0.4750000000000001 2047 + 2.387500000000000 0.4875000000000000 2048 + 2.387500000000000 0.5000000000000000 2049 + 2.375000000000000 0.000000000000000 2050 + 2.375000000000000 0.01250000000000000 2051 + 2.375000000000000 0.02500000000000000 2052 + 2.375000000000000 0.03750000000000001 2053 + 2.375000000000000 0.05000000000000000 2054 + 2.375000000000000 0.06250000000000000 2055 + 2.375000000000000 0.07500000000000001 2056 + 2.375000000000001 0.08750000000000001 2057 + 2.375000000000000 0.1000000000000000 2058 + 2.375000000000000 0.1125000000000000 2059 + 2.375000000000000 0.1250000000000000 2060 + 2.375000000000000 0.1375000000000000 2061 + 2.375000000000000 0.1500000000000000 2062 + 2.375000000000000 0.1625000000000000 2063 + 2.375000000000000 0.1750000000000000 2064 + 2.375000000000000 0.1875000000000000 2065 + 2.375000000000001 0.2000000000000000 2066 + 2.375000000000001 0.2125000000000000 2067 + 2.375000000000001 0.2250000000000001 2068 + 2.375000000000001 0.2375000000000000 2069 + 2.375000000000000 0.2500000000000000 2070 + 2.375000000000000 0.2625000000000000 2071 + 2.375000000000000 0.2750000000000000 2072 + 2.375000000000000 0.2875000000000001 2073 + 2.375000000000000 0.3000000000000000 2074 + 2.375000000000000 0.3125000000000001 2075 + 2.375000000000000 0.3250000000000000 2076 + 2.375000000000000 0.3375000000000000 2077 + 2.374999999999999 0.3499999999999999 2078 + 2.374999999999999 0.3625000000000000 2079 + 2.374999999999999 0.3749999999999999 2080 + 2.374999999999999 0.3875000000000000 2081 + 2.375000000000000 0.4000000000000001 2082 + 2.375000000000000 0.4125000000000001 2083 + 2.375000000000000 0.4250000000000000 2084 + 2.375000000000000 0.4375000000000000 2085 + 2.375000000000000 0.4500000000000000 2086 + 2.375000000000000 0.4625000000000000 2087 + 2.375000000000000 0.4750000000000000 2088 + 2.375000000000000 0.4875000000000002 2089 + 2.375000000000000 0.5000000000000000 2090 + 2.362500000000000 0.000000000000000 2091 + 2.362500000000000 0.01250000000000000 2092 + 2.362500000000001 0.02500000000000000 2093 + 2.362500000000001 0.03750000000000001 2094 + 2.362499999999999 0.05000000000000000 2095 + 2.362499999999999 0.06250000000000000 2096 + 2.362499999999999 0.07500000000000004 2097 + 2.362500000000000 0.08750000000000001 2098 + 2.362499999999999 0.1000000000000000 2099 + 2.362500000000000 0.1125000000000000 2100 + 2.362500000000000 0.1250000000000000 2101 + 2.362499999999999 0.1375000000000000 2102 + 2.362500000000000 0.1500000000000000 2103 + 2.362500000000000 0.1625000000000000 2104 + 2.362499999999999 0.1750000000000001 2105 + 2.362500000000000 0.1875000000000000 2106 + 2.362500000000000 0.2000000000000000 2107 + 2.362499999999999 0.2125000000000001 2108 + 2.362499999999999 0.2250000000000000 2109 + 2.362499999999999 0.2375000000000000 2110 + 2.362499999999999 0.2500000000000000 2111 + 2.362499999999999 0.2625000000000000 2112 + 2.362499999999999 0.2750000000000000 2113 + 2.362499999999999 0.2874999999999999 2114 + 2.362500000000000 0.3000000000000000 2115 + 2.362499999999999 0.3125000000000000 2116 + 2.362499999999999 0.3250000000000000 2117 + 2.362500000000000 0.3374999999999999 2118 + 2.362500000000000 0.3499999999999999 2119 + 2.362500000000000 0.3625000000000000 2120 + 2.362500000000000 0.3750000000000000 2121 + 2.362500000000000 0.3875000000000000 2122 + 2.362500000000000 0.4000000000000000 2123 + 2.362500000000000 0.4125000000000001 2124 + 2.362500000000000 0.4250000000000000 2125 + 2.362500000000000 0.4375000000000000 2126 + 2.362500000000000 0.4499999999999999 2127 + 2.362500000000000 0.4625000000000000 2128 + 2.362500000000000 0.4750000000000000 2129 + 2.362500000000000 0.4875000000000000 2130 + 2.362500000000000 0.5000000000000000 2131 + 2.350000000000001 0.000000000000000 2132 + 2.350000000000000 0.01250000000000000 2133 + 2.350000000000000 0.02500000000000000 2134 + 2.350000000000001 0.03750000000000001 2135 + 2.350000000000000 0.05000000000000000 2136 + 2.350000000000000 0.06250000000000000 2137 + 2.350000000000000 0.07500000000000001 2138 + 2.350000000000001 0.08750000000000001 2139 + 2.350000000000001 0.1000000000000000 2140 + 2.350000000000000 0.1125000000000000 2141 + 2.350000000000000 0.1250000000000000 2142 + 2.350000000000001 0.1375000000000000 2143 + 2.350000000000001 0.1500000000000000 2144 + 2.350000000000000 0.1625000000000000 2145 + 2.350000000000001 0.1750000000000000 2146 + 2.350000000000001 0.1875000000000000 2147 + 2.350000000000001 0.2000000000000000 2148 + 2.350000000000001 0.2125000000000000 2149 + 2.350000000000001 0.2250000000000000 2150 + 2.350000000000001 0.2375000000000000 2151 + 2.350000000000001 0.2500000000000000 2152 + 2.350000000000001 0.2625000000000000 2153 + 2.350000000000001 0.2750000000000000 2154 + 2.350000000000001 0.2875000000000000 2155 + 2.350000000000001 0.3000000000000000 2156 + 2.350000000000000 0.3125000000000000 2157 + 2.350000000000000 0.3250000000000001 2158 + 2.350000000000000 0.3375000000000001 2159 + 2.350000000000000 0.3499999999999999 2160 + 2.350000000000001 0.3625000000000000 2161 + 2.350000000000000 0.3750000000000000 2162 + 2.350000000000000 0.3875000000000000 2163 + 2.350000000000000 0.4000000000000000 2164 + 2.350000000000000 0.4125000000000000 2165 + 2.350000000000001 0.4250000000000000 2166 + 2.350000000000001 0.4375000000000000 2167 + 2.350000000000001 0.4500000000000001 2168 + 2.350000000000001 0.4625000000000000 2169 + 2.350000000000001 0.4750000000000001 2170 + 2.350000000000001 0.4875000000000000 2171 + 2.350000000000000 0.5000000000000000 2172 + 2.337500000000000 0.000000000000000 2173 + 2.337500000000000 0.01250000000000000 2174 + 2.337499999999999 0.02500000000000000 2175 + 2.337500000000000 0.03750000000000001 2176 + 2.337500000000000 0.05000000000000000 2177 + 2.337500000000000 0.06250000000000000 2178 + 2.337500000000000 0.07500000000000001 2179 + 2.337499999999999 0.08750000000000002 2180 + 2.337500000000001 0.1000000000000000 2181 + 2.337499999999999 0.1125000000000000 2182 + 2.337499999999999 0.1250000000000000 2183 + 2.337499999999999 0.1375000000000000 2184 + 2.337499999999999 0.1500000000000000 2185 + 2.337500000000000 0.1625000000000000 2186 + 2.337499999999999 0.1750000000000000 2187 + 2.337499999999999 0.1875000000000000 2188 + 2.337499999999999 0.2000000000000000 2189 + 2.337499999999999 0.2125000000000000 2190 + 2.337499999999999 0.2250000000000000 2191 + 2.337500000000000 0.2375000000000000 2192 + 2.337500000000000 0.2500000000000000 2193 + 2.337500000000000 0.2625000000000000 2194 + 2.337500000000000 0.2750000000000000 2195 + 2.337500000000000 0.2874999999999999 2196 + 2.337500000000000 0.3000000000000000 2197 + 2.337500000000000 0.3124999999999999 2198 + 2.337500000000001 0.3250000000000000 2199 + 2.337500000000001 0.3375000000000000 2200 + 2.337500000000001 0.3500000000000000 2201 + 2.337500000000001 0.3625000000000000 2202 + 2.337500000000001 0.3750000000000000 2203 + 2.337500000000001 0.3874999999999999 2204 + 2.337500000000001 0.4000000000000000 2205 + 2.337500000000001 0.4125000000000001 2206 + 2.337500000000001 0.4250000000000000 2207 + 2.337500000000001 0.4375000000000001 2208 + 2.337500000000001 0.4500000000000000 2209 + 2.337500000000000 0.4625000000000000 2210 + 2.337500000000000 0.4750000000000000 2211 + 2.337500000000000 0.4875000000000000 2212 + 2.337500000000000 0.5000000000000000 2213 + 2.325000000000000 0.000000000000000 2214 + 2.325000000000001 0.01250000000000000 2215 + 2.325000000000000 0.02500000000000000 2216 + 2.325000000000000 0.03750000000000001 2217 + 2.325000000000001 0.05000000000000000 2218 + 2.325000000000001 0.06250000000000000 2219 + 2.325000000000001 0.07500000000000001 2220 + 2.325000000000001 0.08750000000000004 2221 + 2.325000000000001 0.1000000000000000 2222 + 2.325000000000001 0.1125000000000000 2223 + 2.325000000000001 0.1250000000000000 2224 + 2.325000000000001 0.1375000000000000 2225 + 2.325000000000001 0.1500000000000000 2226 + 2.325000000000001 0.1625000000000000 2227 + 2.325000000000001 0.1750000000000000 2228 + 2.325000000000001 0.1875000000000000 2229 + 2.325000000000001 0.2000000000000000 2230 + 2.325000000000001 0.2125000000000001 2231 + 2.325000000000001 0.2250000000000000 2232 + 2.325000000000000 0.2375000000000000 2233 + 2.325000000000000 0.2500000000000000 2234 + 2.325000000000000 0.2625000000000000 2235 + 2.325000000000000 0.2750000000000000 2236 + 2.325000000000001 0.2875000000000000 2237 + 2.325000000000001 0.3000000000000000 2238 + 2.325000000000001 0.3124999999999999 2239 + 2.325000000000000 0.3250000000000000 2240 + 2.325000000000000 0.3375000000000000 2241 + 2.325000000000000 0.3500000000000000 2242 + 2.325000000000000 0.3625000000000000 2243 + 2.325000000000000 0.3749999999999999 2244 + 2.325000000000000 0.3874999999999999 2245 + 2.325000000000000 0.4000000000000000 2246 + 2.325000000000000 0.4125000000000000 2247 + 2.325000000000000 0.4250000000000001 2248 + 2.325000000000000 0.4374999999999999 2249 + 2.325000000000000 0.4499999999999999 2250 + 2.325000000000000 0.4625000000000000 2251 + 2.325000000000000 0.4750000000000000 2252 + 2.325000000000000 0.4875000000000000 2253 + 2.325000000000000 0.5000000000000000 2254 + 2.312500000000000 0.000000000000000 2255 + 2.312500000000000 0.01250000000000000 2256 + 2.312500000000000 0.02500000000000000 2257 + 2.312500000000001 0.03750000000000001 2258 + 2.312500000000000 0.05000000000000000 2259 + 2.312500000000000 0.06250000000000000 2260 + 2.312499999999999 0.07500000000000001 2261 + 2.312500000000000 0.08750000000000001 2262 + 2.312500000000000 0.1000000000000000 2263 + 2.312499999999999 0.1125000000000000 2264 + 2.312500000000000 0.1250000000000000 2265 + 2.312500000000000 0.1375000000000000 2266 + 2.312500000000000 0.1500000000000000 2267 + 2.312499999999999 0.1625000000000000 2268 + 2.312500000000000 0.1750000000000000 2269 + 2.312500000000000 0.1875000000000000 2270 + 2.312500000000000 0.2000000000000000 2271 + 2.312500000000000 0.2125000000000000 2272 + 2.312500000000000 0.2250000000000000 2273 + 2.312500000000000 0.2375000000000000 2274 + 2.312500000000000 0.2500000000000000 2275 + 2.312500000000000 0.2625000000000000 2276 + 2.312500000000000 0.2750000000000000 2277 + 2.312500000000000 0.2875000000000000 2278 + 2.312500000000000 0.3000000000000000 2279 + 2.312500000000000 0.3125000000000000 2280 + 2.312500000000000 0.3250000000000001 2281 + 2.312500000000000 0.3375000000000000 2282 + 2.312500000000000 0.3500000000000000 2283 + 2.312500000000000 0.3625000000000000 2284 + 2.312500000000000 0.3750000000000000 2285 + 2.312500000000000 0.3875000000000000 2286 + 2.312500000000000 0.4000000000000001 2287 + 2.312500000000000 0.4124999999999999 2288 + 2.312500000000000 0.4250000000000000 2289 + 2.312500000000000 0.4375000000000000 2290 + 2.312500000000000 0.4500000000000000 2291 + 2.312500000000000 0.4625000000000000 2292 + 2.312500000000000 0.4750000000000000 2293 + 2.312500000000000 0.4875000000000001 2294 + 2.312500000000000 0.5000000000000000 2295 + 2.300000000000000 0.000000000000000 2296 + 2.300000000000000 0.01250000000000000 2297 + 2.300000000000000 0.02500000000000000 2298 + 2.300000000000000 0.03750000000000001 2299 + 2.300000000000000 0.05000000000000000 2300 + 2.300000000000000 0.06250000000000000 2301 + 2.300000000000000 0.07500000000000001 2302 + 2.300000000000000 0.08750000000000001 2303 + 2.300000000000001 0.09999999999999999 2304 + 2.300000000000000 0.1125000000000000 2305 + 2.300000000000000 0.1250000000000000 2306 + 2.300000000000000 0.1375000000000000 2307 + 2.300000000000000 0.1500000000000000 2308 + 2.300000000000000 0.1625000000000001 2309 + 2.300000000000000 0.1750000000000000 2310 + 2.300000000000000 0.1875000000000000 2311 + 2.300000000000000 0.2000000000000000 2312 + 2.300000000000000 0.2125000000000000 2313 + 2.300000000000001 0.2250000000000001 2314 + 2.300000000000000 0.2375000000000000 2315 + 2.300000000000000 0.2500000000000000 2316 + 2.300000000000000 0.2625000000000000 2317 + 2.300000000000000 0.2750000000000000 2318 + 2.300000000000000 0.2875000000000000 2319 + 2.300000000000001 0.3000000000000000 2320 + 2.300000000000001 0.3125000000000000 2321 + 2.300000000000001 0.3249999999999999 2322 + 2.300000000000001 0.3375000000000000 2323 + 2.300000000000001 0.3500000000000000 2324 + 2.300000000000001 0.3625000000000000 2325 + 2.300000000000001 0.3750000000000000 2326 + 2.300000000000000 0.3875000000000001 2327 + 2.300000000000000 0.4000000000000000 2328 + 2.300000000000000 0.4125000000000001 2329 + 2.300000000000000 0.4250000000000000 2330 + 2.300000000000000 0.4375000000000001 2331 + 2.300000000000000 0.4500000000000001 2332 + 2.300000000000000 0.4625000000000000 2333 + 2.300000000000000 0.4750000000000000 2334 + 2.300000000000000 0.4875000000000002 2335 + 2.300000000000000 0.5000000000000000 2336 + 2.287500000000000 0.000000000000000 2337 + 2.287500000000000 0.01250000000000000 2338 + 2.287500000000000 0.02500000000000000 2339 + 2.287500000000000 0.03750000000000001 2340 + 2.287500000000001 0.05000000000000000 2341 + 2.287500000000000 0.06250000000000000 2342 + 2.287500000000000 0.07500000000000001 2343 + 2.287500000000000 0.08749999999999999 2344 + 2.287500000000000 0.1000000000000000 2345 + 2.287500000000000 0.1125000000000000 2346 + 2.287500000000000 0.1250000000000000 2347 + 2.287500000000001 0.1375000000000000 2348 + 2.287500000000001 0.1500000000000000 2349 + 2.287500000000000 0.1625000000000000 2350 + 2.287500000000001 0.1750000000000000 2351 + 2.287500000000001 0.1875000000000000 2352 + 2.287500000000001 0.2000000000000000 2353 + 2.287500000000001 0.2125000000000000 2354 + 2.287500000000001 0.2250000000000000 2355 + 2.287500000000000 0.2375000000000001 2356 + 2.287500000000001 0.2500000000000000 2357 + 2.287500000000001 0.2625000000000000 2358 + 2.287500000000000 0.2750000000000000 2359 + 2.287500000000000 0.2875000000000000 2360 + 2.287500000000001 0.3000000000000000 2361 + 2.287500000000001 0.3125000000000000 2362 + 2.287500000000001 0.3250000000000000 2363 + 2.287500000000001 0.3375000000000000 2364 + 2.287500000000000 0.3500000000000001 2365 + 2.287500000000000 0.3625000000000000 2366 + 2.287500000000000 0.3750000000000000 2367 + 2.287500000000000 0.3875000000000000 2368 + 2.287500000000000 0.4000000000000000 2369 + 2.287500000000000 0.4125000000000000 2370 + 2.287500000000000 0.4250000000000000 2371 + 2.287500000000000 0.4375000000000000 2372 + 2.287500000000000 0.4500000000000000 2373 + 2.287500000000000 0.4625000000000000 2374 + 2.287500000000000 0.4750000000000000 2375 + 2.287500000000001 0.4875000000000000 2376 + 2.287500000000000 0.5000000000000000 2377 + 2.275000000000000 0.000000000000000 2378 + 2.275000000000000 0.01250000000000000 2379 + 2.275000000000000 0.02500000000000000 2380 + 2.275000000000000 0.03750000000000001 2381 + 2.275000000000000 0.05000000000000000 2382 + 2.275000000000000 0.06250000000000000 2383 + 2.275000000000001 0.07500000000000001 2384 + 2.275000000000000 0.08750000000000001 2385 + 2.275000000000000 0.1000000000000000 2386 + 2.275000000000001 0.1125000000000000 2387 + 2.275000000000001 0.1250000000000000 2388 + 2.275000000000001 0.1375000000000000 2389 + 2.275000000000001 0.1500000000000000 2390 + 2.275000000000001 0.1625000000000001 2391 + 2.275000000000001 0.1750000000000000 2392 + 2.275000000000001 0.1875000000000000 2393 + 2.275000000000000 0.2000000000000000 2394 + 2.275000000000000 0.2125000000000000 2395 + 2.275000000000000 0.2250000000000000 2396 + 2.274999999999999 0.2375000000000000 2397 + 2.275000000000000 0.2500000000000000 2398 + 2.275000000000000 0.2625000000000000 2399 + 2.275000000000000 0.2750000000000000 2400 + 2.275000000000000 0.2875000000000000 2401 + 2.274999999999999 0.3000000000000000 2402 + 2.274999999999999 0.3125000000000001 2403 + 2.274999999999999 0.3249999999999999 2404 + 2.274999999999999 0.3375000000000000 2405 + 2.274999999999999 0.3500000000000000 2406 + 2.274999999999999 0.3625000000000000 2407 + 2.275000000000000 0.3750000000000001 2408 + 2.275000000000000 0.3875000000000000 2409 + 2.275000000000000 0.4000000000000000 2410 + 2.275000000000000 0.4125000000000000 2411 + 2.275000000000000 0.4250000000000001 2412 + 2.275000000000000 0.4375000000000001 2413 + 2.275000000000000 0.4499999999999999 2414 + 2.275000000000000 0.4625000000000000 2415 + 2.275000000000000 0.4750000000000000 2416 + 2.275000000000000 0.4875000000000000 2417 + 2.275000000000000 0.5000000000000000 2418 + 2.262500000000000 0.000000000000000 2419 + 2.262500000000000 0.01250000000000000 2420 + 2.262500000000001 0.02500000000000000 2421 + 2.262500000000002 0.03750000000000001 2422 + 2.262500000000001 0.05000000000000000 2423 + 2.262500000000001 0.06250000000000000 2424 + 2.262500000000000 0.07500000000000001 2425 + 2.262500000000000 0.08749999999999998 2426 + 2.262499999999999 0.1000000000000000 2427 + 2.262500000000000 0.1125000000000000 2428 + 2.262500000000000 0.1250000000000000 2429 + 2.262500000000000 0.1375000000000000 2430 + 2.262500000000000 0.1500000000000000 2431 + 2.262500000000000 0.1625000000000000 2432 + 2.262500000000000 0.1750000000000000 2433 + 2.262500000000000 0.1875000000000000 2434 + 2.262500000000000 0.2000000000000000 2435 + 2.262500000000000 0.2125000000000000 2436 + 2.262500000000000 0.2250000000000000 2437 + 2.262500000000000 0.2375000000000000 2438 + 2.262500000000000 0.2499999999999999 2439 + 2.262500000000000 0.2625000000000000 2440 + 2.262500000000000 0.2750000000000000 2441 + 2.262500000000000 0.2875000000000000 2442 + 2.262499999999999 0.3000000000000000 2443 + 2.262499999999999 0.3125000000000000 2444 + 2.262499999999999 0.3250000000000000 2445 + 2.262500000000000 0.3375000000000000 2446 + 2.262500000000000 0.3500000000000000 2447 + 2.262500000000000 0.3625000000000000 2448 + 2.262500000000000 0.3750000000000000 2449 + 2.262500000000000 0.3875000000000001 2450 + 2.262500000000000 0.4000000000000000 2451 + 2.262500000000000 0.4125000000000000 2452 + 2.262500000000000 0.4250000000000001 2453 + 2.262500000000000 0.4375000000000000 2454 + 2.262500000000000 0.4500000000000001 2455 + 2.262500000000000 0.4625000000000000 2456 + 2.262500000000000 0.4749999999999999 2457 + 2.262500000000000 0.4875000000000001 2458 + 2.262500000000000 0.5000000000000000 2459 + 2.250000000000000 0.000000000000000 2460 + 2.250000000000000 0.01250000000000000 2461 + 2.249999999999999 0.02500000000000000 2462 + 2.250000000000000 0.03750000000000001 2463 + 2.250000000000000 0.05000000000000000 2464 + 2.250000000000000 0.06250000000000000 2465 + 2.250000000000000 0.07500000000000001 2466 + 2.250000000000000 0.08749999999999999 2467 + 2.250000000000000 0.1000000000000000 2468 + 2.250000000000000 0.1125000000000000 2469 + 2.250000000000000 0.1250000000000000 2470 + 2.250000000000000 0.1375000000000000 2471 + 2.250000000000000 0.1500000000000000 2472 + 2.250000000000000 0.1625000000000000 2473 + 2.250000000000000 0.1750000000000000 2474 + 2.250000000000000 0.1875000000000000 2475 + 2.250000000000000 0.2000000000000000 2476 + 2.250000000000000 0.2125000000000000 2477 + 2.250000000000000 0.2250000000000001 2478 + 2.250000000000000 0.2375000000000001 2479 + 2.250000000000000 0.2500000000000000 2480 + 2.250000000000000 0.2625000000000000 2481 + 2.250000000000000 0.2750000000000000 2482 + 2.250000000000000 0.2875000000000000 2483 + 2.250000000000000 0.3000000000000000 2484 + 2.250000000000000 0.3125000000000000 2485 + 2.250000000000000 0.3250000000000000 2486 + 2.250000000000000 0.3374999999999999 2487 + 2.250000000000000 0.3499999999999999 2488 + 2.250000000000000 0.3625000000000000 2489 + 2.250000000000000 0.3750000000000001 2490 + 2.250000000000000 0.3875000000000001 2491 + 2.250000000000000 0.4000000000000000 2492 + 2.250000000000000 0.4125000000000000 2493 + 2.250000000000000 0.4250000000000000 2494 + 2.250000000000000 0.4375000000000000 2495 + 2.250000000000000 0.4500000000000001 2496 + 2.250000000000000 0.4625000000000000 2497 + 2.250000000000000 0.4750000000000001 2498 + 2.250000000000000 0.4875000000000002 2499 + 2.250000000000000 0.5000000000000000 2500 + 2.237500000000000 0.000000000000000 2501 + 2.237500000000000 0.01250000000000000 2502 + 2.237500000000001 0.02500000000000000 2503 + 2.237500000000000 0.03750000000000001 2504 + 2.237500000000000 0.05000000000000000 2505 + 2.237500000000000 0.06250000000000000 2506 + 2.237500000000001 0.07500000000000001 2507 + 2.237500000000000 0.08750000000000002 2508 + 2.237500000000000 0.1000000000000000 2509 + 2.237500000000001 0.1125000000000000 2510 + 2.237500000000001 0.1250000000000000 2511 + 2.237500000000001 0.1375000000000000 2512 + 2.237500000000000 0.1500000000000000 2513 + 2.237500000000001 0.1625000000000000 2514 + 2.237500000000000 0.1750000000000000 2515 + 2.237500000000000 0.1875000000000000 2516 + 2.237500000000000 0.2000000000000000 2517 + 2.237500000000000 0.2125000000000000 2518 + 2.237500000000001 0.2250000000000000 2519 + 2.237500000000000 0.2375000000000000 2520 + 2.237500000000000 0.2500000000000000 2521 + 2.237500000000000 0.2625000000000000 2522 + 2.237500000000000 0.2750000000000000 2523 + 2.237500000000000 0.2875000000000000 2524 + 2.237500000000000 0.3000000000000000 2525 + 2.237500000000000 0.3125000000000000 2526 + 2.237500000000000 0.3250000000000000 2527 + 2.237500000000001 0.3375000000000001 2528 + 2.237500000000001 0.3499999999999999 2529 + 2.237500000000001 0.3625000000000000 2530 + 2.237500000000001 0.3750000000000000 2531 + 2.237500000000001 0.3875000000000001 2532 + 2.237500000000001 0.4000000000000000 2533 + 2.237500000000001 0.4125000000000000 2534 + 2.237500000000001 0.4250000000000000 2535 + 2.237500000000001 0.4375000000000000 2536 + 2.237500000000001 0.4499999999999999 2537 + 2.237500000000000 0.4625000000000000 2538 + 2.237500000000001 0.4750000000000001 2539 + 2.237500000000001 0.4875000000000000 2540 + 2.237500000000000 0.5000000000000000 2541 + 2.225000000000000 0.000000000000000 2542 + 2.225000000000001 0.01250000000000000 2543 + 2.225000000000000 0.02500000000000000 2544 + 2.225000000000001 0.03750000000000001 2545 + 2.225000000000000 0.05000000000000000 2546 + 2.225000000000000 0.06250000000000000 2547 + 2.225000000000001 0.07500000000000001 2548 + 2.225000000000000 0.08750000000000001 2549 + 2.225000000000001 0.1000000000000000 2550 + 2.225000000000000 0.1125000000000000 2551 + 2.225000000000000 0.1250000000000000 2552 + 2.225000000000000 0.1375000000000000 2553 + 2.225000000000000 0.1500000000000000 2554 + 2.225000000000000 0.1625000000000000 2555 + 2.225000000000000 0.1750000000000000 2556 + 2.225000000000000 0.1875000000000000 2557 + 2.225000000000000 0.2000000000000000 2558 + 2.225000000000000 0.2125000000000000 2559 + 2.225000000000000 0.2250000000000000 2560 + 2.225000000000001 0.2375000000000000 2561 + 2.225000000000001 0.2500000000000000 2562 + 2.225000000000001 0.2625000000000000 2563 + 2.225000000000001 0.2750000000000000 2564 + 2.225000000000001 0.2875000000000000 2565 + 2.225000000000001 0.3000000000000000 2566 + 2.225000000000000 0.3125000000000000 2567 + 2.225000000000000 0.3250000000000000 2568 + 2.225000000000000 0.3375000000000000 2569 + 2.225000000000000 0.3500000000000001 2570 + 2.225000000000000 0.3625000000000000 2571 + 2.225000000000000 0.3749999999999999 2572 + 2.225000000000000 0.3875000000000001 2573 + 2.224999999999999 0.4000000000000000 2574 + 2.224999999999999 0.4125000000000001 2575 + 2.224999999999999 0.4250000000000000 2576 + 2.224999999999999 0.4375000000000000 2577 + 2.224999999999999 0.4500000000000001 2578 + 2.224999999999999 0.4625000000000000 2579 + 2.224999999999999 0.4750000000000001 2580 + 2.224999999999999 0.4874999999999999 2581 + 2.225000000000000 0.5000000000000000 2582 + 2.212500000000000 0.000000000000000 2583 + 2.212500000000000 0.01250000000000000 2584 + 2.212500000000000 0.02500000000000000 2585 + 2.212500000000000 0.03750000000000001 2586 + 2.212500000000000 0.05000000000000000 2587 + 2.212500000000000 0.06250000000000000 2588 + 2.212499999999999 0.07500000000000001 2589 + 2.212499999999999 0.08750000000000004 2590 + 2.212499999999999 0.1000000000000000 2591 + 2.212499999999999 0.1125000000000000 2592 + 2.212499999999999 0.1250000000000000 2593 + 2.212500000000000 0.1375000000000000 2594 + 2.212500000000000 0.1500000000000000 2595 + 2.212499999999999 0.1625000000000000 2596 + 2.212499999999999 0.1750000000000000 2597 + 2.212500000000000 0.1875000000000000 2598 + 2.212500000000000 0.2000000000000000 2599 + 2.212500000000000 0.2125000000000000 2600 + 2.212500000000000 0.2250000000000000 2601 + 2.212500000000000 0.2375000000000000 2602 + 2.212499999999999 0.2500000000000000 2603 + 2.212499999999999 0.2625000000000000 2604 + 2.212499999999999 0.2750000000000000 2605 + 2.212499999999999 0.2875000000000000 2606 + 2.212500000000000 0.3000000000000000 2607 + 2.212500000000000 0.3125000000000000 2608 + 2.212499999999999 0.3250000000000000 2609 + 2.212499999999999 0.3375000000000000 2610 + 2.212499999999999 0.3500000000000000 2611 + 2.212499999999999 0.3625000000000000 2612 + 2.212499999999999 0.3750000000000000 2613 + 2.212499999999999 0.3875000000000000 2614 + 2.212499999999999 0.4000000000000000 2615 + 2.212499999999999 0.4125000000000000 2616 + 2.212499999999999 0.4250000000000000 2617 + 2.212500000000000 0.4375000000000000 2618 + 2.212500000000000 0.4500000000000001 2619 + 2.212500000000000 0.4625000000000001 2620 + 2.212500000000000 0.4750000000000001 2621 + 2.212500000000000 0.4875000000000000 2622 + 2.212500000000000 0.5000000000000000 2623 + 2.200000000000000 0.000000000000000 2624 + 2.200000000000000 0.01250000000000000 2625 + 2.199999999999999 0.02500000000000000 2626 + 2.200000000000000 0.03750000000000001 2627 + 2.200000000000000 0.05000000000000000 2628 + 2.199999999999999 0.06250000000000000 2629 + 2.199999999999999 0.07500000000000001 2630 + 2.200000000000000 0.08750000000000004 2631 + 2.200000000000000 0.1000000000000000 2632 + 2.200000000000000 0.1125000000000000 2633 + 2.200000000000000 0.1250000000000000 2634 + 2.200000000000000 0.1375000000000000 2635 + 2.200000000000000 0.1500000000000000 2636 + 2.200000000000000 0.1625000000000000 2637 + 2.200000000000000 0.1750000000000000 2638 + 2.200000000000000 0.1875000000000000 2639 + 2.200000000000000 0.2000000000000000 2640 + 2.200000000000000 0.2125000000000000 2641 + 2.200000000000001 0.2250000000000000 2642 + 2.200000000000000 0.2375000000000000 2643 + 2.200000000000001 0.2500000000000000 2644 + 2.199999999999999 0.2625000000000000 2645 + 2.200000000000000 0.2750000000000000 2646 + 2.199999999999999 0.2875000000000000 2647 + 2.200000000000000 0.3000000000000002 2648 + 2.199999999999999 0.3125000000000000 2649 + 2.200000000000000 0.3250000000000000 2650 + 2.200000000000000 0.3375000000000000 2651 + 2.200000000000000 0.3500000000000000 2652 + 2.200000000000000 0.3625000000000000 2653 + 2.200000000000000 0.3750000000000001 2654 + 2.200000000000000 0.3874999999999999 2655 + 2.200000000000000 0.4000000000000000 2656 + 2.200000000000000 0.4125000000000001 2657 + 2.200000000000000 0.4250000000000001 2658 + 2.200000000000000 0.4374999999999999 2659 + 2.200000000000000 0.4500000000000000 2660 + 2.200000000000000 0.4625000000000000 2661 + 2.200000000000000 0.4750000000000001 2662 + 2.200000000000000 0.4875000000000000 2663 + 2.200000000000000 0.5000000000000000 2664 + 2.187500000000000 0.000000000000000 2665 + 2.187500000000000 0.01250000000000000 2666 + 2.187500000000000 0.02500000000000000 2667 + 2.187500000000000 0.03750000000000001 2668 + 2.187500000000000 0.05000000000000000 2669 + 2.187500000000000 0.06250000000000000 2670 + 2.187500000000000 0.07500000000000001 2671 + 2.187500000000000 0.08750000000000002 2672 + 2.187500000000000 0.1000000000000000 2673 + 2.187500000000000 0.1125000000000000 2674 + 2.187500000000000 0.1250000000000000 2675 + 2.187500000000000 0.1375000000000000 2676 + 2.187500000000000 0.1500000000000000 2677 + 2.187500000000000 0.1625000000000000 2678 + 2.187500000000000 0.1750000000000000 2679 + 2.187500000000000 0.1875000000000000 2680 + 2.187500000000000 0.2000000000000000 2681 + 2.187500000000000 0.2125000000000000 2682 + 2.187500000000000 0.2250000000000000 2683 + 2.187500000000000 0.2375000000000000 2684 + 2.187500000000000 0.2500000000000000 2685 + 2.187500000000000 0.2625000000000000 2686 + 2.187500000000000 0.2750000000000000 2687 + 2.187500000000000 0.2875000000000000 2688 + 2.187500000000000 0.3000000000000000 2689 + 2.187500000000000 0.3125000000000000 2690 + 2.187500000000000 0.3250000000000000 2691 + 2.187500000000000 0.3375000000000000 2692 + 2.187500000000000 0.3500000000000000 2693 + 2.187500000000000 0.3625000000000000 2694 + 2.187500000000000 0.3750000000000000 2695 + 2.187500000000000 0.3874999999999999 2696 + 2.187500000000000 0.4000000000000000 2697 + 2.187500000000000 0.4125000000000000 2698 + 2.187500000000000 0.4250000000000000 2699 + 2.187500000000000 0.4374999999999999 2700 + 2.187500000000001 0.4500000000000000 2701 + 2.187500000000001 0.4625000000000001 2702 + 2.187500000000001 0.4750000000000000 2703 + 2.187500000000000 0.4875000000000001 2704 + 2.187500000000000 0.5000000000000000 2705 + 2.175000000000000 0.000000000000000 2706 + 2.175000000000000 0.01250000000000000 2707 + 2.175000000000000 0.02500000000000001 2708 + 2.175000000000000 0.03750000000000001 2709 + 2.175000000000000 0.05000000000000000 2710 + 2.175000000000000 0.06250000000000000 2711 + 2.175000000000000 0.07500000000000001 2712 + 2.175000000000000 0.08750000000000002 2713 + 2.175000000000000 0.1000000000000000 2714 + 2.175000000000001 0.1125000000000000 2715 + 2.175000000000001 0.1250000000000000 2716 + 2.175000000000001 0.1375000000000000 2717 + 2.175000000000001 0.1500000000000000 2718 + 2.175000000000001 0.1625000000000000 2719 + 2.175000000000000 0.1750000000000000 2720 + 2.175000000000001 0.1875000000000000 2721 + 2.175000000000001 0.2000000000000000 2722 + 2.175000000000001 0.2125000000000000 2723 + 2.175000000000001 0.2250000000000000 2724 + 2.175000000000000 0.2375000000000000 2725 + 2.175000000000000 0.2500000000000000 2726 + 2.175000000000000 0.2625000000000000 2727 + 2.175000000000000 0.2750000000000000 2728 + 2.175000000000000 0.2875000000000000 2729 + 2.174999999999999 0.3000000000000000 2730 + 2.174999999999999 0.3125000000000001 2731 + 2.175000000000000 0.3250000000000000 2732 + 2.175000000000000 0.3375000000000001 2733 + 2.175000000000000 0.3500000000000001 2734 + 2.174999999999999 0.3625000000000000 2735 + 2.174999999999999 0.3750000000000001 2736 + 2.174999999999999 0.3875000000000000 2737 + 2.174999999999999 0.4000000000000000 2738 + 2.174999999999999 0.4125000000000000 2739 + 2.174999999999999 0.4250000000000000 2740 + 2.174999999999999 0.4375000000000000 2741 + 2.174999999999999 0.4500000000000000 2742 + 2.174999999999999 0.4625000000000000 2743 + 2.174999999999999 0.4750000000000000 2744 + 2.174999999999999 0.4875000000000000 2745 + 2.175000000000000 0.5000000000000000 2746 + 2.162500000000000 0.000000000000000 2747 + 2.162500000000000 0.01250000000000000 2748 + 2.162500000000000 0.02500000000000000 2749 + 2.162500000000000 0.03750000000000001 2750 + 2.162500000000001 0.05000000000000000 2751 + 2.162500000000001 0.06250000000000000 2752 + 2.162500000000001 0.07500000000000001 2753 + 2.162500000000001 0.08750000000000001 2754 + 2.162500000000000 0.1000000000000000 2755 + 2.162500000000000 0.1125000000000000 2756 + 2.162500000000000 0.1250000000000000 2757 + 2.162500000000000 0.1375000000000000 2758 + 2.162500000000000 0.1500000000000000 2759 + 2.162500000000000 0.1625000000000000 2760 + 2.162499999999999 0.1750000000000000 2761 + 2.162499999999999 0.1875000000000000 2762 + 2.162499999999999 0.2000000000000000 2763 + 2.162499999999999 0.2125000000000000 2764 + 2.162499999999999 0.2250000000000000 2765 + 2.162499999999999 0.2375000000000000 2766 + 2.162499999999999 0.2500000000000000 2767 + 2.162499999999999 0.2625000000000000 2768 + 2.162499999999999 0.2750000000000000 2769 + 2.162500000000000 0.2875000000000000 2770 + 2.162500000000000 0.3000000000000000 2771 + 2.162500000000000 0.3125000000000000 2772 + 2.162500000000000 0.3250000000000000 2773 + 2.162500000000000 0.3375000000000000 2774 + 2.162500000000001 0.3500000000000001 2775 + 2.162500000000001 0.3624999999999999 2776 + 2.162500000000001 0.3750000000000000 2777 + 2.162500000000001 0.3875000000000001 2778 + 2.162500000000001 0.4000000000000000 2779 + 2.162500000000001 0.4125000000000000 2780 + 2.162500000000001 0.4250000000000000 2781 + 2.162500000000001 0.4375000000000000 2782 + 2.162500000000001 0.4500000000000000 2783 + 2.162500000000000 0.4625000000000001 2784 + 2.162500000000000 0.4749999999999999 2785 + 2.162500000000000 0.4875000000000000 2786 + 2.162500000000000 0.5000000000000000 2787 + 2.150000000000000 0.000000000000000 2788 + 2.150000000000000 0.01250000000000000 2789 + 2.149999999999999 0.02500000000000000 2790 + 2.150000000000000 0.03750000000000001 2791 + 2.149999999999999 0.05000000000000000 2792 + 2.149999999999999 0.06250000000000000 2793 + 2.150000000000000 0.07500000000000001 2794 + 2.149999999999999 0.08749999999999998 2795 + 2.150000000000000 0.1000000000000000 2796 + 2.149999999999999 0.1125000000000000 2797 + 2.149999999999999 0.1250000000000000 2798 + 2.149999999999999 0.1375000000000000 2799 + 2.149999999999999 0.1500000000000000 2800 + 2.149999999999999 0.1625000000000000 2801 + 2.149999999999999 0.1750000000000000 2802 + 2.149999999999999 0.1875000000000000 2803 + 2.149999999999999 0.2000000000000000 2804 + 2.150000000000000 0.2125000000000000 2805 + 2.150000000000000 0.2250000000000000 2806 + 2.150000000000000 0.2375000000000000 2807 + 2.150000000000000 0.2500000000000000 2808 + 2.150000000000000 0.2625000000000000 2809 + 2.150000000000000 0.2750000000000000 2810 + 2.150000000000000 0.2875000000000000 2811 + 2.150000000000000 0.3000000000000000 2812 + 2.150000000000000 0.3125000000000000 2813 + 2.150000000000000 0.3250000000000001 2814 + 2.150000000000000 0.3375000000000000 2815 + 2.150000000000000 0.3500000000000000 2816 + 2.149999999999999 0.3625000000000000 2817 + 2.149999999999999 0.3750000000000001 2818 + 2.149999999999999 0.3875000000000000 2819 + 2.149999999999999 0.4000000000000000 2820 + 2.149999999999999 0.4125000000000001 2821 + 2.149999999999999 0.4250000000000000 2822 + 2.149999999999999 0.4375000000000000 2823 + 2.149999999999999 0.4500000000000000 2824 + 2.149999999999999 0.4625000000000000 2825 + 2.150000000000000 0.4750000000000000 2826 + 2.150000000000000 0.4875000000000000 2827 + 2.150000000000000 0.5000000000000000 2828 + 2.137500000000000 0.000000000000000 2829 + 2.137499999999999 0.01250000000000000 2830 + 2.137500000000000 0.02500000000000000 2831 + 2.137500000000000 0.03750000000000001 2832 + 2.137499999999999 0.05000000000000000 2833 + 2.137499999999999 0.06250000000000000 2834 + 2.137499999999999 0.07500000000000001 2835 + 2.137500000000000 0.08750000000000001 2836 + 2.137500000000000 0.1000000000000000 2837 + 2.137500000000000 0.1125000000000000 2838 + 2.137500000000000 0.1250000000000000 2839 + 2.137500000000000 0.1375000000000000 2840 + 2.137500000000000 0.1500000000000000 2841 + 2.137500000000000 0.1625000000000000 2842 + 2.137500000000000 0.1750000000000000 2843 + 2.137500000000000 0.1875000000000000 2844 + 2.137500000000000 0.2000000000000001 2845 + 2.137500000000000 0.2125000000000000 2846 + 2.137500000000000 0.2250000000000000 2847 + 2.137500000000000 0.2375000000000000 2848 + 2.137500000000000 0.2500000000000000 2849 + 2.137500000000001 0.2625000000000000 2850 + 2.137500000000001 0.2750000000000000 2851 + 2.137500000000001 0.2875000000000001 2852 + 2.137500000000000 0.3000000000000000 2853 + 2.137500000000001 0.3125000000000000 2854 + 2.137500000000001 0.3250000000000000 2855 + 2.137500000000001 0.3374999999999999 2856 + 2.137500000000001 0.3500000000000000 2857 + 2.137500000000001 0.3625000000000000 2858 + 2.137500000000001 0.3750000000000000 2859 + 2.137500000000001 0.3875000000000000 2860 + 2.137500000000001 0.4000000000000000 2861 + 2.137500000000001 0.4125000000000000 2862 + 2.137500000000001 0.4250000000000000 2863 + 2.137500000000001 0.4375000000000001 2864 + 2.137500000000000 0.4500000000000000 2865 + 2.137500000000000 0.4625000000000000 2866 + 2.137500000000000 0.4750000000000001 2867 + 2.137500000000000 0.4875000000000001 2868 + 2.137500000000000 0.5000000000000000 2869 + 2.125000000000000 0.000000000000000 2870 + 2.125000000000000 0.01250000000000000 2871 + 2.125000000000000 0.02500000000000000 2872 + 2.125000000000000 0.03750000000000002 2873 + 2.125000000000000 0.05000000000000000 2874 + 2.125000000000000 0.06250000000000000 2875 + 2.125000000000000 0.07500000000000001 2876 + 2.125000000000000 0.08750000000000001 2877 + 2.125000000000000 0.1000000000000000 2878 + 2.125000000000000 0.1125000000000000 2879 + 2.125000000000000 0.1250000000000000 2880 + 2.125000000000000 0.1375000000000000 2881 + 2.125000000000000 0.1500000000000000 2882 + 2.125000000000000 0.1625000000000000 2883 + 2.125000000000000 0.1750000000000000 2884 + 2.125000000000000 0.1875000000000000 2885 + 2.125000000000000 0.2000000000000000 2886 + 2.125000000000000 0.2125000000000000 2887 + 2.125000000000001 0.2250000000000001 2888 + 2.125000000000001 0.2375000000000000 2889 + 2.125000000000001 0.2500000000000000 2890 + 2.125000000000001 0.2625000000000000 2891 + 2.125000000000000 0.2750000000000000 2892 + 2.125000000000000 0.2874999999999999 2893 + 2.125000000000000 0.3000000000000000 2894 + 2.125000000000000 0.3125000000000000 2895 + 2.125000000000000 0.3250000000000000 2896 + 2.124999999999999 0.3375000000000000 2897 + 2.124999999999999 0.3499999999999999 2898 + 2.124999999999999 0.3625000000000000 2899 + 2.125000000000000 0.3750000000000001 2900 + 2.125000000000000 0.3875000000000001 2901 + 2.125000000000000 0.4000000000000000 2902 + 2.125000000000000 0.4124999999999999 2903 + 2.125000000000000 0.4250000000000000 2904 + 2.125000000000000 0.4375000000000000 2905 + 2.125000000000000 0.4500000000000000 2906 + 2.125000000000000 0.4625000000000000 2907 + 2.125000000000000 0.4750000000000001 2908 + 2.125000000000000 0.4875000000000000 2909 + 2.125000000000000 0.5000000000000000 2910 + 2.112500000000000 0.000000000000000 2911 + 2.112500000000001 0.01250000000000000 2912 + 2.112500000000000 0.02500000000000000 2913 + 2.112500000000001 0.03750000000000001 2914 + 2.112500000000001 0.05000000000000002 2915 + 2.112500000000001 0.06250000000000000 2916 + 2.112500000000001 0.07500000000000001 2917 + 2.112500000000001 0.08750000000000002 2918 + 2.112500000000001 0.09999999999999999 2919 + 2.112500000000000 0.1125000000000000 2920 + 2.112500000000000 0.1250000000000000 2921 + 2.112499999999999 0.1375000000000000 2922 + 2.112500000000000 0.1500000000000000 2923 + 2.112499999999999 0.1625000000000000 2924 + 2.112499999999999 0.1750000000000000 2925 + 2.112500000000000 0.1875000000000000 2926 + 2.112499999999999 0.2000000000000000 2927 + 2.112500000000000 0.2125000000000000 2928 + 2.112500000000000 0.2250000000000000 2929 + 2.112499999999999 0.2375000000000000 2930 + 2.112499999999999 0.2500000000000000 2931 + 2.112499999999999 0.2625000000000001 2932 + 2.112499999999999 0.2750000000000000 2933 + 2.112500000000000 0.2875000000000001 2934 + 2.112499999999999 0.3000000000000000 2935 + 2.112499999999999 0.3125000000000000 2936 + 2.112499999999999 0.3250000000000000 2937 + 2.112500000000000 0.3375000000000000 2938 + 2.112500000000000 0.3500000000000000 2939 + 2.112500000000000 0.3625000000000000 2940 + 2.112500000000000 0.3750000000000000 2941 + 2.112500000000000 0.3875000000000001 2942 + 2.112500000000000 0.4000000000000000 2943 + 2.112500000000000 0.4125000000000000 2944 + 2.112500000000000 0.4250000000000000 2945 + 2.112500000000000 0.4375000000000000 2946 + 2.112500000000000 0.4500000000000000 2947 + 2.112500000000000 0.4624999999999999 2948 + 2.112500000000000 0.4750000000000001 2949 + 2.112500000000000 0.4875000000000000 2950 + 2.112500000000000 0.5000000000000000 2951 + 2.100000000000000 0.000000000000000 2952 + 2.099999999999999 0.01250000000000000 2953 + 2.099999999999999 0.02500000000000000 2954 + 2.099999999999999 0.03750000000000001 2955 + 2.099999999999999 0.05000000000000000 2956 + 2.099999999999999 0.06250000000000000 2957 + 2.100000000000000 0.07500000000000001 2958 + 2.100000000000001 0.08750000000000001 2959 + 2.100000000000000 0.1000000000000000 2960 + 2.100000000000000 0.1125000000000000 2961 + 2.100000000000000 0.1250000000000000 2962 + 2.100000000000001 0.1375000000000000 2963 + 2.100000000000001 0.1500000000000000 2964 + 2.100000000000000 0.1625000000000000 2965 + 2.100000000000000 0.1750000000000000 2966 + 2.100000000000001 0.1875000000000000 2967 + 2.100000000000001 0.2000000000000000 2968 + 2.100000000000001 0.2125000000000000 2969 + 2.100000000000001 0.2250000000000000 2970 + 2.100000000000000 0.2375000000000000 2971 + 2.100000000000000 0.2500000000000000 2972 + 2.100000000000000 0.2625000000000000 2973 + 2.100000000000000 0.2750000000000000 2974 + 2.100000000000000 0.2874999999999999 2975 + 2.100000000000000 0.3000000000000000 2976 + 2.100000000000000 0.3125000000000000 2977 + 2.100000000000000 0.3250000000000000 2978 + 2.100000000000000 0.3375000000000000 2979 + 2.100000000000000 0.3500000000000000 2980 + 2.100000000000001 0.3625000000000000 2981 + 2.100000000000001 0.3750000000000001 2982 + 2.100000000000001 0.3875000000000001 2983 + 2.100000000000001 0.4000000000000000 2984 + 2.100000000000001 0.4125000000000001 2985 + 2.100000000000001 0.4250000000000000 2986 + 2.100000000000001 0.4374999999999999 2987 + 2.100000000000001 0.4500000000000000 2988 + 2.100000000000001 0.4625000000000000 2989 + 2.100000000000000 0.4750000000000000 2990 + 2.100000000000001 0.4874999999999999 2991 + 2.100000000000000 0.5000000000000000 2992 + 2.087500000000000 0.000000000000000 2993 + 2.087500000000000 0.01250000000000000 2994 + 2.087500000000000 0.02500000000000000 2995 + 2.087500000000000 0.03750000000000001 2996 + 2.087500000000000 0.05000000000000001 2997 + 2.087500000000000 0.06250000000000000 2998 + 2.087500000000000 0.07500000000000001 2999 + 2.087500000000000 0.08750000000000004 3000 + 2.087500000000000 0.1000000000000000 3001 + 2.087500000000000 0.1125000000000000 3002 + 2.087500000000000 0.1250000000000000 3003 + 2.087500000000000 0.1375000000000000 3004 + 2.087499999999999 0.1500000000000000 3005 + 2.087500000000001 0.1625000000000000 3006 + 2.087499999999999 0.1750000000000000 3007 + 2.087499999999999 0.1875000000000000 3008 + 2.087499999999999 0.2000000000000000 3009 + 2.087499999999999 0.2125000000000000 3010 + 2.087499999999999 0.2250000000000000 3011 + 2.087499999999999 0.2375000000000000 3012 + 2.087500000000000 0.2500000000000000 3013 + 2.087500000000000 0.2625000000000000 3014 + 2.087500000000000 0.2750000000000000 3015 + 2.087500000000000 0.2875000000000001 3016 + 2.087500000000000 0.3000000000000000 3017 + 2.087500000000001 0.3125000000000000 3018 + 2.087500000000001 0.3250000000000000 3019 + 2.087500000000001 0.3375000000000000 3020 + 2.087500000000001 0.3500000000000001 3021 + 2.087500000000001 0.3625000000000000 3022 + 2.087500000000001 0.3750000000000000 3023 + 2.087500000000001 0.3875000000000001 3024 + 2.087500000000001 0.4000000000000000 3025 + 2.087500000000000 0.4125000000000000 3026 + 2.087500000000000 0.4250000000000002 3027 + 2.087500000000000 0.4375000000000000 3028 + 2.087500000000000 0.4500000000000001 3029 + 2.087499999999999 0.4625000000000000 3030 + 2.087499999999999 0.4750000000000000 3031 + 2.087499999999999 0.4875000000000000 3032 + 2.087500000000000 0.5000000000000000 3033 + 2.075000000000000 0.000000000000000 3034 + 2.075000000000000 0.01250000000000000 3035 + 2.075000000000000 0.02499999999999999 3036 + 2.075000000000000 0.03750000000000001 3037 + 2.075000000000000 0.05000000000000000 3038 + 2.075000000000000 0.06250000000000000 3039 + 2.075000000000000 0.07500000000000001 3040 + 2.074999999999999 0.08750000000000004 3041 + 2.075000000000001 0.09999999999999999 3042 + 2.075000000000000 0.1125000000000000 3043 + 2.075000000000001 0.1250000000000000 3044 + 2.075000000000000 0.1375000000000000 3045 + 2.075000000000000 0.1500000000000000 3046 + 2.075000000000001 0.1625000000000000 3047 + 2.075000000000000 0.1750000000000000 3048 + 2.075000000000000 0.1875000000000000 3049 + 2.075000000000001 0.2000000000000000 3050 + 2.075000000000001 0.2125000000000000 3051 + 2.075000000000001 0.2250000000000000 3052 + 2.075000000000000 0.2375000000000001 3053 + 2.075000000000000 0.2500000000000000 3054 + 2.075000000000000 0.2625000000000000 3055 + 2.075000000000001 0.2750000000000000 3056 + 2.075000000000001 0.2875000000000001 3057 + 2.075000000000001 0.3000000000000000 3058 + 2.075000000000001 0.3125000000000000 3059 + 2.075000000000000 0.3250000000000000 3060 + 2.075000000000000 0.3375000000000000 3061 + 2.075000000000000 0.3500000000000000 3062 + 2.075000000000000 0.3624999999999999 3063 + 2.075000000000000 0.3749999999999999 3064 + 2.075000000000000 0.3875000000000001 3065 + 2.075000000000000 0.4000000000000000 3066 + 2.075000000000000 0.4125000000000000 3067 + 2.075000000000000 0.4250000000000000 3068 + 2.075000000000000 0.4375000000000001 3069 + 2.075000000000000 0.4500000000000000 3070 + 2.075000000000000 0.4625000000000000 3071 + 2.075000000000000 0.4750000000000001 3072 + 2.074999999999999 0.4875000000000000 3073 + 2.075000000000000 0.5000000000000000 3074 + 2.062500000000000 0.000000000000000 3075 + 2.062500000000000 0.01250000000000000 3076 + 2.062500000000001 0.02500000000000000 3077 + 2.062500000000001 0.03750000000000002 3078 + 2.062500000000001 0.05000000000000000 3079 + 2.062500000000001 0.06250000000000000 3080 + 2.062500000000000 0.07500000000000001 3081 + 2.062499999999999 0.08750000000000004 3082 + 2.062500000000000 0.1000000000000000 3083 + 2.062500000000000 0.1125000000000000 3084 + 2.062500000000000 0.1250000000000000 3085 + 2.062499999999999 0.1375000000000000 3086 + 2.062499999999999 0.1500000000000000 3087 + 2.062500000000000 0.1625000000000000 3088 + 2.062500000000000 0.1750000000000000 3089 + 2.062500000000000 0.1875000000000000 3090 + 2.062500000000000 0.2000000000000000 3091 + 2.062500000000000 0.2125000000000000 3092 + 2.062500000000000 0.2250000000000000 3093 + 2.062500000000000 0.2375000000000000 3094 + 2.062500000000000 0.2500000000000000 3095 + 2.062500000000000 0.2625000000000000 3096 + 2.062500000000000 0.2750000000000000 3097 + 2.062500000000000 0.2875000000000000 3098 + 2.062500000000000 0.3000000000000000 3099 + 2.062500000000000 0.3125000000000000 3100 + 2.062500000000000 0.3250000000000001 3101 + 2.062500000000000 0.3375000000000000 3102 + 2.062500000000000 0.3500000000000000 3103 + 2.062500000000000 0.3625000000000000 3104 + 2.062500000000000 0.3750000000000000 3105 + 2.062500000000000 0.3875000000000000 3106 + 2.062500000000000 0.4000000000000000 3107 + 2.062500000000000 0.4125000000000001 3108 + 2.062500000000000 0.4250000000000002 3109 + 2.062500000000000 0.4375000000000000 3110 + 2.062500000000000 0.4499999999999999 3111 + 2.062500000000000 0.4625000000000000 3112 + 2.062500000000000 0.4750000000000000 3113 + 2.062500000000000 0.4874999999999999 3114 + 2.062500000000000 0.5000000000000000 3115 + 2.050000000000000 0.000000000000000 3116 + 2.050000000000000 0.01250000000000000 3117 + 2.050000000000000 0.02500000000000000 3118 + 2.050000000000000 0.03750000000000001 3119 + 2.050000000000000 0.05000000000000000 3120 + 2.050000000000000 0.06250000000000000 3121 + 2.050000000000000 0.07500000000000001 3122 + 2.050000000000000 0.08750000000000004 3123 + 2.050000000000000 0.09999999999999999 3124 + 2.050000000000000 0.1125000000000000 3125 + 2.049999999999999 0.1250000000000000 3126 + 2.049999999999999 0.1375000000000000 3127 + 2.049999999999999 0.1500000000000001 3128 + 2.050000000000001 0.1625000000000000 3129 + 2.050000000000000 0.1750000000000000 3130 + 2.050000000000000 0.1875000000000000 3131 + 2.050000000000000 0.2000000000000000 3132 + 2.050000000000000 0.2125000000000000 3133 + 2.050000000000000 0.2250000000000001 3134 + 2.050000000000000 0.2375000000000000 3135 + 2.050000000000000 0.2500000000000000 3136 + 2.050000000000000 0.2625000000000000 3137 + 2.050000000000000 0.2750000000000000 3138 + 2.050000000000000 0.2875000000000000 3139 + 2.050000000000000 0.3000000000000000 3140 + 2.050000000000000 0.3125000000000000 3141 + 2.050000000000000 0.3250000000000000 3142 + 2.049999999999999 0.3375000000000000 3143 + 2.049999999999999 0.3500000000000001 3144 + 2.050000000000000 0.3624999999999999 3145 + 2.050000000000000 0.3750000000000001 3146 + 2.050000000000000 0.3875000000000000 3147 + 2.050000000000000 0.4000000000000000 3148 + 2.050000000000000 0.4125000000000000 3149 + 2.050000000000000 0.4250000000000000 3150 + 2.050000000000000 0.4375000000000000 3151 + 2.050000000000000 0.4500000000000000 3152 + 2.050000000000000 0.4625000000000000 3153 + 2.050000000000001 0.4750000000000000 3154 + 2.050000000000001 0.4875000000000002 3155 + 2.050000000000000 0.5000000000000000 3156 + 2.037500000000000 0.000000000000000 3157 + 2.037500000000001 0.01250000000000000 3158 + 2.037500000000000 0.02499999999999999 3159 + 2.037500000000001 0.03750000000000001 3160 + 2.037500000000001 0.05000000000000000 3161 + 2.037500000000000 0.06250000000000000 3162 + 2.037500000000000 0.07500000000000001 3163 + 2.037500000000000 0.08750000000000001 3164 + 2.037500000000000 0.1000000000000000 3165 + 2.037500000000000 0.1125000000000000 3166 + 2.037500000000000 0.1250000000000000 3167 + 2.037500000000000 0.1375000000000000 3168 + 2.037500000000000 0.1500000000000000 3169 + 2.037500000000000 0.1625000000000000 3170 + 2.037500000000000 0.1750000000000000 3171 + 2.037500000000000 0.1875000000000000 3172 + 2.037500000000000 0.2000000000000000 3173 + 2.037500000000001 0.2125000000000000 3174 + 2.037500000000001 0.2250000000000000 3175 + 2.037500000000000 0.2375000000000001 3176 + 2.037500000000000 0.2500000000000000 3177 + 2.037499999999999 0.2625000000000000 3178 + 2.037500000000001 0.2750000000000000 3179 + 2.037500000000000 0.2875000000000000 3180 + 2.037500000000000 0.3000000000000000 3181 + 2.037500000000000 0.3125000000000000 3182 + 2.037500000000000 0.3250000000000000 3183 + 2.037500000000000 0.3375000000000000 3184 + 2.037500000000000 0.3500000000000000 3185 + 2.037500000000000 0.3625000000000000 3186 + 2.037500000000000 0.3750000000000000 3187 + 2.037500000000000 0.3874999999999999 3188 + 2.037500000000000 0.4000000000000001 3189 + 2.037500000000001 0.4125000000000000 3190 + 2.037500000000000 0.4249999999999999 3191 + 2.037500000000000 0.4374999999999999 3192 + 2.037499999999999 0.4500000000000001 3193 + 2.037499999999999 0.4625000000000000 3194 + 2.037499999999999 0.4750000000000000 3195 + 2.037499999999999 0.4875000000000000 3196 + 2.037500000000000 0.5000000000000000 3197 + 2.025000000000000 0.000000000000000 3198 + 2.024999999999999 0.01250000000000000 3199 + 2.024999999999999 0.02500000000000000 3200 + 2.024999999999999 0.03749999999999999 3201 + 2.024999999999999 0.05000000000000000 3202 + 2.025000000000000 0.06250000000000000 3203 + 2.025000000000000 0.07500000000000001 3204 + 2.025000000000000 0.08749999999999999 3205 + 2.025000000000000 0.1000000000000000 3206 + 2.025000000000000 0.1125000000000000 3207 + 2.025000000000000 0.1250000000000000 3208 + 2.025000000000001 0.1375000000000000 3209 + 2.025000000000001 0.1500000000000000 3210 + 2.025000000000001 0.1625000000000000 3211 + 2.025000000000000 0.1750000000000000 3212 + 2.025000000000001 0.1875000000000000 3213 + 2.025000000000001 0.2000000000000000 3214 + 2.025000000000001 0.2125000000000000 3215 + 2.025000000000001 0.2250000000000000 3216 + 2.025000000000000 0.2375000000000000 3217 + 2.025000000000000 0.2500000000000000 3218 + 2.025000000000000 0.2625000000000000 3219 + 2.024999999999999 0.2750000000000000 3220 + 2.024999999999999 0.2875000000000000 3221 + 2.024999999999999 0.3000000000000000 3222 + 2.024999999999999 0.3125000000000000 3223 + 2.024999999999999 0.3249999999999999 3224 + 2.024999999999999 0.3375000000000000 3225 + 2.025000000000000 0.3500000000000000 3226 + 2.025000000000000 0.3625000000000000 3227 + 2.025000000000000 0.3750000000000000 3228 + 2.025000000000000 0.3874999999999999 3229 + 2.025000000000000 0.4000000000000000 3230 + 2.025000000000000 0.4125000000000000 3231 + 2.025000000000000 0.4250000000000000 3232 + 2.025000000000000 0.4375000000000000 3233 + 2.024999999999999 0.4500000000000001 3234 + 2.024999999999999 0.4625000000000001 3235 + 2.024999999999999 0.4749999999999999 3236 + 2.024999999999999 0.4874999999999999 3237 + 2.025000000000000 0.5000000000000000 3238 + 2.012500000000000 0.000000000000000 3239 + 2.012500000000000 0.01250000000000000 3240 + 2.012500000000001 0.02499999999999999 3241 + 2.012500000000000 0.03750000000000001 3242 + 2.012500000000001 0.05000000000000000 3243 + 2.012500000000001 0.06250000000000000 3244 + 2.012500000000001 0.07500000000000001 3245 + 2.012499999999999 0.08750000000000001 3246 + 2.012499999999999 0.09999999999999999 3247 + 2.012499999999999 0.1125000000000000 3248 + 2.012499999999999 0.1250000000000000 3249 + 2.012499999999999 0.1375000000000000 3250 + 2.012499999999999 0.1500000000000000 3251 + 2.012500000000000 0.1625000000000000 3252 + 2.012499999999999 0.1750000000000000 3253 + 2.012499999999999 0.1875000000000000 3254 + 2.012499999999999 0.2000000000000001 3255 + 2.012499999999999 0.2125000000000000 3256 + 2.012500000000000 0.2250000000000000 3257 + 2.012499999999999 0.2375000000000000 3258 + 2.012499999999999 0.2500000000000000 3259 + 2.012499999999999 0.2625000000000000 3260 + 2.012500000000000 0.2750000000000000 3261 + 2.012500000000000 0.2875000000000000 3262 + 2.012500000000000 0.3000000000000000 3263 + 2.012500000000000 0.3125000000000000 3264 + 2.012500000000000 0.3250000000000000 3265 + 2.012500000000000 0.3375000000000000 3266 + 2.012500000000000 0.3500000000000000 3267 + 2.012500000000000 0.3625000000000000 3268 + 2.012500000000000 0.3749999999999999 3269 + 2.012500000000000 0.3875000000000000 3270 + 2.012500000000000 0.4000000000000000 3271 + 2.012500000000000 0.4125000000000000 3272 + 2.012499999999999 0.4250000000000000 3273 + 2.012499999999999 0.4375000000000000 3274 + 2.012499999999999 0.4499999999999999 3275 + 2.012499999999999 0.4625000000000000 3276 + 2.012499999999999 0.4750000000000001 3277 + 2.012499999999999 0.4875000000000001 3278 + 2.012500000000000 0.5000000000000000 3279 + 2.000000000000000 0.000000000000000 3280 + 2.000000000000000 0.01250000000000000 3281 + 2.000000000000000 0.02500000000000000 3282 + 1.999999999999999 0.03750000000000001 3283 + 2.000000000000000 0.05000000000000000 3284 + 2.000000000000000 0.06250000000000000 3285 + 2.000000000000000 0.07500000000000004 3286 + 2.000000000000000 0.08749999999999998 3287 + 2.000000000000000 0.1000000000000000 3288 + 2.000000000000000 0.1125000000000000 3289 + 2.000000000000000 0.1250000000000000 3290 + 2.000000000000000 0.1375000000000000 3291 + 2.000000000000000 0.1500000000000000 3292 + 2.000000000000000 0.1625000000000000 3293 + 2.000000000000000 0.1750000000000000 3294 + 2.000000000000000 0.1875000000000000 3295 + 2.000000000000000 0.2000000000000000 3296 + 2.000000000000000 0.2125000000000000 3297 + 2.000000000000000 0.2250000000000000 3298 + 2.000000000000000 0.2375000000000000 3299 + 2.000000000000000 0.2500000000000000 3300 + 2.000000000000000 0.2625000000000000 3301 + 2.000000000000000 0.2750000000000000 3302 + 2.000000000000000 0.2875000000000000 3303 + 2.000000000000000 0.3000000000000000 3304 + 2.000000000000000 0.3125000000000000 3305 + 2.000000000000000 0.3250000000000000 3306 + 2.000000000000000 0.3375000000000000 3307 + 2.000000000000000 0.3499999999999999 3308 + 2.000000000000000 0.3625000000000001 3309 + 2.000000000000000 0.3750000000000000 3310 + 2.000000000000000 0.3875000000000001 3311 + 2.000000000000000 0.4000000000000000 3312 + 2.000000000000000 0.4125000000000000 3313 + 2.000000000000000 0.4249999999999999 3314 + 2.000000000000000 0.4374999999999999 3315 + 2.000000000000000 0.4500000000000000 3316 + 2.000000000000000 0.4625000000000000 3317 + 2.000000000000000 0.4750000000000000 3318 + 2.000000000000000 0.4875000000000000 3319 + 2.000000000000000 0.5000000000000000 3320 + 1.987500000000000 0.000000000000000 3321 + 1.987500000000000 0.01250000000000000 3322 + 1.987500000000000 0.02500000000000000 3323 + 1.987500000000000 0.03750000000000001 3324 + 1.987500000000000 0.05000000000000000 3325 + 1.987500000000000 0.06250000000000000 3326 + 1.987500000000000 0.07500000000000001 3327 + 1.987500000000000 0.08750000000000001 3328 + 1.987500000000000 0.1000000000000000 3329 + 1.987500000000000 0.1125000000000000 3330 + 1.987500000000000 0.1250000000000000 3331 + 1.987500000000001 0.1375000000000000 3332 + 1.987500000000001 0.1500000000000000 3333 + 1.987500000000000 0.1625000000000000 3334 + 1.987500000000001 0.1750000000000000 3335 + 1.987500000000000 0.1875000000000000 3336 + 1.987500000000000 0.2000000000000000 3337 + 1.987500000000000 0.2125000000000000 3338 + 1.987500000000000 0.2250000000000000 3339 + 1.987500000000000 0.2375000000000000 3340 + 1.987500000000000 0.2500000000000000 3341 + 1.987500000000000 0.2625000000000000 3342 + 1.987500000000000 0.2750000000000000 3343 + 1.987500000000000 0.2875000000000000 3344 + 1.987500000000000 0.3000000000000000 3345 + 1.987500000000000 0.3125000000000000 3346 + 1.987500000000000 0.3250000000000000 3347 + 1.987500000000000 0.3375000000000000 3348 + 1.987500000000000 0.3500000000000000 3349 + 1.987500000000000 0.3624999999999999 3350 + 1.987500000000000 0.3750000000000000 3351 + 1.987500000000000 0.3875000000000000 3352 + 1.987500000000000 0.4000000000000000 3353 + 1.987500000000000 0.4125000000000000 3354 + 1.987500000000001 0.4250000000000000 3355 + 1.987500000000000 0.4375000000000000 3356 + 1.987500000000000 0.4500000000000000 3357 + 1.987500000000000 0.4625000000000000 3358 + 1.987500000000000 0.4750000000000000 3359 + 1.987500000000000 0.4875000000000000 3360 + 1.987500000000000 0.5000000000000000 3361 + 1.975000000000000 0.000000000000000 3362 + 1.975000000000001 0.01250000000000000 3363 + 1.975000000000000 0.02500000000000000 3364 + 1.975000000000000 0.03750000000000001 3365 + 1.975000000000001 0.04999999999999999 3366 + 1.975000000000001 0.06250000000000000 3367 + 1.975000000000001 0.07500000000000001 3368 + 1.975000000000000 0.08750000000000001 3369 + 1.975000000000001 0.1000000000000000 3370 + 1.975000000000000 0.1125000000000000 3371 + 1.975000000000000 0.1250000000000000 3372 + 1.975000000000000 0.1375000000000000 3373 + 1.974999999999999 0.1500000000000000 3374 + 1.975000000000000 0.1625000000000000 3375 + 1.974999999999999 0.1750000000000000 3376 + 1.974999999999999 0.1875000000000000 3377 + 1.975000000000000 0.2000000000000000 3378 + 1.975000000000000 0.2125000000000000 3379 + 1.975000000000000 0.2250000000000000 3380 + 1.975000000000000 0.2375000000000000 3381 + 1.975000000000000 0.2500000000000000 3382 + 1.975000000000000 0.2625000000000000 3383 + 1.975000000000000 0.2750000000000000 3384 + 1.975000000000000 0.2875000000000000 3385 + 1.975000000000000 0.3000000000000000 3386 + 1.975000000000000 0.3125000000000000 3387 + 1.974999999999999 0.3250000000000000 3388 + 1.975000000000000 0.3375000000000000 3389 + 1.975000000000000 0.3500000000000000 3390 + 1.975000000000000 0.3625000000000000 3391 + 1.975000000000000 0.3750000000000000 3392 + 1.975000000000000 0.3875000000000000 3393 + 1.975000000000000 0.4000000000000000 3394 + 1.975000000000000 0.4124999999999999 3395 + 1.975000000000000 0.4250000000000000 3396 + 1.975000000000000 0.4375000000000000 3397 + 1.975000000000000 0.4500000000000000 3398 + 1.975000000000000 0.4625000000000000 3399 + 1.974999999999999 0.4750000000000001 3400 + 1.974999999999999 0.4874999999999999 3401 + 1.975000000000000 0.5000000000000000 3402 + 1.962500000000000 0.000000000000000 3403 + 1.962500000000000 0.01250000000000000 3404 + 1.962500000000000 0.02500000000000000 3405 + 1.962500000000000 0.03750000000000001 3406 + 1.962500000000000 0.05000000000000000 3407 + 1.962500000000000 0.06250000000000000 3408 + 1.962500000000000 0.07500000000000001 3409 + 1.962500000000000 0.08750000000000001 3410 + 1.962500000000001 0.1000000000000000 3411 + 1.962500000000000 0.1125000000000000 3412 + 1.962500000000000 0.1250000000000000 3413 + 1.962500000000000 0.1375000000000000 3414 + 1.962500000000000 0.1500000000000000 3415 + 1.962500000000001 0.1625000000000001 3416 + 1.962500000000000 0.1750000000000000 3417 + 1.962500000000000 0.1875000000000000 3418 + 1.962500000000000 0.2000000000000000 3419 + 1.962500000000000 0.2125000000000000 3420 + 1.962500000000000 0.2250000000000000 3421 + 1.962500000000001 0.2375000000000000 3422 + 1.962500000000001 0.2500000000000000 3423 + 1.962500000000001 0.2625000000000000 3424 + 1.962500000000000 0.2750000000000000 3425 + 1.962500000000000 0.2875000000000001 3426 + 1.962500000000000 0.3000000000000000 3427 + 1.962500000000000 0.3125000000000000 3428 + 1.962500000000001 0.3250000000000000 3429 + 1.962500000000000 0.3375000000000000 3430 + 1.962500000000000 0.3500000000000000 3431 + 1.962500000000000 0.3624999999999999 3432 + 1.962500000000000 0.3750000000000000 3433 + 1.962499999999999 0.3875000000000001 3434 + 1.962500000000000 0.3999999999999999 3435 + 1.962500000000000 0.4125000000000001 3436 + 1.962500000000000 0.4250000000000000 3437 + 1.962500000000000 0.4375000000000000 3438 + 1.962500000000000 0.4500000000000001 3439 + 1.962500000000000 0.4625000000000000 3440 + 1.962500000000000 0.4750000000000000 3441 + 1.962500000000000 0.4875000000000000 3442 + 1.962500000000000 0.5000000000000000 3443 + 1.950000000000000 0.000000000000000 3444 + 1.950000000000000 0.01250000000000000 3445 + 1.949999999999999 0.02500000000000000 3446 + 1.950000000000000 0.03750000000000001 3447 + 1.950000000000000 0.05000000000000000 3448 + 1.950000000000000 0.06250000000000000 3449 + 1.950000000000000 0.07500000000000001 3450 + 1.950000000000000 0.08750000000000001 3451 + 1.950000000000000 0.1000000000000000 3452 + 1.950000000000000 0.1125000000000000 3453 + 1.950000000000000 0.1250000000000000 3454 + 1.950000000000000 0.1375000000000000 3455 + 1.950000000000000 0.1500000000000000 3456 + 1.950000000000000 0.1625000000000000 3457 + 1.950000000000000 0.1750000000000000 3458 + 1.950000000000000 0.1875000000000000 3459 + 1.950000000000000 0.2000000000000001 3460 + 1.950000000000000 0.2125000000000000 3461 + 1.950000000000000 0.2250000000000000 3462 + 1.950000000000000 0.2375000000000000 3463 + 1.949999999999999 0.2500000000000000 3464 + 1.949999999999999 0.2625000000000000 3465 + 1.950000000000000 0.2750000000000000 3466 + 1.950000000000000 0.2875000000000000 3467 + 1.949999999999999 0.3000000000000002 3468 + 1.950000000000000 0.3125000000000000 3469 + 1.950000000000000 0.3250000000000000 3470 + 1.950000000000000 0.3375000000000000 3471 + 1.950000000000000 0.3500000000000001 3472 + 1.950000000000000 0.3625000000000000 3473 + 1.950000000000000 0.3750000000000000 3474 + 1.950000000000000 0.3875000000000001 3475 + 1.950000000000000 0.4000000000000000 3476 + 1.950000000000000 0.4125000000000000 3477 + 1.950000000000000 0.4250000000000000 3478 + 1.950000000000000 0.4375000000000000 3479 + 1.950000000000000 0.4500000000000001 3480 + 1.950000000000000 0.4625000000000000 3481 + 1.949999999999999 0.4750000000000001 3482 + 1.949999999999999 0.4875000000000000 3483 + 1.950000000000000 0.5000000000000000 3484 + 1.937500000000000 0.000000000000000 3485 + 1.937500000000000 0.01250000000000000 3486 + 1.937499999999999 0.02500000000000000 3487 + 1.937500000000000 0.03750000000000001 3488 + 1.937500000000000 0.05000000000000000 3489 + 1.937500000000000 0.06250000000000000 3490 + 1.937500000000000 0.07500000000000001 3491 + 1.937500000000000 0.08750000000000001 3492 + 1.937500000000000 0.1000000000000000 3493 + 1.937500000000000 0.1125000000000000 3494 + 1.937500000000000 0.1250000000000000 3495 + 1.937500000000000 0.1375000000000000 3496 + 1.937500000000000 0.1500000000000000 3497 + 1.937500000000000 0.1625000000000000 3498 + 1.937500000000000 0.1750000000000000 3499 + 1.937500000000000 0.1875000000000000 3500 + 1.937500000000000 0.2000000000000000 3501 + 1.937500000000000 0.2125000000000000 3502 + 1.937500000000000 0.2250000000000000 3503 + 1.937500000000000 0.2375000000000000 3504 + 1.937500000000000 0.2500000000000000 3505 + 1.937500000000000 0.2625000000000000 3506 + 1.937500000000000 0.2750000000000000 3507 + 1.937500000000000 0.2875000000000000 3508 + 1.937500000000000 0.3000000000000000 3509 + 1.937500000000001 0.3125000000000000 3510 + 1.937500000000000 0.3249999999999999 3511 + 1.937500000000000 0.3375000000000000 3512 + 1.937499999999999 0.3500000000000000 3513 + 1.937500000000000 0.3625000000000002 3514 + 1.937500000000000 0.3750000000000000 3515 + 1.937500000000000 0.3875000000000000 3516 + 1.937500000000000 0.4000000000000000 3517 + 1.937500000000000 0.4125000000000000 3518 + 1.937500000000000 0.4250000000000000 3519 + 1.937500000000000 0.4375000000000001 3520 + 1.937500000000000 0.4499999999999999 3521 + 1.937500000000000 0.4625000000000000 3522 + 1.937500000000000 0.4750000000000001 3523 + 1.937500000000000 0.4875000000000001 3524 + 1.937500000000000 0.5000000000000000 3525 + 1.925000000000000 0.000000000000000 3526 + 1.925000000000000 0.01250000000000000 3527 + 1.925000000000000 0.02500000000000000 3528 + 1.925000000000000 0.03750000000000001 3529 + 1.925000000000000 0.05000000000000000 3530 + 1.925000000000000 0.06250000000000000 3531 + 1.925000000000000 0.07500000000000001 3532 + 1.925000000000000 0.08750000000000004 3533 + 1.925000000000000 0.1000000000000000 3534 + 1.925000000000000 0.1125000000000000 3535 + 1.925000000000000 0.1250000000000000 3536 + 1.925000000000000 0.1375000000000000 3537 + 1.925000000000000 0.1500000000000001 3538 + 1.925000000000000 0.1625000000000000 3539 + 1.925000000000000 0.1750000000000000 3540 + 1.925000000000000 0.1875000000000000 3541 + 1.925000000000000 0.2000000000000000 3542 + 1.925000000000000 0.2125000000000000 3543 + 1.925000000000001 0.2250000000000000 3544 + 1.925000000000000 0.2375000000000001 3545 + 1.925000000000000 0.2500000000000000 3546 + 1.925000000000000 0.2625000000000001 3547 + 1.925000000000000 0.2750000000000000 3548 + 1.925000000000000 0.2875000000000000 3549 + 1.925000000000000 0.3000000000000000 3550 + 1.925000000000000 0.3125000000000000 3551 + 1.925000000000000 0.3250000000000000 3552 + 1.925000000000000 0.3375000000000000 3553 + 1.925000000000000 0.3500000000000000 3554 + 1.925000000000000 0.3625000000000000 3555 + 1.925000000000000 0.3750000000000000 3556 + 1.925000000000000 0.3875000000000001 3557 + 1.925000000000000 0.4000000000000000 3558 + 1.925000000000000 0.4125000000000000 3559 + 1.925000000000000 0.4250000000000000 3560 + 1.924999999999999 0.4375000000000000 3561 + 1.924999999999999 0.4500000000000000 3562 + 1.924999999999999 0.4625000000000000 3563 + 1.925000000000000 0.4750000000000000 3564 + 1.925000000000000 0.4875000000000002 3565 + 1.925000000000000 0.5000000000000000 3566 + 1.912500000000000 0.000000000000000 3567 + 1.912500000000000 0.01250000000000000 3568 + 1.912500000000000 0.02500000000000000 3569 + 1.912500000000000 0.03749999999999999 3570 + 1.912500000000000 0.05000000000000000 3571 + 1.912500000000000 0.06250000000000000 3572 + 1.912500000000000 0.07500000000000001 3573 + 1.912500000000000 0.08750000000000004 3574 + 1.912500000000000 0.1000000000000000 3575 + 1.912500000000000 0.1125000000000000 3576 + 1.912500000000000 0.1250000000000000 3577 + 1.912500000000000 0.1375000000000000 3578 + 1.912500000000000 0.1500000000000000 3579 + 1.912500000000000 0.1625000000000000 3580 + 1.912500000000000 0.1750000000000000 3581 + 1.912500000000000 0.1874999999999999 3582 + 1.912500000000000 0.2000000000000000 3583 + 1.912500000000000 0.2125000000000000 3584 + 1.912500000000000 0.2250000000000000 3585 + 1.912500000000000 0.2375000000000000 3586 + 1.912500000000000 0.2500000000000000 3587 + 1.912500000000000 0.2625000000000000 3588 + 1.912500000000000 0.2750000000000000 3589 + 1.912500000000000 0.2875000000000000 3590 + 1.912500000000000 0.3000000000000000 3591 + 1.912500000000000 0.3125000000000000 3592 + 1.912500000000000 0.3250000000000001 3593 + 1.912500000000000 0.3375000000000000 3594 + 1.912500000000000 0.3500000000000000 3595 + 1.912500000000000 0.3625000000000000 3596 + 1.912500000000000 0.3750000000000000 3597 + 1.912500000000000 0.3875000000000000 3598 + 1.912500000000000 0.4000000000000000 3599 + 1.912500000000000 0.4125000000000000 3600 + 1.912500000000000 0.4250000000000000 3601 + 1.912500000000000 0.4375000000000000 3602 + 1.912500000000000 0.4500000000000001 3603 + 1.912500000000000 0.4625000000000001 3604 + 1.912500000000000 0.4750000000000000 3605 + 1.912500000000000 0.4875000000000000 3606 + 1.912500000000000 0.5000000000000000 3607 + 1.900000000000000 0.000000000000000 3608 + 1.900000000000000 0.01250000000000000 3609 + 1.900000000000000 0.02500000000000000 3610 + 1.900000000000000 0.03750000000000001 3611 + 1.900000000000000 0.05000000000000000 3612 + 1.900000000000000 0.06250000000000000 3613 + 1.900000000000000 0.07500000000000001 3614 + 1.900000000000000 0.08750000000000001 3615 + 1.900000000000001 0.1000000000000000 3616 + 1.900000000000000 0.1125000000000000 3617 + 1.900000000000000 0.1250000000000000 3618 + 1.900000000000000 0.1375000000000000 3619 + 1.900000000000000 0.1500000000000000 3620 + 1.900000000000000 0.1625000000000000 3621 + 1.900000000000000 0.1750000000000000 3622 + 1.900000000000000 0.1875000000000000 3623 + 1.900000000000000 0.2000000000000000 3624 + 1.900000000000000 0.2125000000000000 3625 + 1.900000000000000 0.2250000000000000 3626 + 1.900000000000000 0.2375000000000000 3627 + 1.900000000000000 0.2500000000000000 3628 + 1.900000000000000 0.2625000000000000 3629 + 1.900000000000000 0.2750000000000000 3630 + 1.900000000000000 0.2875000000000000 3631 + 1.900000000000000 0.3000000000000000 3632 + 1.900000000000000 0.3125000000000000 3633 + 1.900000000000000 0.3250000000000001 3634 + 1.900000000000000 0.3375000000000000 3635 + 1.900000000000000 0.3500000000000000 3636 + 1.900000000000000 0.3625000000000000 3637 + 1.900000000000000 0.3750000000000000 3638 + 1.900000000000000 0.3875000000000000 3639 + 1.900000000000000 0.4000000000000000 3640 + 1.900000000000000 0.4125000000000000 3641 + 1.900000000000000 0.4250000000000000 3642 + 1.900000000000000 0.4375000000000000 3643 + 1.900000000000000 0.4500000000000000 3644 + 1.900000000000000 0.4625000000000000 3645 + 1.900000000000000 0.4750000000000000 3646 + 1.899999999999999 0.4874999999999999 3647 + 1.900000000000000 0.5000000000000000 3648 + 1.887500000000000 0.000000000000000 3649 + 1.887500000000000 0.01250000000000000 3650 + 1.887500000000000 0.02500000000000000 3651 + 1.887500000000000 0.03750000000000001 3652 + 1.887500000000000 0.05000000000000000 3653 + 1.887500000000000 0.06250000000000000 3654 + 1.887500000000000 0.07500000000000001 3655 + 1.887500000000000 0.08750000000000001 3656 + 1.887500000000000 0.1000000000000000 3657 + 1.887500000000000 0.1125000000000000 3658 + 1.887500000000000 0.1250000000000000 3659 + 1.887500000000000 0.1375000000000000 3660 + 1.887500000000000 0.1500000000000000 3661 + 1.887500000000000 0.1625000000000000 3662 + 1.887500000000000 0.1750000000000000 3663 + 1.887500000000000 0.1875000000000000 3664 + 1.887500000000000 0.2000000000000000 3665 + 1.887500000000000 0.2125000000000000 3666 + 1.887500000000000 0.2250000000000000 3667 + 1.887500000000000 0.2375000000000000 3668 + 1.887500000000000 0.2500000000000000 3669 + 1.887500000000000 0.2625000000000000 3670 + 1.887500000000000 0.2750000000000000 3671 + 1.887500000000000 0.2875000000000000 3672 + 1.887500000000000 0.3000000000000000 3673 + 1.887500000000000 0.3125000000000000 3674 + 1.887500000000000 0.3250000000000000 3675 + 1.887500000000000 0.3375000000000000 3676 + 1.887500000000000 0.3500000000000000 3677 + 1.887500000000000 0.3625000000000000 3678 + 1.887500000000000 0.3750000000000000 3679 + 1.887500000000000 0.3875000000000000 3680 + 1.887500000000000 0.4000000000000000 3681 + 1.887500000000000 0.4125000000000000 3682 + 1.887500000000000 0.4250000000000000 3683 + 1.887500000000000 0.4375000000000000 3684 + 1.887500000000000 0.4500000000000000 3685 + 1.887500000000000 0.4625000000000000 3686 + 1.887500000000000 0.4750000000000000 3687 + 1.887500000000000 0.4875000000000000 3688 + 1.887500000000000 0.5000000000000000 3689 + 1.875000000000000 0.000000000000000 3690 + 1.875000000000000 0.01250000000000000 3691 + 1.875000000000000 0.02499999999999999 3692 + 1.875000000000000 0.03750000000000001 3693 + 1.875000000000000 0.05000000000000000 3694 + 1.875000000000000 0.06250000000000000 3695 + 1.875000000000000 0.07500000000000001 3696 + 1.875000000000000 0.08750000000000001 3697 + 1.875000000000000 0.1000000000000000 3698 + 1.875000000000000 0.1125000000000000 3699 + 1.875000000000000 0.1250000000000000 3700 + 1.875000000000000 0.1375000000000000 3701 + 1.875000000000000 0.1500000000000000 3702 + 1.875000000000000 0.1625000000000000 3703 + 1.875000000000000 0.1750000000000000 3704 + 1.875000000000000 0.1875000000000000 3705 + 1.875000000000000 0.2000000000000000 3706 + 1.875000000000000 0.2125000000000000 3707 + 1.875000000000000 0.2250000000000000 3708 + 1.875000000000000 0.2375000000000000 3709 + 1.875000000000000 0.2500000000000000 3710 + 1.875000000000000 0.2625000000000000 3711 + 1.875000000000000 0.2750000000000000 3712 + 1.875000000000000 0.2875000000000000 3713 + 1.875000000000000 0.3000000000000000 3714 + 1.875000000000000 0.3125000000000001 3715 + 1.875000000000000 0.3250000000000000 3716 + 1.875000000000000 0.3375000000000000 3717 + 1.875000000000000 0.3500000000000000 3718 + 1.875000000000000 0.3625000000000000 3719 + 1.875000000000000 0.3750000000000000 3720 + 1.875000000000000 0.3874999999999999 3721 + 1.875000000000000 0.3999999999999999 3722 + 1.875000000000000 0.4125000000000001 3723 + 1.875000000000000 0.4250000000000001 3724 + 1.874999999999999 0.4375000000000000 3725 + 1.874999999999999 0.4500000000000001 3726 + 1.874999999999999 0.4625000000000001 3727 + 1.875000000000000 0.4750000000000001 3728 + 1.875000000000000 0.4875000000000000 3729 + 1.875000000000000 0.5000000000000000 3730 + 1.862500000000000 0.000000000000000 3731 + 1.862500000000000 0.01250000000000000 3732 + 1.862500000000000 0.02500000000000000 3733 + 1.862500000000000 0.03750000000000001 3734 + 1.862500000000000 0.05000000000000000 3735 + 1.862500000000000 0.06250000000000000 3736 + 1.862500000000000 0.07500000000000001 3737 + 1.862500000000000 0.08750000000000001 3738 + 1.862500000000000 0.1000000000000000 3739 + 1.862500000000000 0.1125000000000000 3740 + 1.862500000000000 0.1250000000000000 3741 + 1.862500000000000 0.1375000000000000 3742 + 1.862500000000000 0.1500000000000000 3743 + 1.862500000000000 0.1625000000000000 3744 + 1.862500000000000 0.1750000000000000 3745 + 1.862500000000000 0.1875000000000000 3746 + 1.862500000000000 0.2000000000000000 3747 + 1.862500000000000 0.2125000000000000 3748 + 1.862500000000000 0.2250000000000000 3749 + 1.862500000000000 0.2375000000000000 3750 + 1.862500000000000 0.2500000000000000 3751 + 1.862500000000000 0.2625000000000000 3752 + 1.862500000000000 0.2750000000000000 3753 + 1.862500000000000 0.2875000000000000 3754 + 1.862500000000000 0.3000000000000000 3755 + 1.862500000000000 0.3125000000000000 3756 + 1.862500000000000 0.3250000000000000 3757 + 1.862500000000000 0.3375000000000000 3758 + 1.862500000000000 0.3500000000000000 3759 + 1.862500000000000 0.3625000000000000 3760 + 1.862500000000000 0.3750000000000000 3761 + 1.862500000000000 0.3875000000000000 3762 + 1.862500000000000 0.4000000000000000 3763 + 1.862500000000000 0.4125000000000000 3764 + 1.862500000000000 0.4250000000000000 3765 + 1.862500000000000 0.4375000000000000 3766 + 1.862500000000000 0.4500000000000001 3767 + 1.862500000000000 0.4625000000000000 3768 + 1.862500000000000 0.4750000000000001 3769 + 1.862500000000000 0.4875000000000000 3770 + 1.862500000000000 0.5000000000000000 3771 + 1.850000000000000 0.000000000000000 3772 + 1.850000000000000 0.01250000000000000 3773 + 1.850000000000000 0.02500000000000000 3774 + 1.850000000000000 0.03749999999999999 3775 + 1.850000000000000 0.04999999999999999 3776 + 1.850000000000000 0.06250000000000000 3777 + 1.850000000000000 0.07500000000000001 3778 + 1.850000000000000 0.08750000000000001 3779 + 1.850000000000000 0.1000000000000000 3780 + 1.850000000000000 0.1125000000000000 3781 + 1.850000000000000 0.1250000000000000 3782 + 1.850000000000000 0.1375000000000000 3783 + 1.850000000000000 0.1500000000000000 3784 + 1.850000000000000 0.1625000000000000 3785 + 1.849999999999999 0.1750000000000001 3786 + 1.850000000000000 0.1875000000000000 3787 + 1.850000000000000 0.2000000000000000 3788 + 1.850000000000000 0.2125000000000000 3789 + 1.850000000000000 0.2250000000000000 3790 + 1.850000000000000 0.2375000000000000 3791 + 1.850000000000000 0.2500000000000000 3792 + 1.850000000000000 0.2625000000000000 3793 + 1.850000000000000 0.2750000000000000 3794 + 1.850000000000000 0.2875000000000000 3795 + 1.850000000000000 0.3000000000000000 3796 + 1.850000000000000 0.3125000000000000 3797 + 1.850000000000000 0.3250000000000000 3798 + 1.850000000000000 0.3375000000000000 3799 + 1.850000000000000 0.3500000000000001 3800 + 1.850000000000000 0.3625000000000000 3801 + 1.850000000000000 0.3750000000000000 3802 + 1.850000000000000 0.3875000000000000 3803 + 1.850000000000000 0.4000000000000000 3804 + 1.850000000000000 0.4125000000000000 3805 + 1.850000000000000 0.4250000000000000 3806 + 1.850000000000000 0.4375000000000000 3807 + 1.850000000000000 0.4500000000000000 3808 + 1.850000000000000 0.4625000000000001 3809 + 1.849999999999999 0.4750000000000001 3810 + 1.849999999999999 0.4875000000000000 3811 + 1.850000000000000 0.5000000000000000 3812 + 1.837500000000000 0.000000000000000 3813 + 1.837500000000000 0.01250000000000000 3814 + 1.837500000000000 0.02500000000000000 3815 + 1.837500000000000 0.03750000000000001 3816 + 1.837500000000000 0.05000000000000000 3817 + 1.837500000000000 0.06250000000000000 3818 + 1.837500000000000 0.07500000000000001 3819 + 1.837500000000000 0.08749999999999999 3820 + 1.837500000000000 0.1000000000000000 3821 + 1.837500000000000 0.1125000000000000 3822 + 1.837500000000000 0.1250000000000000 3823 + 1.837500000000000 0.1375000000000000 3824 + 1.837500000000000 0.1500000000000000 3825 + 1.837500000000000 0.1625000000000000 3826 + 1.837500000000000 0.1750000000000000 3827 + 1.837500000000000 0.1875000000000000 3828 + 1.837500000000000 0.2000000000000000 3829 + 1.837500000000000 0.2125000000000000 3830 + 1.837500000000000 0.2250000000000000 3831 + 1.837500000000000 0.2375000000000000 3832 + 1.837500000000000 0.2500000000000000 3833 + 1.837500000000000 0.2625000000000000 3834 + 1.837500000000000 0.2750000000000000 3835 + 1.837500000000000 0.2875000000000000 3836 + 1.837500000000000 0.3000000000000000 3837 + 1.837500000000000 0.3125000000000000 3838 + 1.837500000000000 0.3250000000000000 3839 + 1.837500000000000 0.3375000000000000 3840 + 1.837500000000000 0.3500000000000001 3841 + 1.837500000000000 0.3625000000000000 3842 + 1.837500000000000 0.3750000000000000 3843 + 1.837500000000000 0.3875000000000000 3844 + 1.837500000000000 0.4000000000000000 3845 + 1.837500000000000 0.4125000000000000 3846 + 1.837500000000000 0.4250000000000000 3847 + 1.837500000000000 0.4375000000000000 3848 + 1.837500000000000 0.4500000000000000 3849 + 1.837500000000000 0.4625000000000001 3850 + 1.837500000000000 0.4750000000000001 3851 + 1.837500000000000 0.4875000000000000 3852 + 1.837500000000000 0.5000000000000000 3853 + 1.825000000000000 0.000000000000000 3854 + 1.825000000000000 0.01250000000000000 3855 + 1.825000000000000 0.02500000000000000 3856 + 1.825000000000000 0.03750000000000001 3857 + 1.825000000000000 0.05000000000000000 3858 + 1.825000000000000 0.06250000000000000 3859 + 1.825000000000000 0.07500000000000001 3860 + 1.825000000000000 0.08750000000000001 3861 + 1.825000000000000 0.09999999999999998 3862 + 1.825000000000000 0.1125000000000000 3863 + 1.825000000000000 0.1250000000000000 3864 + 1.825000000000000 0.1375000000000000 3865 + 1.825000000000000 0.1500000000000000 3866 + 1.825000000000000 0.1625000000000000 3867 + 1.825000000000000 0.1750000000000000 3868 + 1.825000000000000 0.1875000000000000 3869 + 1.825000000000000 0.2000000000000000 3870 + 1.825000000000000 0.2125000000000001 3871 + 1.825000000000000 0.2250000000000000 3872 + 1.825000000000000 0.2375000000000000 3873 + 1.825000000000000 0.2500000000000000 3874 + 1.825000000000000 0.2625000000000001 3875 + 1.825000000000000 0.2750000000000000 3876 + 1.825000000000000 0.2875000000000000 3877 + 1.825000000000000 0.3000000000000000 3878 + 1.825000000000000 0.3125000000000000 3879 + 1.825000000000000 0.3250000000000000 3880 + 1.825000000000000 0.3375000000000000 3881 + 1.825000000000000 0.3500000000000000 3882 + 1.825000000000000 0.3625000000000000 3883 + 1.825000000000000 0.3750000000000000 3884 + 1.825000000000000 0.3875000000000000 3885 + 1.825000000000000 0.4000000000000000 3886 + 1.825000000000000 0.4125000000000001 3887 + 1.825000000000000 0.4250000000000000 3888 + 1.825000000000000 0.4375000000000000 3889 + 1.825000000000000 0.4500000000000001 3890 + 1.825000000000000 0.4625000000000001 3891 + 1.825000000000000 0.4750000000000000 3892 + 1.825000000000000 0.4875000000000000 3893 + 1.825000000000000 0.5000000000000000 3894 + 1.812500000000000 0.000000000000000 3895 + 1.812500000000000 0.01250000000000000 3896 + 1.812500000000000 0.02499999999999999 3897 + 1.812500000000000 0.03750000000000001 3898 + 1.812500000000000 0.05000000000000000 3899 + 1.812500000000000 0.06250000000000000 3900 + 1.812500000000000 0.07500000000000001 3901 + 1.812500000000000 0.08750000000000001 3902 + 1.812500000000000 0.1000000000000000 3903 + 1.812500000000000 0.1125000000000000 3904 + 1.812500000000000 0.1250000000000000 3905 + 1.812500000000000 0.1375000000000000 3906 + 1.812500000000000 0.1500000000000000 3907 + 1.812500000000000 0.1625000000000000 3908 + 1.812500000000000 0.1750000000000000 3909 + 1.812500000000000 0.1875000000000000 3910 + 1.812500000000000 0.2000000000000000 3911 + 1.812500000000000 0.2125000000000000 3912 + 1.812500000000000 0.2250000000000000 3913 + 1.812500000000000 0.2375000000000000 3914 + 1.812500000000000 0.2500000000000000 3915 + 1.812500000000000 0.2625000000000000 3916 + 1.812500000000000 0.2750000000000000 3917 + 1.812500000000000 0.2875000000000000 3918 + 1.812500000000000 0.3000000000000000 3919 + 1.812500000000000 0.3125000000000000 3920 + 1.812500000000000 0.3250000000000000 3921 + 1.812500000000000 0.3375000000000000 3922 + 1.812500000000000 0.3500000000000000 3923 + 1.812500000000000 0.3625000000000000 3924 + 1.812500000000000 0.3750000000000000 3925 + 1.812500000000000 0.3875000000000000 3926 + 1.812500000000000 0.3999999999999999 3927 + 1.812500000000000 0.4125000000000000 3928 + 1.812500000000000 0.4250000000000000 3929 + 1.812500000000000 0.4375000000000000 3930 + 1.812500000000000 0.4500000000000001 3931 + 1.812500000000000 0.4625000000000001 3932 + 1.812500000000000 0.4750000000000000 3933 + 1.812500000000000 0.4875000000000000 3934 + 1.812500000000000 0.5000000000000000 3935 + 1.800000000000000 0.000000000000000 3936 + 1.800000000000000 0.01250000000000000 3937 + 1.800000000000000 0.02500000000000000 3938 + 1.800000000000000 0.03750000000000001 3939 + 1.800000000000000 0.05000000000000000 3940 + 1.800000000000000 0.06250000000000000 3941 + 1.800000000000001 0.07500000000000001 3942 + 1.800000000000000 0.08750000000000001 3943 + 1.800000000000000 0.1000000000000000 3944 + 1.800000000000000 0.1125000000000000 3945 + 1.800000000000000 0.1250000000000000 3946 + 1.800000000000000 0.1375000000000000 3947 + 1.800000000000000 0.1500000000000000 3948 + 1.800000000000000 0.1625000000000000 3949 + 1.800000000000000 0.1750000000000000 3950 + 1.800000000000000 0.1875000000000000 3951 + 1.800000000000000 0.2000000000000000 3952 + 1.800000000000000 0.2125000000000000 3953 + 1.800000000000000 0.2250000000000001 3954 + 1.800000000000000 0.2375000000000000 3955 + 1.800000000000000 0.2500000000000000 3956 + 1.800000000000000 0.2625000000000001 3957 + 1.800000000000000 0.2750000000000000 3958 + 1.800000000000000 0.2875000000000000 3959 + 1.800000000000000 0.3000000000000000 3960 + 1.800000000000000 0.3125000000000000 3961 + 1.800000000000000 0.3250000000000000 3962 + 1.800000000000000 0.3374999999999999 3963 + 1.800000000000000 0.3500000000000000 3964 + 1.800000000000000 0.3625000000000002 3965 + 1.800000000000000 0.3750000000000000 3966 + 1.800000000000000 0.3875000000000001 3967 + 1.800000000000000 0.4000000000000000 3968 + 1.800000000000000 0.4125000000000000 3969 + 1.800000000000000 0.4250000000000000 3970 + 1.800000000000000 0.4375000000000000 3971 + 1.800000000000000 0.4500000000000000 3972 + 1.800000000000000 0.4625000000000000 3973 + 1.799999999999999 0.4750000000000000 3974 + 1.799999999999999 0.4875000000000002 3975 + 1.800000000000000 0.5000000000000000 3976 + 1.787500000000000 0.000000000000000 3977 + 1.787500000000000 0.01250000000000000 3978 + 1.787500000000000 0.02500000000000001 3979 + 1.787500000000000 0.03750000000000001 3980 + 1.787500000000000 0.05000000000000000 3981 + 1.787500000000000 0.06250000000000000 3982 + 1.787500000000000 0.07500000000000001 3983 + 1.787500000000000 0.08750000000000004 3984 + 1.787500000000000 0.1000000000000000 3985 + 1.787500000000000 0.1125000000000000 3986 + 1.787500000000000 0.1250000000000000 3987 + 1.787500000000000 0.1375000000000000 3988 + 1.787500000000000 0.1500000000000000 3989 + 1.787500000000000 0.1625000000000000 3990 + 1.787500000000000 0.1750000000000000 3991 + 1.787500000000000 0.1875000000000000 3992 + 1.787500000000000 0.2000000000000000 3993 + 1.787500000000001 0.2125000000000000 3994 + 1.787500000000001 0.2250000000000000 3995 + 1.787500000000000 0.2375000000000001 3996 + 1.787500000000000 0.2500000000000000 3997 + 1.787500000000000 0.2625000000000000 3998 + 1.787500000000000 0.2750000000000000 3999 + 1.787500000000000 0.2875000000000000 4000 + 1.787500000000000 0.3000000000000000 4001 + 1.787499999999999 0.3125000000000000 4002 + 1.787500000000000 0.3250000000000000 4003 + 1.787500000000000 0.3375000000000000 4004 + 1.787500000000000 0.3500000000000000 4005 + 1.787500000000000 0.3625000000000000 4006 + 1.787500000000000 0.3750000000000000 4007 + 1.787500000000000 0.3875000000000001 4008 + 1.787500000000000 0.4000000000000000 4009 + 1.787500000000000 0.4124999999999999 4010 + 1.787500000000000 0.4250000000000000 4011 + 1.787500000000000 0.4375000000000001 4012 + 1.787500000000000 0.4500000000000000 4013 + 1.787499999999999 0.4625000000000000 4014 + 1.787500000000000 0.4750000000000001 4015 + 1.787500000000000 0.4875000000000000 4016 + 1.787500000000000 0.5000000000000000 4017 + 1.775000000000000 0.000000000000000 4018 + 1.775000000000000 0.01250000000000000 4019 + 1.775000000000000 0.02499999999999999 4020 + 1.775000000000000 0.03750000000000001 4021 + 1.775000000000000 0.05000000000000000 4022 + 1.775000000000000 0.06250000000000000 4023 + 1.775000000000000 0.07500000000000001 4024 + 1.775000000000000 0.08750000000000004 4025 + 1.775000000000000 0.1000000000000000 4026 + 1.775000000000000 0.1125000000000000 4027 + 1.775000000000000 0.1250000000000000 4028 + 1.775000000000000 0.1375000000000000 4029 + 1.775000000000000 0.1500000000000000 4030 + 1.774999999999999 0.1625000000000000 4031 + 1.775000000000000 0.1750000000000000 4032 + 1.775000000000000 0.1875000000000000 4033 + 1.774999999999999 0.2000000000000000 4034 + 1.774999999999999 0.2125000000000000 4035 + 1.774999999999999 0.2250000000000000 4036 + 1.775000000000000 0.2375000000000000 4037 + 1.775000000000000 0.2500000000000000 4038 + 1.775000000000000 0.2625000000000000 4039 + 1.775000000000000 0.2750000000000000 4040 + 1.775000000000000 0.2875000000000000 4041 + 1.775000000000000 0.3000000000000000 4042 + 1.775000000000000 0.3125000000000000 4043 + 1.775000000000000 0.3249999999999999 4044 + 1.775000000000000 0.3375000000000000 4045 + 1.775000000000000 0.3499999999999999 4046 + 1.775000000000000 0.3625000000000000 4047 + 1.775000000000000 0.3750000000000000 4048 + 1.775000000000000 0.3875000000000000 4049 + 1.775000000000000 0.4000000000000000 4050 + 1.775000000000000 0.4125000000000001 4051 + 1.775000000000000 0.4250000000000000 4052 + 1.775000000000000 0.4374999999999999 4053 + 1.774999999999999 0.4500000000000001 4054 + 1.774999999999999 0.4625000000000000 4055 + 1.774999999999999 0.4750000000000001 4056 + 1.774999999999999 0.4874999999999999 4057 + 1.775000000000000 0.5000000000000000 4058 + 1.762500000000000 0.000000000000000 4059 + 1.762500000000000 0.01250000000000000 4060 + 1.762500000000000 0.02500000000000000 4061 + 1.762500000000000 0.03750000000000001 4062 + 1.762500000000000 0.05000000000000000 4063 + 1.762500000000000 0.06250000000000000 4064 + 1.762500000000000 0.07500000000000001 4065 + 1.762500000000000 0.08749999999999999 4066 + 1.762500000000000 0.09999999999999998 4067 + 1.762500000000000 0.1125000000000000 4068 + 1.762500000000000 0.1250000000000000 4069 + 1.762500000000000 0.1375000000000000 4070 + 1.762500000000000 0.1500000000000000 4071 + 1.762500000000000 0.1625000000000000 4072 + 1.762500000000000 0.1750000000000000 4073 + 1.762500000000000 0.1875000000000000 4074 + 1.762500000000000 0.2000000000000000 4075 + 1.762500000000000 0.2125000000000000 4076 + 1.762500000000000 0.2250000000000000 4077 + 1.762500000000000 0.2375000000000000 4078 + 1.762500000000000 0.2500000000000000 4079 + 1.762500000000000 0.2625000000000001 4080 + 1.762500000000000 0.2750000000000000 4081 + 1.762500000000000 0.2875000000000000 4082 + 1.762500000000000 0.3000000000000000 4083 + 1.762500000000000 0.3125000000000000 4084 + 1.762499999999999 0.3250000000000000 4085 + 1.762500000000000 0.3375000000000000 4086 + 1.762499999999999 0.3500000000000000 4087 + 1.762500000000000 0.3625000000000000 4088 + 1.762500000000000 0.3750000000000000 4089 + 1.762500000000000 0.3875000000000000 4090 + 1.762500000000000 0.4000000000000000 4091 + 1.762500000000000 0.4125000000000001 4092 + 1.762500000000000 0.4250000000000000 4093 + 1.762500000000000 0.4375000000000000 4094 + 1.762500000000000 0.4500000000000000 4095 + 1.762500000000000 0.4625000000000001 4096 + 1.762500000000000 0.4750000000000000 4097 + 1.762500000000000 0.4875000000000002 4098 + 1.762500000000000 0.5000000000000000 4099 + 1.750000000000000 0.000000000000000 4100 + 1.750000000000000 0.01250000000000000 4101 + 1.750000000000000 0.02500000000000000 4102 + 1.750000000000000 0.03750000000000001 4103 + 1.750000000000000 0.05000000000000000 4104 + 1.750000000000000 0.06250000000000000 4105 + 1.750000000000000 0.07500000000000001 4106 + 1.750000000000000 0.08750000000000001 4107 + 1.750000000000000 0.1000000000000000 4108 + 1.750000000000000 0.1125000000000000 4109 + 1.750000000000000 0.1250000000000000 4110 + 1.750000000000000 0.1375000000000000 4111 + 1.750000000000000 0.1500000000000000 4112 + 1.750000000000000 0.1625000000000000 4113 + 1.749999999999999 0.1750000000000000 4114 + 1.750000000000000 0.1875000000000000 4115 + 1.750000000000000 0.2000000000000000 4116 + 1.750000000000000 0.2125000000000000 4117 + 1.750000000000000 0.2250000000000000 4118 + 1.750000000000000 0.2375000000000000 4119 + 1.750000000000000 0.2500000000000000 4120 + 1.750000000000000 0.2625000000000000 4121 + 1.750000000000000 0.2750000000000000 4122 + 1.750000000000000 0.2875000000000000 4123 + 1.750000000000000 0.3000000000000000 4124 + 1.750000000000000 0.3125000000000000 4125 + 1.750000000000000 0.3250000000000000 4126 + 1.750000000000000 0.3375000000000000 4127 + 1.750000000000000 0.3500000000000000 4128 + 1.750000000000000 0.3625000000000000 4129 + 1.750000000000000 0.3750000000000000 4130 + 1.750000000000000 0.3875000000000000 4131 + 1.750000000000000 0.3999999999999999 4132 + 1.750000000000000 0.4125000000000000 4133 + 1.750000000000000 0.4250000000000000 4134 + 1.750000000000000 0.4375000000000000 4135 + 1.749999999999999 0.4500000000000000 4136 + 1.750000000000000 0.4625000000000000 4137 + 1.750000000000000 0.4750000000000001 4138 + 1.750000000000000 0.4875000000000000 4139 + 1.750000000000000 0.5000000000000000 4140 + 1.737500000000000 0.000000000000000 4141 + 1.737500000000000 0.01250000000000000 4142 + 1.737500000000000 0.02500000000000000 4143 + 1.737500000000000 0.03750000000000001 4144 + 1.737500000000000 0.05000000000000000 4145 + 1.737500000000000 0.06250000000000000 4146 + 1.737500000000000 0.07500000000000001 4147 + 1.737500000000000 0.08750000000000002 4148 + 1.737500000000000 0.1000000000000000 4149 + 1.737500000000000 0.1125000000000000 4150 + 1.737500000000000 0.1250000000000000 4151 + 1.737500000000000 0.1375000000000000 4152 + 1.737500000000000 0.1500000000000000 4153 + 1.737500000000000 0.1625000000000000 4154 + 1.737500000000000 0.1750000000000000 4155 + 1.737500000000000 0.1875000000000000 4156 + 1.737500000000000 0.2000000000000000 4157 + 1.737500000000000 0.2125000000000000 4158 + 1.737500000000001 0.2250000000000000 4159 + 1.737500000000000 0.2375000000000000 4160 + 1.737500000000000 0.2500000000000000 4161 + 1.737500000000000 0.2625000000000000 4162 + 1.737500000000000 0.2750000000000000 4163 + 1.737500000000000 0.2875000000000000 4164 + 1.737500000000000 0.3000000000000000 4165 + 1.737500000000000 0.3125000000000000 4166 + 1.737500000000000 0.3250000000000000 4167 + 1.737500000000000 0.3375000000000000 4168 + 1.737500000000000 0.3500000000000001 4169 + 1.737500000000000 0.3625000000000000 4170 + 1.737500000000000 0.3750000000000000 4171 + 1.737500000000000 0.3875000000000000 4172 + 1.737500000000000 0.4000000000000000 4173 + 1.737500000000000 0.4125000000000000 4174 + 1.737500000000000 0.4250000000000000 4175 + 1.737500000000000 0.4375000000000000 4176 + 1.737500000000000 0.4500000000000001 4177 + 1.737500000000000 0.4625000000000000 4178 + 1.737500000000000 0.4750000000000001 4179 + 1.737500000000000 0.4874999999999999 4180 + 1.737500000000000 0.5000000000000000 4181 + 1.725000000000000 0.000000000000000 4182 + 1.725000000000000 0.01250000000000000 4183 + 1.725000000000000 0.02500000000000000 4184 + 1.725000000000000 0.03750000000000001 4185 + 1.725000000000000 0.05000000000000000 4186 + 1.725000000000000 0.06250000000000000 4187 + 1.725000000000000 0.07500000000000001 4188 + 1.725000000000000 0.08749999999999998 4189 + 1.725000000000000 0.1000000000000000 4190 + 1.725000000000000 0.1125000000000000 4191 + 1.725000000000000 0.1250000000000000 4192 + 1.725000000000000 0.1375000000000000 4193 + 1.725000000000000 0.1500000000000000 4194 + 1.725000000000000 0.1625000000000000 4195 + 1.725000000000000 0.1750000000000000 4196 + 1.725000000000000 0.1875000000000000 4197 + 1.725000000000000 0.2000000000000000 4198 + 1.725000000000000 0.2125000000000000 4199 + 1.725000000000000 0.2250000000000000 4200 + 1.725000000000000 0.2375000000000000 4201 + 1.725000000000000 0.2500000000000000 4202 + 1.725000000000000 0.2625000000000000 4203 + 1.725000000000000 0.2750000000000000 4204 + 1.725000000000000 0.2875000000000000 4205 + 1.725000000000000 0.3000000000000000 4206 + 1.725000000000000 0.3125000000000000 4207 + 1.725000000000000 0.3250000000000000 4208 + 1.725000000000000 0.3375000000000000 4209 + 1.725000000000000 0.3500000000000001 4210 + 1.725000000000001 0.3625000000000000 4211 + 1.725000000000001 0.3750000000000000 4212 + 1.725000000000001 0.3875000000000000 4213 + 1.725000000000000 0.4000000000000000 4214 + 1.725000000000000 0.4125000000000001 4215 + 1.725000000000000 0.4250000000000000 4216 + 1.725000000000000 0.4375000000000000 4217 + 1.725000000000000 0.4500000000000000 4218 + 1.724999999999999 0.4625000000000000 4219 + 1.725000000000000 0.4750000000000000 4220 + 1.725000000000000 0.4875000000000001 4221 + 1.725000000000000 0.5000000000000000 4222 + 1.712500000000000 0.000000000000000 4223 + 1.712500000000000 0.01250000000000000 4224 + 1.712500000000000 0.02499999999999999 4225 + 1.712500000000000 0.03750000000000001 4226 + 1.712500000000000 0.05000000000000000 4227 + 1.712500000000000 0.06250000000000000 4228 + 1.712500000000000 0.07500000000000001 4229 + 1.712500000000000 0.08749999999999998 4230 + 1.712500000000000 0.1000000000000000 4231 + 1.712500000000000 0.1125000000000000 4232 + 1.712500000000000 0.1250000000000000 4233 + 1.712500000000000 0.1375000000000000 4234 + 1.712500000000000 0.1500000000000000 4235 + 1.712500000000000 0.1625000000000000 4236 + 1.712500000000000 0.1750000000000000 4237 + 1.712500000000000 0.1875000000000000 4238 + 1.712500000000000 0.2000000000000000 4239 + 1.712500000000000 0.2125000000000000 4240 + 1.712500000000000 0.2250000000000000 4241 + 1.712500000000000 0.2375000000000001 4242 + 1.712500000000000 0.2500000000000000 4243 + 1.712500000000000 0.2625000000000000 4244 + 1.712500000000000 0.2750000000000000 4245 + 1.712500000000000 0.2875000000000000 4246 + 1.712500000000000 0.3000000000000000 4247 + 1.712500000000000 0.3125000000000000 4248 + 1.712500000000000 0.3250000000000000 4249 + 1.712499999999999 0.3375000000000000 4250 + 1.712499999999999 0.3500000000000001 4251 + 1.712499999999999 0.3625000000000000 4252 + 1.712500000000000 0.3750000000000000 4253 + 1.712500000000000 0.3875000000000001 4254 + 1.712500000000000 0.4000000000000000 4255 + 1.712500000000000 0.4125000000000000 4256 + 1.712500000000000 0.4250000000000000 4257 + 1.712500000000000 0.4375000000000000 4258 + 1.712500000000000 0.4500000000000000 4259 + 1.712500000000000 0.4625000000000000 4260 + 1.712500000000000 0.4750000000000001 4261 + 1.712500000000000 0.4875000000000000 4262 + 1.712500000000000 0.5000000000000000 4263 + 1.700000000000000 0.000000000000000 4264 + 1.700000000000000 0.01250000000000000 4265 + 1.700000000000000 0.02500000000000000 4266 + 1.700000000000000 0.03750000000000001 4267 + 1.700000000000000 0.05000000000000000 4268 + 1.700000000000000 0.06250000000000000 4269 + 1.700000000000000 0.07500000000000001 4270 + 1.700000000000000 0.08750000000000001 4271 + 1.700000000000000 0.1000000000000000 4272 + 1.700000000000000 0.1125000000000000 4273 + 1.700000000000000 0.1250000000000000 4274 + 1.700000000000000 0.1375000000000000 4275 + 1.700000000000000 0.1500000000000000 4276 + 1.700000000000000 0.1625000000000000 4277 + 1.700000000000000 0.1750000000000000 4278 + 1.700000000000000 0.1875000000000000 4279 + 1.700000000000000 0.2000000000000000 4280 + 1.700000000000000 0.2125000000000000 4281 + 1.700000000000000 0.2250000000000000 4282 + 1.700000000000000 0.2375000000000000 4283 + 1.700000000000000 0.2500000000000000 4284 + 1.700000000000000 0.2625000000000000 4285 + 1.700000000000000 0.2750000000000000 4286 + 1.700000000000000 0.2875000000000000 4287 + 1.700000000000000 0.3000000000000000 4288 + 1.700000000000000 0.3125000000000000 4289 + 1.700000000000000 0.3250000000000000 4290 + 1.700000000000000 0.3375000000000000 4291 + 1.700000000000000 0.3500000000000001 4292 + 1.700000000000000 0.3625000000000000 4293 + 1.700000000000000 0.3750000000000000 4294 + 1.700000000000000 0.3874999999999999 4295 + 1.700000000000000 0.4000000000000000 4296 + 1.700000000000000 0.4125000000000000 4297 + 1.700000000000000 0.4250000000000000 4298 + 1.700000000000000 0.4375000000000000 4299 + 1.700000000000000 0.4500000000000001 4300 + 1.700000000000000 0.4625000000000000 4301 + 1.700000000000000 0.4750000000000000 4302 + 1.700000000000000 0.4874999999999999 4303 + 1.700000000000000 0.5000000000000000 4304 + 1.687500000000000 0.000000000000000 4305 + 1.687500000000000 0.01250000000000000 4306 + 1.687500000000000 0.02500000000000000 4307 + 1.687500000000000 0.03750000000000001 4308 + 1.687500000000000 0.04999999999999999 4309 + 1.687500000000000 0.06250000000000000 4310 + 1.687500000000000 0.07500000000000001 4311 + 1.687500000000000 0.08750000000000001 4312 + 1.687500000000000 0.1000000000000000 4313 + 1.687500000000000 0.1125000000000000 4314 + 1.687500000000000 0.1250000000000000 4315 + 1.687500000000000 0.1375000000000000 4316 + 1.687500000000000 0.1500000000000000 4317 + 1.687500000000000 0.1625000000000000 4318 + 1.687500000000000 0.1750000000000000 4319 + 1.687500000000000 0.1875000000000000 4320 + 1.687500000000000 0.2000000000000000 4321 + 1.687500000000000 0.2125000000000000 4322 + 1.687500000000000 0.2250000000000000 4323 + 1.687500000000000 0.2375000000000000 4324 + 1.687500000000000 0.2500000000000000 4325 + 1.687500000000000 0.2625000000000000 4326 + 1.687500000000000 0.2750000000000000 4327 + 1.687500000000000 0.2875000000000000 4328 + 1.687500000000000 0.3000000000000000 4329 + 1.687500000000000 0.3125000000000000 4330 + 1.687500000000000 0.3250000000000000 4331 + 1.687500000000000 0.3374999999999999 4332 + 1.687500000000000 0.3500000000000000 4333 + 1.687500000000000 0.3625000000000000 4334 + 1.687500000000000 0.3750000000000000 4335 + 1.687500000000000 0.3875000000000000 4336 + 1.687500000000000 0.3999999999999999 4337 + 1.687500000000000 0.4125000000000001 4338 + 1.687500000000000 0.4250000000000000 4339 + 1.687500000000000 0.4375000000000000 4340 + 1.687500000000000 0.4500000000000000 4341 + 1.687500000000000 0.4625000000000000 4342 + 1.687500000000000 0.4750000000000000 4343 + 1.687500000000000 0.4875000000000001 4344 + 1.687500000000000 0.5000000000000000 4345 + 1.675000000000000 0.000000000000000 4346 + 1.675000000000000 0.01250000000000000 4347 + 1.675000000000000 0.02500000000000000 4348 + 1.675000000000000 0.03750000000000001 4349 + 1.675000000000000 0.05000000000000000 4350 + 1.675000000000000 0.06250000000000000 4351 + 1.675000000000000 0.07500000000000001 4352 + 1.675000000000000 0.08750000000000001 4353 + 1.675000000000000 0.1000000000000000 4354 + 1.675000000000001 0.1125000000000000 4355 + 1.675000000000000 0.1250000000000000 4356 + 1.675000000000000 0.1375000000000000 4357 + 1.675000000000000 0.1500000000000000 4358 + 1.675000000000000 0.1625000000000000 4359 + 1.675000000000000 0.1750000000000000 4360 + 1.675000000000000 0.1875000000000000 4361 + 1.675000000000000 0.2000000000000000 4362 + 1.675000000000000 0.2125000000000000 4363 + 1.675000000000000 0.2250000000000000 4364 + 1.675000000000000 0.2375000000000000 4365 + 1.675000000000000 0.2500000000000000 4366 + 1.675000000000000 0.2625000000000000 4367 + 1.675000000000000 0.2750000000000000 4368 + 1.675000000000000 0.2875000000000000 4369 + 1.675000000000000 0.3000000000000000 4370 + 1.675000000000000 0.3125000000000000 4371 + 1.675000000000000 0.3250000000000001 4372 + 1.675000000000000 0.3375000000000000 4373 + 1.675000000000000 0.3500000000000001 4374 + 1.675000000000000 0.3625000000000000 4375 + 1.675000000000001 0.3750000000000000 4376 + 1.675000000000000 0.3875000000000000 4377 + 1.675000000000000 0.4000000000000000 4378 + 1.675000000000000 0.4125000000000001 4379 + 1.675000000000000 0.4250000000000000 4380 + 1.675000000000000 0.4375000000000000 4381 + 1.675000000000000 0.4500000000000001 4382 + 1.675000000000000 0.4625000000000000 4383 + 1.675000000000000 0.4750000000000000 4384 + 1.675000000000000 0.4875000000000000 4385 + 1.675000000000000 0.5000000000000000 4386 + 1.662500000000000 0.000000000000000 4387 + 1.662500000000000 0.01250000000000000 4388 + 1.662500000000001 0.02500000000000000 4389 + 1.662500000000000 0.03750000000000001 4390 + 1.662500000000000 0.05000000000000002 4391 + 1.662500000000000 0.06250000000000000 4392 + 1.662500000000000 0.07500000000000001 4393 + 1.662500000000000 0.08750000000000002 4394 + 1.662500000000000 0.1000000000000000 4395 + 1.662500000000000 0.1125000000000000 4396 + 1.662500000000000 0.1250000000000000 4397 + 1.662500000000000 0.1375000000000000 4398 + 1.662500000000000 0.1500000000000000 4399 + 1.662500000000000 0.1625000000000000 4400 + 1.662500000000000 0.1750000000000000 4401 + 1.662500000000000 0.1875000000000000 4402 + 1.662500000000000 0.2000000000000000 4403 + 1.662500000000000 0.2125000000000000 4404 + 1.662500000000001 0.2250000000000000 4405 + 1.662500000000001 0.2375000000000000 4406 + 1.662500000000001 0.2500000000000000 4407 + 1.662500000000000 0.2625000000000000 4408 + 1.662500000000000 0.2750000000000000 4409 + 1.662500000000000 0.2875000000000000 4410 + 1.662500000000000 0.3000000000000000 4411 + 1.662500000000000 0.3125000000000000 4412 + 1.662500000000000 0.3250000000000000 4413 + 1.662500000000000 0.3375000000000000 4414 + 1.662500000000000 0.3500000000000001 4415 + 1.662500000000000 0.3625000000000000 4416 + 1.662500000000000 0.3750000000000000 4417 + 1.662500000000000 0.3875000000000000 4418 + 1.662500000000000 0.4000000000000000 4419 + 1.662500000000000 0.4125000000000001 4420 + 1.662500000000000 0.4250000000000000 4421 + 1.662500000000000 0.4375000000000000 4422 + 1.662500000000000 0.4500000000000001 4423 + 1.662500000000000 0.4625000000000000 4424 + 1.662500000000000 0.4750000000000001 4425 + 1.662500000000000 0.4874999999999999 4426 + 1.662500000000000 0.5000000000000000 4427 + 1.650000000000000 0.000000000000000 4428 + 1.650000000000000 0.01250000000000000 4429 + 1.650000000000000 0.02500000000000000 4430 + 1.650000000000000 0.03750000000000001 4431 + 1.650000000000000 0.05000000000000000 4432 + 1.650000000000000 0.06250000000000000 4433 + 1.650000000000000 0.07500000000000001 4434 + 1.650000000000000 0.08750000000000004 4435 + 1.650000000000000 0.1000000000000000 4436 + 1.650000000000000 0.1125000000000000 4437 + 1.650000000000000 0.1250000000000000 4438 + 1.650000000000001 0.1375000000000000 4439 + 1.650000000000000 0.1500000000000000 4440 + 1.650000000000001 0.1625000000000000 4441 + 1.650000000000000 0.1750000000000000 4442 + 1.650000000000000 0.1875000000000001 4443 + 1.650000000000000 0.2000000000000000 4444 + 1.650000000000000 0.2125000000000000 4445 + 1.650000000000000 0.2250000000000000 4446 + 1.650000000000000 0.2375000000000000 4447 + 1.650000000000000 0.2500000000000000 4448 + 1.650000000000000 0.2625000000000000 4449 + 1.650000000000000 0.2750000000000000 4450 + 1.650000000000000 0.2875000000000000 4451 + 1.650000000000000 0.3000000000000000 4452 + 1.650000000000000 0.3125000000000000 4453 + 1.650000000000000 0.3250000000000001 4454 + 1.650000000000000 0.3375000000000000 4455 + 1.650000000000000 0.3500000000000000 4456 + 1.650000000000000 0.3625000000000000 4457 + 1.650000000000000 0.3750000000000000 4458 + 1.650000000000000 0.3875000000000000 4459 + 1.650000000000000 0.4000000000000000 4460 + 1.650000000000001 0.4125000000000000 4461 + 1.650000000000000 0.4250000000000000 4462 + 1.650000000000000 0.4375000000000001 4463 + 1.650000000000000 0.4500000000000000 4464 + 1.650000000000000 0.4625000000000000 4465 + 1.650000000000000 0.4750000000000000 4466 + 1.650000000000000 0.4875000000000000 4467 + 1.650000000000000 0.5000000000000000 4468 + 1.637500000000000 0.000000000000000 4469 + 1.637500000000000 0.01250000000000000 4470 + 1.637500000000000 0.02500000000000000 4471 + 1.637500000000000 0.03750000000000001 4472 + 1.637500000000000 0.05000000000000000 4473 + 1.637500000000000 0.06250000000000000 4474 + 1.637500000000000 0.07500000000000001 4475 + 1.637500000000000 0.08750000000000001 4476 + 1.637500000000000 0.1000000000000000 4477 + 1.637500000000000 0.1125000000000000 4478 + 1.637500000000000 0.1250000000000000 4479 + 1.637500000000000 0.1375000000000000 4480 + 1.637500000000000 0.1500000000000000 4481 + 1.637500000000000 0.1625000000000000 4482 + 1.637500000000000 0.1750000000000000 4483 + 1.637500000000000 0.1875000000000000 4484 + 1.637500000000000 0.2000000000000000 4485 + 1.637500000000000 0.2125000000000000 4486 + 1.637500000000000 0.2250000000000000 4487 + 1.637500000000000 0.2375000000000001 4488 + 1.637500000000000 0.2500000000000000 4489 + 1.637500000000000 0.2625000000000000 4490 + 1.637500000000000 0.2750000000000000 4491 + 1.637500000000000 0.2875000000000000 4492 + 1.637500000000000 0.3000000000000000 4493 + 1.637500000000000 0.3125000000000000 4494 + 1.637500000000000 0.3250000000000000 4495 + 1.637500000000000 0.3375000000000000 4496 + 1.637500000000000 0.3499999999999999 4497 + 1.637500000000000 0.3624999999999999 4498 + 1.637500000000000 0.3750000000000000 4499 + 1.637500000000000 0.3875000000000000 4500 + 1.637500000000000 0.4000000000000000 4501 + 1.637500000000000 0.4125000000000001 4502 + 1.637500000000000 0.4250000000000001 4503 + 1.637500000000000 0.4375000000000000 4504 + 1.637500000000000 0.4499999999999999 4505 + 1.637500000000000 0.4625000000000000 4506 + 1.637500000000000 0.4750000000000001 4507 + 1.637500000000000 0.4875000000000000 4508 + 1.637500000000000 0.5000000000000000 4509 + 1.625000000000000 0.000000000000000 4510 + 1.625000000000000 0.01250000000000000 4511 + 1.625000000000000 0.02500000000000000 4512 + 1.625000000000000 0.03750000000000001 4513 + 1.625000000000000 0.05000000000000000 4514 + 1.625000000000000 0.06250000000000000 4515 + 1.625000000000000 0.07500000000000001 4516 + 1.625000000000000 0.08750000000000002 4517 + 1.625000000000000 0.1000000000000000 4518 + 1.625000000000000 0.1125000000000000 4519 + 1.625000000000000 0.1250000000000000 4520 + 1.625000000000000 0.1375000000000000 4521 + 1.625000000000000 0.1500000000000000 4522 + 1.625000000000000 0.1625000000000000 4523 + 1.625000000000000 0.1750000000000000 4524 + 1.625000000000000 0.1875000000000000 4525 + 1.625000000000000 0.2000000000000000 4526 + 1.625000000000000 0.2125000000000000 4527 + 1.625000000000000 0.2250000000000000 4528 + 1.625000000000000 0.2375000000000000 4529 + 1.625000000000000 0.2500000000000000 4530 + 1.625000000000000 0.2625000000000000 4531 + 1.625000000000000 0.2750000000000000 4532 + 1.625000000000000 0.2875000000000000 4533 + 1.625000000000000 0.3000000000000000 4534 + 1.625000000000000 0.3125000000000000 4535 + 1.625000000000000 0.3250000000000000 4536 + 1.625000000000000 0.3375000000000000 4537 + 1.625000000000000 0.3499999999999999 4538 + 1.625000000000000 0.3625000000000000 4539 + 1.625000000000000 0.3750000000000000 4540 + 1.625000000000000 0.3875000000000000 4541 + 1.625000000000000 0.4000000000000000 4542 + 1.625000000000000 0.4125000000000001 4543 + 1.625000000000001 0.4250000000000000 4544 + 1.625000000000001 0.4375000000000000 4545 + 1.625000000000000 0.4500000000000001 4546 + 1.625000000000000 0.4625000000000000 4547 + 1.625000000000000 0.4750000000000001 4548 + 1.625000000000000 0.4875000000000000 4549 + 1.625000000000000 0.5000000000000000 4550 + 1.612500000000000 0.000000000000000 4551 + 1.612500000000000 0.01250000000000000 4552 + 1.612500000000000 0.02500000000000000 4553 + 1.612500000000000 0.03750000000000001 4554 + 1.612500000000000 0.05000000000000000 4555 + 1.612500000000000 0.06250000000000000 4556 + 1.612500000000000 0.07500000000000001 4557 + 1.612500000000000 0.08750000000000002 4558 + 1.612500000000000 0.1000000000000000 4559 + 1.612500000000000 0.1125000000000000 4560 + 1.612500000000000 0.1250000000000000 4561 + 1.612500000000000 0.1375000000000000 4562 + 1.612500000000000 0.1500000000000000 4563 + 1.612500000000000 0.1625000000000000 4564 + 1.612500000000000 0.1750000000000000 4565 + 1.612500000000000 0.1875000000000000 4566 + 1.612500000000000 0.2000000000000000 4567 + 1.612500000000000 0.2125000000000000 4568 + 1.612500000000000 0.2250000000000000 4569 + 1.612500000000000 0.2375000000000000 4570 + 1.612500000000000 0.2500000000000000 4571 + 1.612500000000000 0.2625000000000000 4572 + 1.612500000000000 0.2750000000000000 4573 + 1.612500000000000 0.2875000000000000 4574 + 1.612500000000000 0.3000000000000000 4575 + 1.612500000000000 0.3125000000000000 4576 + 1.612500000000000 0.3250000000000000 4577 + 1.612500000000000 0.3375000000000000 4578 + 1.612500000000000 0.3500000000000000 4579 + 1.612500000000000 0.3625000000000000 4580 + 1.612500000000000 0.3750000000000000 4581 + 1.612500000000000 0.3875000000000000 4582 + 1.612500000000000 0.4000000000000000 4583 + 1.612500000000000 0.4125000000000000 4584 + 1.612500000000000 0.4250000000000000 4585 + 1.612500000000000 0.4375000000000000 4586 + 1.612500000000000 0.4500000000000001 4587 + 1.612500000000000 0.4625000000000000 4588 + 1.612500000000000 0.4749999999999999 4589 + 1.612500000000000 0.4875000000000000 4590 + 1.612500000000000 0.5000000000000000 4591 + 1.600000000000000 0.000000000000000 4592 + 1.600000000000000 0.01250000000000000 4593 + 1.600000000000000 0.02500000000000000 4594 + 1.600000000000000 0.03750000000000001 4595 + 1.600000000000000 0.05000000000000000 4596 + 1.600000000000000 0.06250000000000000 4597 + 1.600000000000000 0.07500000000000001 4598 + 1.600000000000000 0.08749999999999999 4599 + 1.600000000000000 0.1000000000000000 4600 + 1.600000000000001 0.1125000000000000 4601 + 1.600000000000001 0.1250000000000000 4602 + 1.600000000000000 0.1375000000000000 4603 + 1.600000000000000 0.1500000000000000 4604 + 1.600000000000000 0.1625000000000001 4605 + 1.600000000000000 0.1750000000000000 4606 + 1.600000000000000 0.1875000000000001 4607 + 1.600000000000000 0.2000000000000000 4608 + 1.600000000000000 0.2125000000000000 4609 + 1.600000000000000 0.2250000000000000 4610 + 1.600000000000000 0.2375000000000001 4611 + 1.600000000000000 0.2500000000000000 4612 + 1.600000000000000 0.2625000000000000 4613 + 1.600000000000000 0.2750000000000000 4614 + 1.600000000000000 0.2875000000000000 4615 + 1.600000000000000 0.3000000000000000 4616 + 1.600000000000000 0.3125000000000000 4617 + 1.600000000000000 0.3250000000000000 4618 + 1.600000000000000 0.3375000000000000 4619 + 1.600000000000000 0.3500000000000001 4620 + 1.600000000000001 0.3625000000000000 4621 + 1.600000000000001 0.3750000000000000 4622 + 1.600000000000000 0.3875000000000000 4623 + 1.600000000000000 0.4000000000000000 4624 + 1.600000000000000 0.4125000000000001 4625 + 1.600000000000000 0.4250000000000000 4626 + 1.600000000000000 0.4375000000000000 4627 + 1.599999999999999 0.4500000000000000 4628 + 1.600000000000000 0.4625000000000000 4629 + 1.600000000000000 0.4750000000000001 4630 + 1.600000000000000 0.4875000000000000 4631 + 1.600000000000000 0.5000000000000000 4632 + 1.587500000000000 0.000000000000000 4633 + 1.587500000000001 0.01250000000000000 4634 + 1.587500000000000 0.02500000000000000 4635 + 1.587500000000001 0.03750000000000001 4636 + 1.587500000000000 0.05000000000000000 4637 + 1.587500000000000 0.06250000000000000 4638 + 1.587500000000000 0.07500000000000001 4639 + 1.587500000000000 0.08749999999999998 4640 + 1.587500000000000 0.1000000000000000 4641 + 1.587500000000000 0.1125000000000000 4642 + 1.587500000000000 0.1250000000000000 4643 + 1.587500000000000 0.1375000000000000 4644 + 1.587500000000000 0.1500000000000000 4645 + 1.587500000000000 0.1625000000000000 4646 + 1.587500000000000 0.1750000000000000 4647 + 1.587500000000000 0.1875000000000000 4648 + 1.587500000000000 0.2000000000000000 4649 + 1.587500000000000 0.2125000000000000 4650 + 1.587500000000000 0.2250000000000000 4651 + 1.587500000000000 0.2375000000000000 4652 + 1.587500000000000 0.2500000000000000 4653 + 1.587500000000000 0.2625000000000000 4654 + 1.587500000000000 0.2750000000000000 4655 + 1.587500000000000 0.2875000000000000 4656 + 1.587500000000000 0.3000000000000000 4657 + 1.587500000000000 0.3125000000000000 4658 + 1.587500000000000 0.3250000000000000 4659 + 1.587499999999999 0.3375000000000000 4660 + 1.587499999999999 0.3500000000000001 4661 + 1.587500000000000 0.3625000000000000 4662 + 1.587500000000000 0.3750000000000000 4663 + 1.587500000000000 0.3875000000000000 4664 + 1.587500000000000 0.4000000000000000 4665 + 1.587500000000000 0.4125000000000001 4666 + 1.587500000000000 0.4250000000000000 4667 + 1.587500000000000 0.4375000000000001 4668 + 1.587500000000000 0.4499999999999999 4669 + 1.587500000000000 0.4625000000000000 4670 + 1.587500000000000 0.4750000000000001 4671 + 1.587500000000000 0.4875000000000000 4672 + 1.587500000000000 0.5000000000000000 4673 + 1.575000000000000 0.000000000000000 4674 + 1.575000000000000 0.01250000000000000 4675 + 1.575000000000000 0.02500000000000000 4676 + 1.575000000000000 0.03750000000000001 4677 + 1.575000000000000 0.05000000000000000 4678 + 1.575000000000000 0.06250000000000000 4679 + 1.575000000000000 0.07500000000000001 4680 + 1.575000000000000 0.08750000000000001 4681 + 1.575000000000000 0.1000000000000000 4682 + 1.575000000000000 0.1125000000000000 4683 + 1.575000000000000 0.1250000000000000 4684 + 1.575000000000000 0.1375000000000000 4685 + 1.575000000000000 0.1500000000000000 4686 + 1.575000000000001 0.1625000000000000 4687 + 1.575000000000000 0.1750000000000000 4688 + 1.575000000000000 0.1875000000000000 4689 + 1.575000000000000 0.2000000000000000 4690 + 1.575000000000000 0.2125000000000000 4691 + 1.575000000000000 0.2250000000000000 4692 + 1.575000000000000 0.2375000000000000 4693 + 1.575000000000000 0.2500000000000000 4694 + 1.575000000000000 0.2625000000000000 4695 + 1.575000000000000 0.2750000000000000 4696 + 1.575000000000000 0.2875000000000000 4697 + 1.575000000000000 0.3000000000000000 4698 + 1.575000000000000 0.3125000000000000 4699 + 1.575000000000000 0.3250000000000000 4700 + 1.575000000000000 0.3374999999999999 4701 + 1.575000000000000 0.3500000000000001 4702 + 1.575000000000000 0.3625000000000000 4703 + 1.575000000000000 0.3750000000000000 4704 + 1.575000000000000 0.3875000000000000 4705 + 1.575000000000000 0.4000000000000000 4706 + 1.575000000000000 0.4125000000000000 4707 + 1.575000000000000 0.4249999999999999 4708 + 1.575000000000000 0.4374999999999999 4709 + 1.575000000000000 0.4500000000000000 4710 + 1.574999999999999 0.4625000000000000 4711 + 1.575000000000000 0.4750000000000000 4712 + 1.575000000000000 0.4875000000000000 4713 + 1.575000000000000 0.5000000000000000 4714 + 1.562500000000000 0.000000000000000 4715 + 1.562500000000000 0.01250000000000000 4716 + 1.562500000000000 0.02500000000000000 4717 + 1.562500000000000 0.03750000000000001 4718 + 1.562500000000000 0.05000000000000000 4719 + 1.562500000000000 0.06250000000000000 4720 + 1.562500000000000 0.07500000000000001 4721 + 1.562500000000000 0.08750000000000002 4722 + 1.562500000000000 0.1000000000000000 4723 + 1.562500000000000 0.1125000000000000 4724 + 1.562500000000000 0.1250000000000000 4725 + 1.562500000000000 0.1375000000000000 4726 + 1.562500000000000 0.1500000000000000 4727 + 1.562500000000000 0.1625000000000000 4728 + 1.562500000000000 0.1750000000000000 4729 + 1.562500000000000 0.1875000000000000 4730 + 1.562500000000000 0.2000000000000000 4731 + 1.562500000000000 0.2125000000000000 4732 + 1.562500000000000 0.2250000000000000 4733 + 1.562500000000000 0.2375000000000000 4734 + 1.562500000000000 0.2500000000000000 4735 + 1.562500000000000 0.2625000000000000 4736 + 1.562500000000000 0.2750000000000000 4737 + 1.562500000000000 0.2875000000000000 4738 + 1.562500000000000 0.3000000000000000 4739 + 1.562500000000000 0.3125000000000000 4740 + 1.562500000000000 0.3250000000000000 4741 + 1.562500000000000 0.3375000000000000 4742 + 1.562500000000000 0.3500000000000000 4743 + 1.562500000000000 0.3625000000000000 4744 + 1.562500000000000 0.3750000000000000 4745 + 1.562500000000000 0.3874999999999999 4746 + 1.562500000000000 0.4000000000000000 4747 + 1.562500000000000 0.4125000000000000 4748 + 1.562500000000000 0.4249999999999999 4749 + 1.562500000000000 0.4375000000000000 4750 + 1.562500000000000 0.4500000000000001 4751 + 1.562500000000000 0.4625000000000000 4752 + 1.562500000000000 0.4750000000000001 4753 + 1.562500000000000 0.4875000000000000 4754 + 1.562500000000000 0.5000000000000000 4755 + 1.550000000000000 0.000000000000000 4756 + 1.550000000000000 0.01250000000000000 4757 + 1.550000000000000 0.02500000000000000 4758 + 1.550000000000000 0.03750000000000001 4759 + 1.550000000000000 0.05000000000000000 4760 + 1.550000000000000 0.06250000000000000 4761 + 1.550000000000000 0.07500000000000001 4762 + 1.550000000000000 0.08750000000000002 4763 + 1.550000000000000 0.1000000000000000 4764 + 1.550000000000000 0.1125000000000000 4765 + 1.550000000000000 0.1250000000000000 4766 + 1.550000000000000 0.1375000000000000 4767 + 1.550000000000000 0.1500000000000000 4768 + 1.550000000000000 0.1625000000000000 4769 + 1.550000000000000 0.1750000000000000 4770 + 1.550000000000000 0.1875000000000001 4771 + 1.550000000000000 0.2000000000000000 4772 + 1.550000000000000 0.2125000000000000 4773 + 1.550000000000000 0.2250000000000001 4774 + 1.550000000000000 0.2375000000000000 4775 + 1.550000000000000 0.2500000000000000 4776 + 1.550000000000000 0.2625000000000000 4777 + 1.550000000000000 0.2750000000000000 4778 + 1.550000000000000 0.2875000000000000 4779 + 1.550000000000000 0.3000000000000000 4780 + 1.550000000000000 0.3125000000000000 4781 + 1.550000000000000 0.3250000000000000 4782 + 1.550000000000000 0.3375000000000000 4783 + 1.550000000000000 0.3500000000000000 4784 + 1.550000000000000 0.3625000000000000 4785 + 1.550000000000000 0.3750000000000000 4786 + 1.550000000000000 0.3875000000000001 4787 + 1.550000000000000 0.4000000000000000 4788 + 1.550000000000000 0.4125000000000000 4789 + 1.550000000000000 0.4250000000000000 4790 + 1.550000000000000 0.4375000000000000 4791 + 1.550000000000000 0.4500000000000000 4792 + 1.550000000000000 0.4625000000000001 4793 + 1.550000000000000 0.4750000000000000 4794 + 1.550000000000000 0.4875000000000000 4795 + 1.550000000000000 0.5000000000000000 4796 + 1.537500000000000 0.000000000000000 4797 + 1.537500000000000 0.01250000000000000 4798 + 1.537500000000000 0.02500000000000000 4799 + 1.537500000000000 0.03750000000000001 4800 + 1.537500000000000 0.05000000000000002 4801 + 1.537499999999999 0.06250000000000000 4802 + 1.537500000000000 0.07500000000000001 4803 + 1.537500000000000 0.08750000000000004 4804 + 1.537500000000000 0.1000000000000000 4805 + 1.537500000000000 0.1125000000000000 4806 + 1.537500000000000 0.1250000000000000 4807 + 1.537500000000000 0.1375000000000000 4808 + 1.537500000000000 0.1500000000000000 4809 + 1.537500000000000 0.1625000000000000 4810 + 1.537500000000000 0.1750000000000000 4811 + 1.537500000000000 0.1875000000000000 4812 + 1.537500000000000 0.2000000000000000 4813 + 1.537500000000000 0.2125000000000000 4814 + 1.537500000000000 0.2250000000000000 4815 + 1.537500000000000 0.2375000000000000 4816 + 1.537500000000000 0.2500000000000000 4817 + 1.537500000000000 0.2625000000000000 4818 + 1.537500000000000 0.2750000000000000 4819 + 1.537500000000000 0.2875000000000000 4820 + 1.537500000000000 0.3000000000000000 4821 + 1.537499999999999 0.3125000000000000 4822 + 1.537500000000000 0.3250000000000001 4823 + 1.537500000000000 0.3375000000000000 4824 + 1.537500000000000 0.3500000000000000 4825 + 1.537500000000000 0.3625000000000000 4826 + 1.537500000000000 0.3750000000000000 4827 + 1.537500000000000 0.3875000000000001 4828 + 1.537500000000000 0.4000000000000000 4829 + 1.537500000000000 0.4125000000000001 4830 + 1.537500000000000 0.4250000000000000 4831 + 1.537500000000000 0.4375000000000000 4832 + 1.537499999999999 0.4500000000000000 4833 + 1.537500000000000 0.4625000000000001 4834 + 1.537500000000000 0.4750000000000000 4835 + 1.537500000000000 0.4875000000000000 4836 + 1.537500000000000 0.5000000000000000 4837 + 1.525000000000000 0.000000000000000 4838 + 1.525000000000000 0.01250000000000000 4839 + 1.525000000000000 0.02500000000000000 4840 + 1.525000000000000 0.03750000000000001 4841 + 1.525000000000000 0.05000000000000000 4842 + 1.525000000000000 0.06250000000000000 4843 + 1.525000000000000 0.07500000000000001 4844 + 1.525000000000000 0.08750000000000001 4845 + 1.525000000000000 0.1000000000000000 4846 + 1.525000000000000 0.1125000000000000 4847 + 1.525000000000000 0.1250000000000000 4848 + 1.525000000000000 0.1375000000000000 4849 + 1.525000000000001 0.1500000000000000 4850 + 1.525000000000000 0.1625000000000000 4851 + 1.525000000000000 0.1750000000000000 4852 + 1.525000000000000 0.1875000000000000 4853 + 1.525000000000000 0.2000000000000000 4854 + 1.525000000000000 0.2125000000000000 4855 + 1.525000000000000 0.2250000000000000 4856 + 1.524999999999999 0.2375000000000000 4857 + 1.525000000000000 0.2500000000000000 4858 + 1.525000000000000 0.2625000000000000 4859 + 1.525000000000000 0.2750000000000000 4860 + 1.525000000000000 0.2875000000000000 4861 + 1.525000000000000 0.3000000000000000 4862 + 1.525000000000000 0.3125000000000000 4863 + 1.525000000000000 0.3249999999999999 4864 + 1.525000000000000 0.3375000000000000 4865 + 1.525000000000000 0.3499999999999999 4866 + 1.525000000000000 0.3625000000000000 4867 + 1.525000000000000 0.3750000000000000 4868 + 1.525000000000000 0.3875000000000000 4869 + 1.525000000000000 0.4000000000000000 4870 + 1.525000000000000 0.4125000000000000 4871 + 1.525000000000000 0.4250000000000000 4872 + 1.525000000000000 0.4375000000000001 4873 + 1.524999999999999 0.4500000000000001 4874 + 1.524999999999999 0.4625000000000001 4875 + 1.524999999999999 0.4750000000000001 4876 + 1.525000000000000 0.4875000000000002 4877 + 1.525000000000000 0.5000000000000000 4878 + 1.512500000000000 0.000000000000000 4879 + 1.512500000000000 0.01250000000000000 4880 + 1.512500000000000 0.02500000000000000 4881 + 1.512500000000001 0.03750000000000001 4882 + 1.512500000000000 0.05000000000000000 4883 + 1.512500000000000 0.06250000000000000 4884 + 1.512500000000000 0.07500000000000001 4885 + 1.512500000000000 0.08750000000000001 4886 + 1.512500000000000 0.1000000000000000 4887 + 1.512500000000000 0.1125000000000000 4888 + 1.512500000000000 0.1250000000000000 4889 + 1.512500000000000 0.1375000000000000 4890 + 1.512500000000000 0.1500000000000000 4891 + 1.512500000000000 0.1625000000000000 4892 + 1.512500000000000 0.1750000000000000 4893 + 1.512500000000000 0.1875000000000000 4894 + 1.512500000000000 0.2000000000000000 4895 + 1.512500000000000 0.2125000000000000 4896 + 1.512500000000000 0.2250000000000000 4897 + 1.512500000000000 0.2375000000000000 4898 + 1.512500000000000 0.2500000000000000 4899 + 1.512500000000000 0.2625000000000000 4900 + 1.512500000000000 0.2750000000000000 4901 + 1.512500000000000 0.2875000000000000 4902 + 1.512500000000000 0.3000000000000000 4903 + 1.512500000000000 0.3125000000000000 4904 + 1.512500000000000 0.3250000000000001 4905 + 1.512500000000000 0.3375000000000000 4906 + 1.512500000000000 0.3500000000000000 4907 + 1.512500000000000 0.3625000000000000 4908 + 1.512500000000000 0.3750000000000000 4909 + 1.512500000000000 0.3875000000000001 4910 + 1.512500000000000 0.4000000000000000 4911 + 1.512500000000000 0.4125000000000000 4912 + 1.512500000000000 0.4250000000000000 4913 + 1.512500000000000 0.4375000000000000 4914 + 1.512500000000000 0.4500000000000001 4915 + 1.512500000000000 0.4625000000000000 4916 + 1.512500000000000 0.4750000000000000 4917 + 1.512500000000000 0.4875000000000000 4918 + 1.512500000000000 0.5000000000000000 4919 + 1.500000000000000 0.000000000000000 4920 + 1.500000000000000 0.01250000000000000 4921 + 1.500000000000000 0.02500000000000000 4922 + 1.500000000000000 0.03750000000000001 4923 + 1.500000000000000 0.05000000000000000 4924 + 1.500000000000000 0.06250000000000000 4925 + 1.500000000000000 0.07500000000000001 4926 + 1.500000000000000 0.08750000000000001 4927 + 1.500000000000000 0.1000000000000000 4928 + 1.500000000000000 0.1125000000000000 4929 + 1.500000000000000 0.1250000000000000 4930 + 1.500000000000000 0.1375000000000000 4931 + 1.500000000000000 0.1500000000000000 4932 + 1.500000000000000 0.1625000000000000 4933 + 1.500000000000000 0.1750000000000000 4934 + 1.500000000000000 0.1875000000000001 4935 + 1.500000000000000 0.2000000000000000 4936 + 1.500000000000000 0.2125000000000000 4937 + 1.500000000000000 0.2250000000000000 4938 + 1.500000000000000 0.2375000000000000 4939 + 1.500000000000000 0.2500000000000000 4940 + 1.500000000000000 0.2625000000000000 4941 + 1.500000000000000 0.2750000000000000 4942 + 1.500000000000000 0.2875000000000000 4943 + 1.500000000000000 0.3000000000000000 4944 + 1.500000000000000 0.3125000000000000 4945 + 1.500000000000000 0.3250000000000000 4946 + 1.500000000000000 0.3375000000000000 4947 + 1.500000000000000 0.3500000000000000 4948 + 1.500000000000000 0.3625000000000000 4949 + 1.500000000000000 0.3750000000000000 4950 + 1.500000000000000 0.3875000000000000 4951 + 1.500000000000000 0.4000000000000000 4952 + 1.500000000000000 0.4125000000000000 4953 + 1.500000000000000 0.4250000000000000 4954 + 1.500000000000000 0.4375000000000000 4955 + 1.500000000000000 0.4499999999999999 4956 + 1.500000000000000 0.4625000000000000 4957 + 1.500000000000000 0.4750000000000000 4958 + 1.500000000000000 0.4875000000000000 4959 + 1.500000000000000 0.5000000000000000 4960 + 1.487500000000000 0.000000000000000 4961 + 1.487500000000000 0.01250000000000000 4962 + 1.487500000000000 0.02500000000000000 4963 + 1.487500000000000 0.03750000000000001 4964 + 1.487500000000000 0.05000000000000000 4965 + 1.487500000000000 0.06250000000000000 4966 + 1.487500000000000 0.07500000000000001 4967 + 1.487500000000000 0.08750000000000001 4968 + 1.487500000000000 0.1000000000000000 4969 + 1.487500000000000 0.1125000000000000 4970 + 1.487500000000000 0.1250000000000000 4971 + 1.487500000000000 0.1375000000000000 4972 + 1.487500000000000 0.1500000000000000 4973 + 1.487500000000000 0.1625000000000000 4974 + 1.487500000000000 0.1750000000000000 4975 + 1.487500000000000 0.1875000000000000 4976 + 1.487500000000000 0.2000000000000000 4977 + 1.487500000000000 0.2125000000000000 4978 + 1.487500000000000 0.2250000000000000 4979 + 1.487500000000000 0.2375000000000000 4980 + 1.487500000000000 0.2500000000000000 4981 + 1.487500000000000 0.2625000000000000 4982 + 1.487500000000000 0.2750000000000000 4983 + 1.487500000000000 0.2875000000000000 4984 + 1.487500000000000 0.3000000000000000 4985 + 1.487500000000000 0.3125000000000000 4986 + 1.487500000000000 0.3250000000000001 4987 + 1.487500000000000 0.3375000000000000 4988 + 1.487500000000000 0.3500000000000000 4989 + 1.487500000000000 0.3625000000000000 4990 + 1.487500000000000 0.3750000000000000 4991 + 1.487500000000000 0.3875000000000000 4992 + 1.487500000000000 0.4000000000000000 4993 + 1.487500000000000 0.4125000000000001 4994 + 1.487500000000000 0.4250000000000000 4995 + 1.487500000000000 0.4374999999999999 4996 + 1.487500000000000 0.4500000000000000 4997 + 1.487500000000000 0.4625000000000000 4998 + 1.487500000000000 0.4750000000000001 4999 + 1.487500000000000 0.4875000000000000 5000 + 1.487500000000000 0.5000000000000000 5001 + 1.475000000000000 0.000000000000000 5002 + 1.475000000000000 0.01250000000000000 5003 + 1.475000000000000 0.02500000000000000 5004 + 1.475000000000000 0.03750000000000001 5005 + 1.475000000000000 0.05000000000000000 5006 + 1.475000000000000 0.06250000000000000 5007 + 1.475000000000000 0.07500000000000001 5008 + 1.475000000000000 0.08750000000000001 5009 + 1.475000000000000 0.1000000000000000 5010 + 1.475000000000001 0.1125000000000000 5011 + 1.475000000000001 0.1250000000000000 5012 + 1.475000000000001 0.1375000000000000 5013 + 1.475000000000000 0.1500000000000000 5014 + 1.475000000000000 0.1625000000000000 5015 + 1.475000000000000 0.1750000000000000 5016 + 1.475000000000000 0.1875000000000000 5017 + 1.475000000000000 0.2000000000000000 5018 + 1.475000000000000 0.2125000000000000 5019 + 1.475000000000000 0.2250000000000000 5020 + 1.475000000000000 0.2375000000000000 5021 + 1.475000000000000 0.2500000000000000 5022 + 1.475000000000000 0.2625000000000000 5023 + 1.475000000000000 0.2750000000000000 5024 + 1.475000000000000 0.2875000000000000 5025 + 1.475000000000000 0.3000000000000000 5026 + 1.475000000000000 0.3125000000000000 5027 + 1.475000000000000 0.3250000000000000 5028 + 1.475000000000000 0.3375000000000000 5029 + 1.475000000000000 0.3500000000000000 5030 + 1.475000000000000 0.3625000000000002 5031 + 1.475000000000000 0.3750000000000000 5032 + 1.475000000000000 0.3875000000000001 5033 + 1.475000000000000 0.4000000000000000 5034 + 1.475000000000000 0.4125000000000000 5035 + 1.475000000000000 0.4250000000000000 5036 + 1.474999999999999 0.4375000000000000 5037 + 1.475000000000000 0.4500000000000001 5038 + 1.475000000000000 0.4625000000000000 5039 + 1.475000000000000 0.4749999999999999 5040 + 1.475000000000000 0.4875000000000000 5041 + 1.475000000000000 0.5000000000000000 5042 + 1.462500000000000 0.000000000000000 5043 + 1.462500000000000 0.01250000000000000 5044 + 1.462500000000000 0.02500000000000001 5045 + 1.462500000000000 0.03750000000000001 5046 + 1.462500000000001 0.05000000000000000 5047 + 1.462500000000000 0.06250000000000000 5048 + 1.462500000000000 0.07500000000000001 5049 + 1.462500000000000 0.08750000000000001 5050 + 1.462500000000000 0.1000000000000000 5051 + 1.462500000000000 0.1125000000000000 5052 + 1.462499999999999 0.1250000000000000 5053 + 1.462500000000000 0.1375000000000000 5054 + 1.462500000000000 0.1500000000000000 5055 + 1.462500000000000 0.1625000000000000 5056 + 1.462500000000000 0.1750000000000000 5057 + 1.462500000000000 0.1875000000000000 5058 + 1.462500000000000 0.2000000000000000 5059 + 1.462500000000000 0.2125000000000000 5060 + 1.462500000000000 0.2250000000000000 5061 + 1.462500000000000 0.2375000000000000 5062 + 1.462500000000000 0.2500000000000000 5063 + 1.462500000000000 0.2625000000000000 5064 + 1.462500000000000 0.2750000000000000 5065 + 1.462500000000000 0.2875000000000001 5066 + 1.462500000000000 0.3000000000000000 5067 + 1.462500000000000 0.3125000000000000 5068 + 1.462500000000000 0.3250000000000000 5069 + 1.462499999999999 0.3374999999999999 5070 + 1.462499999999999 0.3500000000000001 5071 + 1.462499999999999 0.3625000000000000 5072 + 1.462500000000000 0.3750000000000000 5073 + 1.462500000000000 0.3875000000000000 5074 + 1.462500000000000 0.4000000000000000 5075 + 1.462500000000000 0.4125000000000000 5076 + 1.462500000000000 0.4250000000000000 5077 + 1.462500000000000 0.4375000000000000 5078 + 1.462500000000000 0.4499999999999999 5079 + 1.462500000000000 0.4625000000000000 5080 + 1.462500000000000 0.4750000000000000 5081 + 1.462500000000000 0.4875000000000000 5082 + 1.462500000000000 0.5000000000000000 5083 + 1.450000000000000 0.000000000000000 5084 + 1.450000000000000 0.01250000000000000 5085 + 1.450000000000000 0.02500000000000000 5086 + 1.450000000000000 0.03750000000000001 5087 + 1.450000000000000 0.05000000000000000 5088 + 1.450000000000000 0.06250000000000000 5089 + 1.450000000000000 0.07500000000000001 5090 + 1.450000000000000 0.08750000000000001 5091 + 1.450000000000000 0.1000000000000000 5092 + 1.450000000000000 0.1125000000000000 5093 + 1.450000000000000 0.1250000000000000 5094 + 1.450000000000000 0.1375000000000000 5095 + 1.450000000000000 0.1500000000000000 5096 + 1.450000000000000 0.1625000000000000 5097 + 1.450000000000000 0.1750000000000000 5098 + 1.450000000000000 0.1875000000000000 5099 + 1.450000000000000 0.2000000000000000 5100 + 1.450000000000000 0.2125000000000000 5101 + 1.450000000000000 0.2250000000000000 5102 + 1.450000000000000 0.2375000000000000 5103 + 1.450000000000000 0.2500000000000000 5104 + 1.450000000000000 0.2625000000000000 5105 + 1.450000000000000 0.2750000000000000 5106 + 1.450000000000000 0.2875000000000001 5107 + 1.450000000000000 0.3000000000000000 5108 + 1.450000000000000 0.3125000000000000 5109 + 1.450000000000000 0.3250000000000000 5110 + 1.450000000000000 0.3375000000000000 5111 + 1.450000000000000 0.3500000000000000 5112 + 1.450000000000000 0.3625000000000000 5113 + 1.450000000000000 0.3750000000000000 5114 + 1.450000000000000 0.3875000000000000 5115 + 1.450000000000000 0.4000000000000000 5116 + 1.450000000000000 0.4125000000000001 5117 + 1.450000000000000 0.4250000000000000 5118 + 1.450000000000000 0.4375000000000000 5119 + 1.450000000000000 0.4500000000000000 5120 + 1.450000000000000 0.4625000000000000 5121 + 1.450000000000000 0.4750000000000001 5122 + 1.450000000000000 0.4875000000000002 5123 + 1.450000000000000 0.5000000000000000 5124 + 1.437500000000000 0.000000000000000 5125 + 1.437500000000000 0.01250000000000000 5126 + 1.437500000000000 0.02500000000000000 5127 + 1.437500000000000 0.03750000000000001 5128 + 1.437500000000000 0.05000000000000000 5129 + 1.437500000000000 0.06250000000000000 5130 + 1.437500000000000 0.07500000000000001 5131 + 1.437500000000000 0.08750000000000001 5132 + 1.437500000000000 0.1000000000000000 5133 + 1.437500000000000 0.1125000000000000 5134 + 1.437500000000000 0.1250000000000000 5135 + 1.437500000000000 0.1375000000000000 5136 + 1.437500000000000 0.1500000000000000 5137 + 1.437500000000000 0.1625000000000000 5138 + 1.437500000000000 0.1750000000000000 5139 + 1.437500000000000 0.1875000000000000 5140 + 1.437500000000000 0.2000000000000000 5141 + 1.437500000000000 0.2125000000000000 5142 + 1.437500000000000 0.2250000000000000 5143 + 1.437500000000000 0.2375000000000000 5144 + 1.437500000000000 0.2500000000000000 5145 + 1.437500000000000 0.2625000000000000 5146 + 1.437500000000000 0.2750000000000000 5147 + 1.437500000000000 0.2875000000000000 5148 + 1.437500000000000 0.3000000000000000 5149 + 1.437500000000000 0.3125000000000000 5150 + 1.437500000000000 0.3250000000000000 5151 + 1.437500000000000 0.3375000000000000 5152 + 1.437500000000000 0.3500000000000000 5153 + 1.437500000000000 0.3625000000000000 5154 + 1.437500000000000 0.3750000000000000 5155 + 1.437500000000000 0.3875000000000000 5156 + 1.437500000000000 0.4000000000000000 5157 + 1.437500000000000 0.4125000000000000 5158 + 1.437500000000000 0.4250000000000000 5159 + 1.437500000000000 0.4375000000000000 5160 + 1.437500000000000 0.4500000000000000 5161 + 1.437500000000000 0.4625000000000000 5162 + 1.437500000000000 0.4749999999999999 5163 + 1.437500000000000 0.4875000000000000 5164 + 1.437500000000000 0.5000000000000000 5165 + 1.425000000000000 0.000000000000000 5166 + 1.425000000000000 0.01250000000000000 5167 + 1.425000000000000 0.02500000000000000 5168 + 1.425000000000000 0.03750000000000001 5169 + 1.425000000000000 0.05000000000000000 5170 + 1.425000000000000 0.06250000000000000 5171 + 1.425000000000000 0.07500000000000001 5172 + 1.425000000000000 0.08749999999999999 5173 + 1.425000000000000 0.1000000000000000 5174 + 1.425000000000000 0.1125000000000000 5175 + 1.425000000000000 0.1250000000000000 5176 + 1.425000000000000 0.1375000000000000 5177 + 1.425000000000000 0.1500000000000000 5178 + 1.425000000000000 0.1625000000000000 5179 + 1.425000000000000 0.1750000000000000 5180 + 1.425000000000000 0.1875000000000000 5181 + 1.425000000000000 0.2000000000000000 5182 + 1.425000000000000 0.2125000000000000 5183 + 1.425000000000000 0.2250000000000000 5184 + 1.425000000000000 0.2375000000000001 5185 + 1.425000000000000 0.2500000000000000 5186 + 1.425000000000000 0.2625000000000000 5187 + 1.425000000000000 0.2750000000000000 5188 + 1.425000000000000 0.2875000000000000 5189 + 1.425000000000000 0.3000000000000000 5190 + 1.425000000000000 0.3125000000000000 5191 + 1.425000000000000 0.3250000000000000 5192 + 1.425000000000000 0.3375000000000000 5193 + 1.425000000000000 0.3500000000000000 5194 + 1.425000000000000 0.3625000000000000 5195 + 1.425000000000000 0.3750000000000000 5196 + 1.425000000000000 0.3875000000000000 5197 + 1.425000000000000 0.4000000000000000 5198 + 1.425000000000000 0.4125000000000000 5199 + 1.425000000000000 0.4250000000000000 5200 + 1.425000000000000 0.4375000000000000 5201 + 1.425000000000000 0.4500000000000001 5202 + 1.425000000000000 0.4625000000000000 5203 + 1.425000000000000 0.4750000000000001 5204 + 1.425000000000000 0.4875000000000000 5205 + 1.425000000000000 0.5000000000000000 5206 + 1.412500000000000 0.000000000000000 5207 + 1.412500000000001 0.01250000000000000 5208 + 1.412500000000000 0.02500000000000000 5209 + 1.412500000000001 0.03750000000000001 5210 + 1.412500000000000 0.05000000000000000 5211 + 1.412500000000000 0.06250000000000000 5212 + 1.412500000000000 0.07500000000000001 5213 + 1.412500000000000 0.08749999999999999 5214 + 1.412500000000000 0.1000000000000000 5215 + 1.412500000000000 0.1125000000000000 5216 + 1.412500000000000 0.1250000000000000 5217 + 1.412500000000000 0.1375000000000000 5218 + 1.412500000000000 0.1500000000000000 5219 + 1.412500000000000 0.1625000000000000 5220 + 1.412500000000000 0.1750000000000000 5221 + 1.412500000000000 0.1875000000000000 5222 + 1.412500000000000 0.2000000000000000 5223 + 1.412500000000000 0.2125000000000000 5224 + 1.412500000000000 0.2250000000000000 5225 + 1.412500000000000 0.2375000000000000 5226 + 1.412500000000001 0.2500000000000000 5227 + 1.412500000000000 0.2625000000000000 5228 + 1.412500000000000 0.2750000000000000 5229 + 1.412500000000000 0.2875000000000000 5230 + 1.412500000000000 0.3000000000000000 5231 + 1.412500000000000 0.3125000000000000 5232 + 1.412500000000000 0.3250000000000000 5233 + 1.412500000000000 0.3375000000000000 5234 + 1.412500000000000 0.3500000000000000 5235 + 1.412500000000000 0.3625000000000000 5236 + 1.412500000000000 0.3750000000000000 5237 + 1.412500000000000 0.3875000000000000 5238 + 1.412500000000000 0.4000000000000000 5239 + 1.412500000000000 0.4125000000000000 5240 + 1.412500000000000 0.4250000000000000 5241 + 1.412500000000000 0.4375000000000000 5242 + 1.412500000000000 0.4500000000000000 5243 + 1.412500000000000 0.4625000000000000 5244 + 1.412500000000000 0.4750000000000000 5245 + 1.412500000000000 0.4875000000000000 5246 + 1.412500000000000 0.5000000000000000 5247 + 1.400000000000000 0.000000000000000 5248 + 1.399999999999999 0.01250000000000000 5249 + 1.400000000000000 0.02500000000000001 5250 + 1.400000000000000 0.03750000000000001 5251 + 1.400000000000000 0.05000000000000000 5252 + 1.400000000000000 0.06250000000000000 5253 + 1.400000000000000 0.07500000000000001 5254 + 1.400000000000000 0.08750000000000001 5255 + 1.400000000000000 0.1000000000000000 5256 + 1.400000000000000 0.1125000000000000 5257 + 1.400000000000000 0.1250000000000000 5258 + 1.400000000000000 0.1375000000000000 5259 + 1.400000000000000 0.1500000000000000 5260 + 1.400000000000000 0.1625000000000000 5261 + 1.400000000000000 0.1750000000000000 5262 + 1.400000000000000 0.1875000000000000 5263 + 1.400000000000000 0.2000000000000000 5264 + 1.400000000000000 0.2125000000000000 5265 + 1.400000000000000 0.2250000000000000 5266 + 1.399999999999999 0.2375000000000000 5267 + 1.400000000000000 0.2500000000000000 5268 + 1.400000000000000 0.2625000000000000 5269 + 1.400000000000000 0.2750000000000000 5270 + 1.400000000000000 0.2875000000000000 5271 + 1.400000000000000 0.3000000000000000 5272 + 1.400000000000000 0.3125000000000000 5273 + 1.400000000000000 0.3250000000000001 5274 + 1.400000000000000 0.3375000000000000 5275 + 1.400000000000000 0.3499999999999999 5276 + 1.400000000000000 0.3625000000000000 5277 + 1.400000000000000 0.3750000000000000 5278 + 1.400000000000000 0.3875000000000000 5279 + 1.400000000000000 0.4000000000000000 5280 + 1.400000000000000 0.4125000000000001 5281 + 1.400000000000000 0.4250000000000000 5282 + 1.400000000000000 0.4375000000000000 5283 + 1.399999999999999 0.4500000000000001 5284 + 1.399999999999999 0.4624999999999999 5285 + 1.400000000000000 0.4750000000000000 5286 + 1.400000000000000 0.4875000000000000 5287 + 1.400000000000000 0.5000000000000000 5288 + 1.387500000000000 0.000000000000000 5289 + 1.387500000000000 0.01250000000000000 5290 + 1.387500000000000 0.02500000000000000 5291 + 1.387500000000000 0.03750000000000001 5292 + 1.387500000000000 0.05000000000000000 5293 + 1.387500000000000 0.06250000000000000 5294 + 1.387500000000000 0.07500000000000001 5295 + 1.387500000000000 0.08750000000000001 5296 + 1.387500000000000 0.1000000000000000 5297 + 1.387500000000000 0.1125000000000000 5298 + 1.387500000000000 0.1250000000000000 5299 + 1.387500000000000 0.1375000000000000 5300 + 1.387500000000000 0.1500000000000000 5301 + 1.387500000000000 0.1625000000000000 5302 + 1.387500000000000 0.1750000000000000 5303 + 1.387500000000000 0.1875000000000000 5304 + 1.387500000000000 0.2000000000000000 5305 + 1.387500000000000 0.2125000000000000 5306 + 1.387500000000000 0.2250000000000000 5307 + 1.387500000000000 0.2375000000000001 5308 + 1.387500000000000 0.2500000000000000 5309 + 1.387500000000000 0.2625000000000001 5310 + 1.387500000000000 0.2750000000000000 5311 + 1.387500000000000 0.2875000000000000 5312 + 1.387500000000000 0.3000000000000000 5313 + 1.387500000000000 0.3125000000000000 5314 + 1.387500000000000 0.3249999999999999 5315 + 1.387500000000000 0.3375000000000000 5316 + 1.387500000000000 0.3500000000000000 5317 + 1.387500000000000 0.3625000000000002 5318 + 1.387500000000000 0.3750000000000000 5319 + 1.387500000000000 0.3875000000000001 5320 + 1.387500000000000 0.4000000000000000 5321 + 1.387500000000000 0.4125000000000000 5322 + 1.387500000000000 0.4250000000000000 5323 + 1.387500000000000 0.4375000000000000 5324 + 1.387500000000000 0.4500000000000001 5325 + 1.387500000000000 0.4625000000000000 5326 + 1.387500000000000 0.4750000000000001 5327 + 1.387500000000000 0.4875000000000000 5328 + 1.387500000000000 0.5000000000000000 5329 + 1.375000000000000 0.000000000000000 5330 + 1.375000000000000 0.01250000000000000 5331 + 1.375000000000000 0.02500000000000000 5332 + 1.375000000000000 0.03750000000000001 5333 + 1.375000000000000 0.05000000000000000 5334 + 1.375000000000000 0.06250000000000000 5335 + 1.375000000000000 0.07500000000000001 5336 + 1.375000000000000 0.08750000000000002 5337 + 1.375000000000000 0.1000000000000000 5338 + 1.375000000000000 0.1125000000000000 5339 + 1.375000000000000 0.1250000000000000 5340 + 1.375000000000000 0.1375000000000000 5341 + 1.375000000000000 0.1500000000000000 5342 + 1.375000000000000 0.1625000000000000 5343 + 1.375000000000000 0.1750000000000000 5344 + 1.375000000000000 0.1875000000000000 5345 + 1.375000000000000 0.2000000000000001 5346 + 1.375000000000000 0.2125000000000000 5347 + 1.375000000000000 0.2250000000000000 5348 + 1.375000000000000 0.2375000000000000 5349 + 1.375000000000000 0.2500000000000000 5350 + 1.375000000000000 0.2625000000000000 5351 + 1.375000000000000 0.2750000000000000 5352 + 1.375000000000000 0.2875000000000000 5353 + 1.375000000000000 0.3000000000000000 5354 + 1.375000000000000 0.3125000000000000 5355 + 1.375000000000000 0.3250000000000000 5356 + 1.375000000000000 0.3375000000000000 5357 + 1.375000000000000 0.3500000000000000 5358 + 1.375000000000000 0.3625000000000000 5359 + 1.375000000000000 0.3750000000000000 5360 + 1.375000000000000 0.3875000000000000 5361 + 1.375000000000000 0.4000000000000000 5362 + 1.375000000000000 0.4125000000000001 5363 + 1.375000000000000 0.4250000000000000 5364 + 1.375000000000000 0.4375000000000000 5365 + 1.375000000000000 0.4500000000000000 5366 + 1.375000000000000 0.4625000000000000 5367 + 1.375000000000000 0.4750000000000000 5368 + 1.375000000000000 0.4875000000000000 5369 + 1.375000000000000 0.5000000000000000 5370 + 1.362500000000000 0.000000000000000 5371 + 1.362500000000000 0.01250000000000000 5372 + 1.362500000000000 0.02500000000000000 5373 + 1.362500000000000 0.03750000000000001 5374 + 1.362500000000000 0.05000000000000000 5375 + 1.362500000000000 0.06250000000000000 5376 + 1.362500000000000 0.07500000000000001 5377 + 1.362499999999999 0.08750000000000002 5378 + 1.362500000000000 0.1000000000000000 5379 + 1.362500000000000 0.1125000000000000 5380 + 1.362500000000000 0.1250000000000000 5381 + 1.362500000000000 0.1375000000000000 5382 + 1.362500000000000 0.1500000000000000 5383 + 1.362500000000000 0.1625000000000000 5384 + 1.362500000000000 0.1750000000000000 5385 + 1.362500000000000 0.1875000000000000 5386 + 1.362500000000000 0.2000000000000000 5387 + 1.362500000000000 0.2125000000000000 5388 + 1.362500000000000 0.2250000000000000 5389 + 1.362500000000000 0.2375000000000000 5390 + 1.362500000000000 0.2500000000000000 5391 + 1.362500000000000 0.2625000000000000 5392 + 1.362500000000000 0.2750000000000000 5393 + 1.362500000000000 0.2875000000000000 5394 + 1.362500000000000 0.3000000000000000 5395 + 1.362500000000000 0.3125000000000000 5396 + 1.362500000000000 0.3250000000000000 5397 + 1.362500000000000 0.3375000000000000 5398 + 1.362500000000000 0.3500000000000000 5399 + 1.362500000000000 0.3625000000000000 5400 + 1.362500000000000 0.3750000000000000 5401 + 1.362500000000000 0.3875000000000000 5402 + 1.362500000000000 0.4000000000000001 5403 + 1.362499999999999 0.4125000000000000 5404 + 1.362500000000000 0.4250000000000000 5405 + 1.362500000000000 0.4375000000000000 5406 + 1.362500000000000 0.4500000000000000 5407 + 1.362500000000000 0.4625000000000000 5408 + 1.362500000000000 0.4750000000000001 5409 + 1.362500000000000 0.4875000000000000 5410 + 1.362500000000000 0.5000000000000000 5411 + 1.350000000000000 0.000000000000000 5412 + 1.350000000000000 0.01250000000000000 5413 + 1.350000000000000 0.02500000000000000 5414 + 1.350000000000001 0.03750000000000001 5415 + 1.350000000000000 0.05000000000000000 5416 + 1.350000000000000 0.06250000000000000 5417 + 1.350000000000000 0.07500000000000001 5418 + 1.350000000000000 0.08749999999999999 5419 + 1.350000000000000 0.1000000000000000 5420 + 1.350000000000000 0.1125000000000000 5421 + 1.350000000000001 0.1250000000000000 5422 + 1.350000000000000 0.1375000000000000 5423 + 1.350000000000000 0.1500000000000000 5424 + 1.350000000000000 0.1625000000000000 5425 + 1.350000000000000 0.1750000000000000 5426 + 1.350000000000000 0.1875000000000001 5427 + 1.350000000000000 0.2000000000000000 5428 + 1.350000000000000 0.2125000000000000 5429 + 1.350000000000000 0.2250000000000000 5430 + 1.350000000000000 0.2375000000000000 5431 + 1.350000000000000 0.2500000000000000 5432 + 1.350000000000000 0.2625000000000000 5433 + 1.350000000000000 0.2750000000000000 5434 + 1.350000000000000 0.2875000000000000 5435 + 1.350000000000000 0.3000000000000000 5436 + 1.350000000000000 0.3125000000000000 5437 + 1.350000000000000 0.3250000000000001 5438 + 1.350000000000000 0.3375000000000000 5439 + 1.350000000000000 0.3500000000000001 5440 + 1.350000000000000 0.3625000000000000 5441 + 1.350000000000000 0.3749999999999999 5442 + 1.349999999999999 0.3875000000000001 5443 + 1.350000000000000 0.4000000000000000 5444 + 1.349999999999999 0.4125000000000001 5445 + 1.350000000000000 0.4250000000000000 5446 + 1.350000000000000 0.4375000000000000 5447 + 1.350000000000000 0.4500000000000001 5448 + 1.350000000000000 0.4625000000000000 5449 + 1.350000000000000 0.4750000000000000 5450 + 1.350000000000000 0.4875000000000000 5451 + 1.350000000000000 0.5000000000000000 5452 + 1.337500000000000 0.000000000000000 5453 + 1.337500000000000 0.01250000000000000 5454 + 1.337500000000000 0.02500000000000000 5455 + 1.337500000000000 0.03750000000000001 5456 + 1.337500000000001 0.05000000000000000 5457 + 1.337500000000000 0.06250000000000000 5458 + 1.337500000000000 0.07500000000000001 5459 + 1.337500000000000 0.08750000000000001 5460 + 1.337500000000000 0.1000000000000000 5461 + 1.337499999999999 0.1125000000000000 5462 + 1.337499999999999 0.1250000000000000 5463 + 1.337500000000000 0.1375000000000000 5464 + 1.337500000000000 0.1500000000000000 5465 + 1.337500000000000 0.1625000000000000 5466 + 1.337500000000000 0.1750000000000000 5467 + 1.337500000000000 0.1875000000000000 5468 + 1.337500000000000 0.2000000000000000 5469 + 1.337500000000000 0.2125000000000000 5470 + 1.337500000000000 0.2250000000000000 5471 + 1.337500000000000 0.2375000000000000 5472 + 1.337500000000000 0.2500000000000000 5473 + 1.337500000000000 0.2625000000000000 5474 + 1.337500000000000 0.2750000000000000 5475 + 1.337500000000000 0.2875000000000000 5476 + 1.337500000000000 0.3000000000000000 5477 + 1.337500000000000 0.3125000000000000 5478 + 1.337499999999999 0.3250000000000001 5479 + 1.337499999999999 0.3375000000000000 5480 + 1.337500000000000 0.3500000000000001 5481 + 1.337500000000000 0.3625000000000000 5482 + 1.337500000000000 0.3750000000000000 5483 + 1.337500000000000 0.3875000000000001 5484 + 1.337500000000000 0.4000000000000000 5485 + 1.337500000000000 0.4125000000000000 5486 + 1.337500000000000 0.4250000000000000 5487 + 1.337500000000000 0.4375000000000000 5488 + 1.337500000000000 0.4500000000000000 5489 + 1.337500000000000 0.4625000000000000 5490 + 1.337500000000000 0.4750000000000001 5491 + 1.337500000000000 0.4875000000000000 5492 + 1.337500000000000 0.5000000000000000 5493 + 1.325000000000000 0.000000000000000 5494 + 1.325000000000000 0.01250000000000000 5495 + 1.325000000000000 0.02500000000000000 5496 + 1.325000000000000 0.03750000000000001 5497 + 1.325000000000000 0.05000000000000000 5498 + 1.325000000000000 0.06250000000000000 5499 + 1.325000000000000 0.07500000000000001 5500 + 1.325000000000000 0.08750000000000001 5501 + 1.325000000000000 0.1000000000000000 5502 + 1.325000000000000 0.1125000000000000 5503 + 1.325000000000000 0.1250000000000000 5504 + 1.325000000000000 0.1375000000000000 5505 + 1.325000000000000 0.1500000000000000 5506 + 1.325000000000000 0.1625000000000000 5507 + 1.325000000000000 0.1750000000000000 5508 + 1.325000000000000 0.1875000000000000 5509 + 1.325000000000000 0.2000000000000000 5510 + 1.325000000000000 0.2125000000000000 5511 + 1.325000000000000 0.2250000000000000 5512 + 1.324999999999999 0.2375000000000000 5513 + 1.325000000000000 0.2500000000000000 5514 + 1.325000000000000 0.2625000000000000 5515 + 1.325000000000000 0.2750000000000000 5516 + 1.325000000000000 0.2875000000000001 5517 + 1.325000000000000 0.3000000000000000 5518 + 1.325000000000000 0.3125000000000000 5519 + 1.325000000000000 0.3250000000000000 5520 + 1.325000000000000 0.3375000000000000 5521 + 1.325000000000000 0.3500000000000000 5522 + 1.325000000000000 0.3625000000000000 5523 + 1.325000000000000 0.3750000000000000 5524 + 1.325000000000000 0.3875000000000000 5525 + 1.325000000000000 0.4000000000000000 5526 + 1.325000000000000 0.4125000000000000 5527 + 1.325000000000000 0.4250000000000000 5528 + 1.324999999999999 0.4375000000000000 5529 + 1.325000000000000 0.4500000000000000 5530 + 1.325000000000000 0.4625000000000000 5531 + 1.325000000000000 0.4750000000000000 5532 + 1.325000000000000 0.4875000000000000 5533 + 1.325000000000000 0.5000000000000000 5534 + 1.312500000000000 0.000000000000000 5535 + 1.312500000000000 0.01250000000000000 5536 + 1.312500000000000 0.02500000000000000 5537 + 1.312500000000000 0.03750000000000001 5538 + 1.312500000000000 0.05000000000000000 5539 + 1.312500000000000 0.06250000000000000 5540 + 1.312500000000000 0.07500000000000001 5541 + 1.312500000000000 0.08750000000000002 5542 + 1.312500000000000 0.1000000000000000 5543 + 1.312500000000000 0.1125000000000000 5544 + 1.312500000000000 0.1250000000000000 5545 + 1.312500000000000 0.1375000000000000 5546 + 1.312500000000000 0.1500000000000000 5547 + 1.312500000000000 0.1625000000000000 5548 + 1.312500000000000 0.1750000000000000 5549 + 1.312500000000000 0.1875000000000000 5550 + 1.312500000000000 0.2000000000000001 5551 + 1.312500000000000 0.2125000000000000 5552 + 1.312500000000000 0.2250000000000000 5553 + 1.312500000000000 0.2375000000000000 5554 + 1.312500000000000 0.2500000000000000 5555 + 1.312500000000000 0.2625000000000000 5556 + 1.312500000000000 0.2750000000000000 5557 + 1.312500000000000 0.2875000000000000 5558 + 1.312500000000000 0.3000000000000000 5559 + 1.312500000000000 0.3125000000000000 5560 + 1.312500000000000 0.3250000000000001 5561 + 1.312500000000000 0.3375000000000000 5562 + 1.312500000000000 0.3500000000000000 5563 + 1.312500000000000 0.3625000000000000 5564 + 1.312500000000000 0.3750000000000000 5565 + 1.312500000000000 0.3875000000000000 5566 + 1.312500000000000 0.4000000000000000 5567 + 1.312500000000000 0.4125000000000001 5568 + 1.312500000000000 0.4250000000000000 5569 + 1.312500000000000 0.4375000000000000 5570 + 1.312500000000000 0.4500000000000000 5571 + 1.312500000000000 0.4625000000000000 5572 + 1.312500000000000 0.4750000000000000 5573 + 1.312500000000000 0.4875000000000001 5574 + 1.312500000000000 0.5000000000000000 5575 + 1.300000000000000 0.000000000000000 5576 + 1.300000000000000 0.01250000000000000 5577 + 1.300000000000000 0.02500000000000000 5578 + 1.300000000000000 0.03750000000000001 5579 + 1.300000000000000 0.05000000000000000 5580 + 1.300000000000000 0.06250000000000000 5581 + 1.300000000000000 0.07500000000000001 5582 + 1.300000000000000 0.08749999999999999 5583 + 1.300000000000000 0.1000000000000000 5584 + 1.300000000000000 0.1125000000000000 5585 + 1.300000000000000 0.1250000000000000 5586 + 1.300000000000000 0.1375000000000000 5587 + 1.300000000000000 0.1500000000000000 5588 + 1.300000000000000 0.1625000000000000 5589 + 1.300000000000000 0.1750000000000000 5590 + 1.300000000000000 0.1875000000000000 5591 + 1.300000000000000 0.2000000000000000 5592 + 1.300000000000000 0.2125000000000000 5593 + 1.300000000000000 0.2250000000000000 5594 + 1.300000000000000 0.2375000000000000 5595 + 1.300000000000000 0.2500000000000000 5596 + 1.300000000000000 0.2625000000000000 5597 + 1.300000000000000 0.2750000000000000 5598 + 1.300000000000000 0.2875000000000000 5599 + 1.300000000000000 0.3000000000000000 5600 + 1.300000000000000 0.3125000000000000 5601 + 1.300000000000000 0.3250000000000000 5602 + 1.300000000000000 0.3375000000000000 5603 + 1.300000000000000 0.3500000000000000 5604 + 1.300000000000000 0.3625000000000000 5605 + 1.300000000000000 0.3750000000000000 5606 + 1.300000000000000 0.3875000000000001 5607 + 1.300000000000000 0.4000000000000000 5608 + 1.300000000000000 0.4125000000000000 5609 + 1.300000000000000 0.4250000000000000 5610 + 1.300000000000000 0.4375000000000000 5611 + 1.300000000000000 0.4500000000000000 5612 + 1.300000000000000 0.4625000000000000 5613 + 1.300000000000000 0.4750000000000000 5614 + 1.300000000000000 0.4875000000000000 5615 + 1.300000000000000 0.5000000000000000 5616 + 1.287500000000000 0.000000000000000 5617 + 1.287500000000000 0.01250000000000000 5618 + 1.287500000000000 0.02500000000000000 5619 + 1.287500000000000 0.03750000000000001 5620 + 1.287500000000001 0.05000000000000000 5621 + 1.287500000000000 0.06250000000000000 5622 + 1.287500000000000 0.07500000000000001 5623 + 1.287500000000000 0.08750000000000001 5624 + 1.287500000000000 0.1000000000000000 5625 + 1.287500000000000 0.1125000000000000 5626 + 1.287500000000000 0.1250000000000000 5627 + 1.287500000000000 0.1375000000000000 5628 + 1.287500000000000 0.1500000000000000 5629 + 1.287500000000000 0.1625000000000000 5630 + 1.287500000000000 0.1750000000000000 5631 + 1.287500000000000 0.1875000000000000 5632 + 1.287500000000000 0.2000000000000000 5633 + 1.287500000000000 0.2125000000000000 5634 + 1.287500000000000 0.2250000000000000 5635 + 1.287500000000001 0.2375000000000000 5636 + 1.287500000000001 0.2500000000000000 5637 + 1.287500000000001 0.2625000000000000 5638 + 1.287500000000000 0.2750000000000000 5639 + 1.287500000000000 0.2875000000000000 5640 + 1.287500000000000 0.3000000000000000 5641 + 1.287500000000000 0.3125000000000000 5642 + 1.287499999999999 0.3250000000000000 5643 + 1.287500000000000 0.3375000000000000 5644 + 1.287500000000000 0.3500000000000000 5645 + 1.287500000000000 0.3625000000000000 5646 + 1.287500000000000 0.3750000000000000 5647 + 1.287500000000000 0.3875000000000001 5648 + 1.287500000000000 0.4000000000000000 5649 + 1.287500000000000 0.4125000000000000 5650 + 1.287500000000000 0.4250000000000000 5651 + 1.287500000000000 0.4374999999999999 5652 + 1.287500000000000 0.4499999999999999 5653 + 1.287500000000000 0.4625000000000000 5654 + 1.287500000000000 0.4750000000000000 5655 + 1.287500000000000 0.4875000000000000 5656 + 1.287500000000000 0.5000000000000000 5657 + 1.275000000000000 0.000000000000000 5658 + 1.275000000000000 0.01250000000000000 5659 + 1.275000000000000 0.02500000000000000 5660 + 1.275000000000000 0.03750000000000001 5661 + 1.275000000000000 0.05000000000000002 5662 + 1.275000000000000 0.06250000000000000 5663 + 1.275000000000000 0.07500000000000001 5664 + 1.275000000000000 0.08750000000000001 5665 + 1.275000000000000 0.1000000000000000 5666 + 1.275000000000000 0.1125000000000000 5667 + 1.275000000000000 0.1250000000000000 5668 + 1.275000000000000 0.1375000000000000 5669 + 1.275000000000000 0.1500000000000000 5670 + 1.275000000000000 0.1625000000000000 5671 + 1.275000000000000 0.1750000000000000 5672 + 1.275000000000000 0.1875000000000000 5673 + 1.275000000000000 0.2000000000000000 5674 + 1.275000000000000 0.2125000000000000 5675 + 1.275000000000000 0.2250000000000000 5676 + 1.274999999999999 0.2375000000000000 5677 + 1.274999999999999 0.2500000000000000 5678 + 1.275000000000000 0.2625000000000000 5679 + 1.275000000000000 0.2750000000000000 5680 + 1.275000000000000 0.2875000000000001 5681 + 1.275000000000000 0.3000000000000000 5682 + 1.275000000000000 0.3125000000000000 5683 + 1.275000000000000 0.3250000000000000 5684 + 1.275000000000000 0.3375000000000000 5685 + 1.275000000000000 0.3499999999999999 5686 + 1.275000000000000 0.3625000000000000 5687 + 1.275000000000000 0.3750000000000000 5688 + 1.275000000000000 0.3875000000000001 5689 + 1.275000000000000 0.4000000000000000 5690 + 1.275000000000000 0.4125000000000000 5691 + 1.275000000000000 0.4250000000000000 5692 + 1.274999999999999 0.4375000000000000 5693 + 1.274999999999999 0.4500000000000000 5694 + 1.275000000000000 0.4625000000000000 5695 + 1.275000000000000 0.4750000000000000 5696 + 1.275000000000000 0.4875000000000000 5697 + 1.275000000000000 0.5000000000000000 5698 + 1.262500000000000 0.000000000000000 5699 + 1.262500000000000 0.01250000000000000 5700 + 1.262500000000000 0.02500000000000000 5701 + 1.262500000000000 0.03750000000000001 5702 + 1.262500000000000 0.05000000000000000 5703 + 1.262500000000000 0.06250000000000000 5704 + 1.262500000000000 0.07500000000000001 5705 + 1.262500000000000 0.08750000000000002 5706 + 1.262500000000001 0.1000000000000000 5707 + 1.262500000000000 0.1125000000000000 5708 + 1.262500000000000 0.1250000000000000 5709 + 1.262500000000000 0.1375000000000000 5710 + 1.262500000000000 0.1500000000000000 5711 + 1.262500000000000 0.1625000000000000 5712 + 1.262500000000000 0.1750000000000000 5713 + 1.262500000000000 0.1875000000000000 5714 + 1.262500000000000 0.2000000000000000 5715 + 1.262500000000000 0.2125000000000000 5716 + 1.262500000000000 0.2250000000000000 5717 + 1.262500000000000 0.2375000000000000 5718 + 1.262500000000000 0.2500000000000000 5719 + 1.262500000000000 0.2625000000000000 5720 + 1.262500000000000 0.2750000000000000 5721 + 1.262500000000000 0.2875000000000001 5722 + 1.262500000000000 0.3000000000000000 5723 + 1.262500000000000 0.3125000000000000 5724 + 1.262500000000000 0.3250000000000000 5725 + 1.262500000000000 0.3375000000000000 5726 + 1.262500000000000 0.3500000000000000 5727 + 1.262500000000000 0.3625000000000000 5728 + 1.262500000000000 0.3750000000000000 5729 + 1.262500000000000 0.3875000000000000 5730 + 1.262500000000000 0.4000000000000000 5731 + 1.262500000000000 0.4125000000000001 5732 + 1.262500000000000 0.4250000000000000 5733 + 1.262500000000000 0.4375000000000000 5734 + 1.262500000000000 0.4500000000000000 5735 + 1.262500000000000 0.4625000000000000 5736 + 1.262500000000000 0.4750000000000000 5737 + 1.262500000000000 0.4875000000000000 5738 + 1.262500000000000 0.5000000000000000 5739 + 1.250000000000000 0.000000000000000 5740 + 1.250000000000000 0.01250000000000000 5741 + 1.250000000000000 0.02500000000000000 5742 + 1.250000000000000 0.03750000000000001 5743 + 1.250000000000000 0.05000000000000000 5744 + 1.250000000000000 0.06250000000000000 5745 + 1.250000000000000 0.07500000000000001 5746 + 1.250000000000000 0.08750000000000001 5747 + 1.250000000000000 0.1000000000000000 5748 + 1.250000000000000 0.1125000000000000 5749 + 1.250000000000000 0.1250000000000000 5750 + 1.250000000000000 0.1375000000000000 5751 + 1.250000000000000 0.1500000000000000 5752 + 1.250000000000000 0.1625000000000000 5753 + 1.250000000000000 0.1750000000000000 5754 + 1.250000000000000 0.1875000000000000 5755 + 1.250000000000000 0.2000000000000001 5756 + 1.250000000000000 0.2125000000000000 5757 + 1.250000000000000 0.2250000000000000 5758 + 1.250000000000000 0.2375000000000000 5759 + 1.250000000000000 0.2500000000000000 5760 + 1.250000000000000 0.2625000000000000 5761 + 1.250000000000000 0.2750000000000000 5762 + 1.250000000000000 0.2875000000000001 5763 + 1.250000000000000 0.3000000000000000 5764 + 1.250000000000000 0.3125000000000000 5765 + 1.250000000000000 0.3250000000000000 5766 + 1.250000000000000 0.3375000000000000 5767 + 1.250000000000000 0.3500000000000000 5768 + 1.250000000000000 0.3625000000000000 5769 + 1.250000000000000 0.3750000000000000 5770 + 1.250000000000000 0.3874999999999999 5771 + 1.250000000000000 0.4000000000000000 5772 + 1.250000000000000 0.4125000000000000 5773 + 1.250000000000000 0.4250000000000000 5774 + 1.250000000000000 0.4375000000000000 5775 + 1.250000000000000 0.4500000000000000 5776 + 1.250000000000000 0.4625000000000000 5777 + 1.250000000000000 0.4750000000000001 5778 + 1.250000000000000 0.4875000000000000 5779 + 1.250000000000000 0.5000000000000000 5780 + 1.237500000000000 0.000000000000000 5781 + 1.237500000000000 0.01250000000000000 5782 + 1.237500000000000 0.02500000000000000 5783 + 1.237500000000000 0.03750000000000001 5784 + 1.237500000000000 0.05000000000000000 5785 + 1.237500000000000 0.06250000000000000 5786 + 1.237500000000000 0.07500000000000001 5787 + 1.237500000000000 0.08750000000000004 5788 + 1.237500000000000 0.1000000000000000 5789 + 1.237500000000000 0.1125000000000000 5790 + 1.237500000000000 0.1250000000000000 5791 + 1.237500000000000 0.1375000000000000 5792 + 1.237500000000000 0.1500000000000000 5793 + 1.237500000000000 0.1625000000000000 5794 + 1.237500000000000 0.1750000000000000 5795 + 1.237500000000000 0.1875000000000000 5796 + 1.237500000000000 0.2000000000000000 5797 + 1.237500000000000 0.2125000000000000 5798 + 1.237500000000000 0.2250000000000000 5799 + 1.237500000000000 0.2375000000000000 5800 + 1.237500000000000 0.2500000000000000 5801 + 1.237500000000000 0.2625000000000000 5802 + 1.237500000000000 0.2750000000000000 5803 + 1.237500000000000 0.2875000000000000 5804 + 1.237500000000000 0.3000000000000000 5805 + 1.237500000000000 0.3125000000000000 5806 + 1.237500000000000 0.3250000000000000 5807 + 1.237500000000000 0.3375000000000000 5808 + 1.237500000000000 0.3500000000000001 5809 + 1.237500000000000 0.3625000000000000 5810 + 1.237500000000000 0.3750000000000000 5811 + 1.237500000000000 0.3875000000000000 5812 + 1.237500000000000 0.4000000000000000 5813 + 1.237500000000000 0.4125000000000000 5814 + 1.237500000000000 0.4250000000000000 5815 + 1.237500000000000 0.4375000000000000 5816 + 1.237500000000000 0.4499999999999999 5817 + 1.237500000000000 0.4625000000000000 5818 + 1.237499999999999 0.4750000000000000 5819 + 1.237499999999999 0.4875000000000000 5820 + 1.237500000000000 0.5000000000000000 5821 + 1.225000000000000 0.000000000000000 5822 + 1.224999999999999 0.01250000000000000 5823 + 1.225000000000000 0.02500000000000000 5824 + 1.225000000000000 0.03750000000000001 5825 + 1.225000000000000 0.05000000000000000 5826 + 1.225000000000000 0.06250000000000000 5827 + 1.225000000000000 0.07500000000000001 5828 + 1.225000000000000 0.08750000000000001 5829 + 1.225000000000000 0.1000000000000000 5830 + 1.225000000000000 0.1125000000000000 5831 + 1.225000000000000 0.1250000000000000 5832 + 1.225000000000001 0.1375000000000000 5833 + 1.225000000000001 0.1500000000000000 5834 + 1.225000000000000 0.1625000000000000 5835 + 1.225000000000000 0.1750000000000000 5836 + 1.225000000000000 0.1875000000000000 5837 + 1.225000000000000 0.2000000000000000 5838 + 1.224999999999999 0.2125000000000000 5839 + 1.225000000000000 0.2250000000000001 5840 + 1.225000000000000 0.2375000000000000 5841 + 1.225000000000000 0.2500000000000000 5842 + 1.225000000000000 0.2625000000000000 5843 + 1.225000000000000 0.2750000000000000 5844 + 1.225000000000000 0.2875000000000000 5845 + 1.225000000000000 0.3000000000000000 5846 + 1.225000000000000 0.3125000000000000 5847 + 1.225000000000000 0.3250000000000000 5848 + 1.225000000000000 0.3375000000000000 5849 + 1.225000000000000 0.3500000000000001 5850 + 1.225000000000000 0.3625000000000000 5851 + 1.225000000000000 0.3750000000000000 5852 + 1.225000000000000 0.3875000000000000 5853 + 1.224999999999999 0.4000000000000000 5854 + 1.224999999999999 0.4125000000000000 5855 + 1.225000000000000 0.4250000000000000 5856 + 1.225000000000000 0.4375000000000000 5857 + 1.225000000000000 0.4500000000000000 5858 + 1.225000000000000 0.4625000000000000 5859 + 1.225000000000000 0.4750000000000000 5860 + 1.225000000000000 0.4875000000000000 5861 + 1.225000000000000 0.5000000000000000 5862 + 1.212500000000000 0.000000000000000 5863 + 1.212500000000000 0.01250000000000000 5864 + 1.212500000000000 0.02500000000000000 5865 + 1.212500000000000 0.03750000000000001 5866 + 1.212500000000000 0.05000000000000000 5867 + 1.212500000000001 0.06250000000000000 5868 + 1.212500000000001 0.07500000000000001 5869 + 1.212500000000000 0.08750000000000001 5870 + 1.212500000000000 0.1000000000000000 5871 + 1.212500000000000 0.1125000000000000 5872 + 1.212500000000000 0.1250000000000000 5873 + 1.212499999999999 0.1375000000000000 5874 + 1.212499999999999 0.1500000000000000 5875 + 1.212500000000000 0.1625000000000000 5876 + 1.212500000000000 0.1750000000000000 5877 + 1.212500000000000 0.1875000000000000 5878 + 1.212500000000000 0.2000000000000000 5879 + 1.212500000000000 0.2125000000000000 5880 + 1.212500000000000 0.2250000000000000 5881 + 1.212500000000000 0.2375000000000000 5882 + 1.212500000000000 0.2500000000000000 5883 + 1.212500000000000 0.2625000000000000 5884 + 1.212500000000000 0.2750000000000000 5885 + 1.212500000000000 0.2875000000000000 5886 + 1.212500000000000 0.3000000000000000 5887 + 1.212500000000000 0.3125000000000000 5888 + 1.212499999999999 0.3250000000000000 5889 + 1.212499999999999 0.3375000000000000 5890 + 1.212500000000000 0.3500000000000000 5891 + 1.212500000000000 0.3625000000000000 5892 + 1.212500000000000 0.3750000000000000 5893 + 1.212500000000000 0.3875000000000000 5894 + 1.212500000000000 0.4000000000000000 5895 + 1.212500000000000 0.4125000000000001 5896 + 1.212500000000000 0.4250000000000000 5897 + 1.212500000000000 0.4375000000000000 5898 + 1.212500000000000 0.4500000000000001 5899 + 1.212500000000000 0.4625000000000000 5900 + 1.212500000000000 0.4750000000000000 5901 + 1.212500000000000 0.4875000000000000 5902 + 1.212500000000000 0.5000000000000000 5903 + 1.200000000000000 0.000000000000000 5904 + 1.200000000000000 0.01250000000000000 5905 + 1.200000000000000 0.02500000000000000 5906 + 1.200000000000000 0.03750000000000001 5907 + 1.200000000000000 0.05000000000000000 5908 + 1.200000000000000 0.06250000000000000 5909 + 1.200000000000000 0.07500000000000001 5910 + 1.200000000000000 0.08750000000000001 5911 + 1.200000000000000 0.1000000000000000 5912 + 1.200000000000000 0.1125000000000000 5913 + 1.200000000000000 0.1250000000000000 5914 + 1.200000000000000 0.1375000000000000 5915 + 1.200000000000000 0.1500000000000000 5916 + 1.200000000000000 0.1625000000000000 5917 + 1.200000000000000 0.1750000000000000 5918 + 1.200000000000000 0.1875000000000000 5919 + 1.200000000000000 0.2000000000000000 5920 + 1.200000000000000 0.2125000000000000 5921 + 1.200000000000000 0.2250000000000000 5922 + 1.200000000000000 0.2375000000000000 5923 + 1.200000000000000 0.2500000000000000 5924 + 1.200000000000000 0.2625000000000000 5925 + 1.200000000000000 0.2750000000000000 5926 + 1.200000000000000 0.2875000000000000 5927 + 1.200000000000000 0.3000000000000000 5928 + 1.200000000000000 0.3125000000000000 5929 + 1.200000000000000 0.3250000000000000 5930 + 1.200000000000000 0.3375000000000000 5931 + 1.200000000000000 0.3500000000000000 5932 + 1.200000000000000 0.3625000000000000 5933 + 1.200000000000000 0.3750000000000000 5934 + 1.200000000000000 0.3875000000000000 5935 + 1.200000000000000 0.4000000000000000 5936 + 1.200000000000000 0.4125000000000000 5937 + 1.199999999999999 0.4250000000000000 5938 + 1.199999999999999 0.4375000000000000 5939 + 1.200000000000000 0.4500000000000000 5940 + 1.200000000000000 0.4625000000000000 5941 + 1.200000000000000 0.4750000000000000 5942 + 1.200000000000000 0.4875000000000000 5943 + 1.200000000000000 0.5000000000000000 5944 + 1.187500000000000 0.000000000000000 5945 + 1.187500000000000 0.01250000000000000 5946 + 1.187500000000000 0.02500000000000000 5947 + 1.187500000000000 0.03750000000000001 5948 + 1.187500000000000 0.05000000000000000 5949 + 1.187500000000000 0.06250000000000000 5950 + 1.187500000000000 0.07500000000000001 5951 + 1.187500000000000 0.08750000000000001 5952 + 1.187500000000000 0.1000000000000000 5953 + 1.187500000000000 0.1125000000000000 5954 + 1.187500000000000 0.1250000000000000 5955 + 1.187500000000000 0.1375000000000000 5956 + 1.187500000000000 0.1500000000000000 5957 + 1.187500000000000 0.1625000000000000 5958 + 1.187500000000000 0.1750000000000001 5959 + 1.187500000000000 0.1875000000000000 5960 + 1.187500000000000 0.2000000000000000 5961 + 1.187500000000000 0.2125000000000000 5962 + 1.187500000000000 0.2250000000000000 5963 + 1.187500000000000 0.2375000000000000 5964 + 1.187500000000000 0.2500000000000000 5965 + 1.187500000000000 0.2625000000000000 5966 + 1.187500000000000 0.2750000000000000 5967 + 1.187500000000000 0.2875000000000000 5968 + 1.187500000000000 0.3000000000000000 5969 + 1.187500000000000 0.3125000000000000 5970 + 1.187500000000000 0.3250000000000000 5971 + 1.187500000000000 0.3375000000000000 5972 + 1.187500000000000 0.3500000000000000 5973 + 1.187500000000000 0.3625000000000000 5974 + 1.187500000000000 0.3750000000000000 5975 + 1.187500000000000 0.3875000000000000 5976 + 1.187500000000000 0.4000000000000000 5977 + 1.187500000000000 0.4124999999999999 5978 + 1.187500000000000 0.4250000000000000 5979 + 1.187500000000000 0.4375000000000000 5980 + 1.187500000000000 0.4500000000000000 5981 + 1.187500000000000 0.4625000000000000 5982 + 1.187499999999999 0.4750000000000001 5983 + 1.187499999999999 0.4875000000000000 5984 + 1.187500000000000 0.5000000000000000 5985 + 1.175000000000000 0.000000000000000 5986 + 1.175000000000000 0.01250000000000000 5987 + 1.175000000000000 0.02500000000000000 5988 + 1.175000000000000 0.03750000000000001 5989 + 1.175000000000000 0.05000000000000000 5990 + 1.175000000000000 0.06250000000000000 5991 + 1.175000000000000 0.07500000000000001 5992 + 1.175000000000000 0.08749999999999998 5993 + 1.175000000000000 0.1000000000000000 5994 + 1.175000000000000 0.1125000000000000 5995 + 1.175000000000000 0.1250000000000000 5996 + 1.175000000000000 0.1375000000000000 5997 + 1.175000000000000 0.1500000000000000 5998 + 1.175000000000000 0.1625000000000000 5999 + 1.175000000000000 0.1750000000000001 6000 + 1.175000000000000 0.1875000000000000 6001 + 1.175000000000000 0.2000000000000000 6002 + 1.175000000000000 0.2125000000000000 6003 + 1.175000000000000 0.2250000000000000 6004 + 1.175000000000000 0.2375000000000001 6005 + 1.175000000000000 0.2500000000000000 6006 + 1.175000000000000 0.2625000000000000 6007 + 1.175000000000000 0.2750000000000000 6008 + 1.175000000000000 0.2875000000000000 6009 + 1.175000000000000 0.3000000000000000 6010 + 1.175000000000000 0.3125000000000000 6011 + 1.175000000000000 0.3250000000000000 6012 + 1.175000000000000 0.3375000000000000 6013 + 1.175000000000000 0.3499999999999999 6014 + 1.175000000000000 0.3625000000000000 6015 + 1.175000000000000 0.3750000000000000 6016 + 1.175000000000000 0.3875000000000001 6017 + 1.175000000000000 0.4000000000000000 6018 + 1.175000000000000 0.4125000000000000 6019 + 1.175000000000000 0.4250000000000000 6020 + 1.175000000000000 0.4375000000000000 6021 + 1.175000000000000 0.4500000000000001 6022 + 1.175000000000000 0.4625000000000000 6023 + 1.175000000000000 0.4750000000000000 6024 + 1.175000000000000 0.4875000000000000 6025 + 1.175000000000000 0.5000000000000000 6026 + 1.162500000000000 0.000000000000000 6027 + 1.162500000000000 0.01250000000000000 6028 + 1.162500000000000 0.02500000000000000 6029 + 1.162500000000000 0.03750000000000001 6030 + 1.162500000000001 0.05000000000000000 6031 + 1.162500000000000 0.06250000000000000 6032 + 1.162500000000000 0.07500000000000001 6033 + 1.162500000000001 0.08750000000000001 6034 + 1.162500000000000 0.1000000000000000 6035 + 1.162500000000000 0.1125000000000000 6036 + 1.162500000000000 0.1250000000000000 6037 + 1.162500000000000 0.1375000000000000 6038 + 1.162500000000000 0.1500000000000000 6039 + 1.162500000000000 0.1625000000000000 6040 + 1.162500000000000 0.1750000000000000 6041 + 1.162500000000000 0.1875000000000000 6042 + 1.162500000000000 0.2000000000000000 6043 + 1.162500000000000 0.2125000000000000 6044 + 1.162500000000000 0.2250000000000000 6045 + 1.162500000000000 0.2375000000000000 6046 + 1.162500000000001 0.2500000000000000 6047 + 1.162500000000000 0.2625000000000000 6048 + 1.162500000000000 0.2750000000000000 6049 + 1.162500000000000 0.2875000000000000 6050 + 1.162499999999999 0.3000000000000000 6051 + 1.162499999999999 0.3125000000000000 6052 + 1.162500000000000 0.3250000000000000 6053 + 1.162500000000000 0.3375000000000000 6054 + 1.162500000000000 0.3499999999999999 6055 + 1.162500000000000 0.3625000000000000 6056 + 1.162500000000000 0.3750000000000000 6057 + 1.162500000000000 0.3875000000000000 6058 + 1.162500000000000 0.4000000000000000 6059 + 1.162500000000000 0.4125000000000000 6060 + 1.162500000000000 0.4250000000000000 6061 + 1.162500000000000 0.4375000000000000 6062 + 1.162500000000000 0.4500000000000000 6063 + 1.162500000000000 0.4625000000000000 6064 + 1.162500000000000 0.4750000000000000 6065 + 1.162500000000000 0.4875000000000000 6066 + 1.162500000000000 0.5000000000000000 6067 + 1.150000000000000 0.000000000000000 6068 + 1.150000000000000 0.01250000000000000 6069 + 1.150000000000000 0.02500000000000000 6070 + 1.150000000000000 0.03750000000000001 6071 + 1.150000000000000 0.05000000000000000 6072 + 1.150000000000000 0.06250000000000000 6073 + 1.150000000000000 0.07500000000000001 6074 + 1.150000000000000 0.08750000000000001 6075 + 1.150000000000000 0.1000000000000000 6076 + 1.150000000000000 0.1125000000000000 6077 + 1.150000000000000 0.1250000000000000 6078 + 1.150000000000000 0.1375000000000000 6079 + 1.150000000000000 0.1500000000000000 6080 + 1.150000000000001 0.1625000000000000 6081 + 1.150000000000000 0.1750000000000000 6082 + 1.150000000000000 0.1875000000000000 6083 + 1.150000000000000 0.2000000000000000 6084 + 1.150000000000000 0.2125000000000000 6085 + 1.150000000000000 0.2250000000000000 6086 + 1.149999999999999 0.2375000000000000 6087 + 1.149999999999999 0.2500000000000000 6088 + 1.150000000000000 0.2625000000000000 6089 + 1.150000000000000 0.2750000000000000 6090 + 1.150000000000000 0.2875000000000000 6091 + 1.150000000000000 0.3000000000000000 6092 + 1.150000000000000 0.3125000000000000 6093 + 1.150000000000000 0.3250000000000000 6094 + 1.150000000000000 0.3375000000000000 6095 + 1.150000000000000 0.3500000000000000 6096 + 1.150000000000000 0.3625000000000000 6097 + 1.150000000000000 0.3750000000000000 6098 + 1.150000000000000 0.3875000000000000 6099 + 1.150000000000000 0.4000000000000000 6100 + 1.150000000000000 0.4125000000000000 6101 + 1.149999999999999 0.4250000000000000 6102 + 1.149999999999999 0.4375000000000000 6103 + 1.150000000000000 0.4499999999999999 6104 + 1.150000000000000 0.4625000000000000 6105 + 1.150000000000000 0.4750000000000001 6106 + 1.150000000000000 0.4875000000000000 6107 + 1.150000000000000 0.5000000000000000 6108 + 1.137500000000000 0.000000000000000 6109 + 1.137500000000000 0.01250000000000000 6110 + 1.137500000000000 0.02500000000000000 6111 + 1.137500000000000 0.03750000000000001 6112 + 1.137500000000000 0.05000000000000000 6113 + 1.137500000000000 0.06250000000000000 6114 + 1.137500000000000 0.07500000000000001 6115 + 1.137500000000000 0.08750000000000001 6116 + 1.137500000000000 0.1000000000000000 6117 + 1.137500000000000 0.1125000000000000 6118 + 1.137500000000000 0.1250000000000000 6119 + 1.137500000000000 0.1375000000000000 6120 + 1.137500000000000 0.1500000000000000 6121 + 1.137500000000000 0.1625000000000000 6122 + 1.137500000000000 0.1750000000000000 6123 + 1.137500000000000 0.1875000000000000 6124 + 1.137500000000000 0.2000000000000000 6125 + 1.137500000000000 0.2125000000000000 6126 + 1.137500000000000 0.2250000000000000 6127 + 1.137500000000000 0.2375000000000001 6128 + 1.137500000000000 0.2500000000000000 6129 + 1.137500000000000 0.2625000000000000 6130 + 1.137500000000000 0.2750000000000000 6131 + 1.137500000000000 0.2875000000000000 6132 + 1.137500000000000 0.3000000000000000 6133 + 1.137500000000000 0.3125000000000000 6134 + 1.137500000000000 0.3250000000000000 6135 + 1.137500000000000 0.3375000000000000 6136 + 1.137500000000000 0.3500000000000000 6137 + 1.137500000000000 0.3625000000000000 6138 + 1.137500000000000 0.3750000000000000 6139 + 1.137500000000000 0.3875000000000000 6140 + 1.137500000000000 0.4000000000000000 6141 + 1.137500000000000 0.4125000000000000 6142 + 1.137500000000000 0.4250000000000000 6143 + 1.137500000000000 0.4375000000000000 6144 + 1.137500000000000 0.4500000000000000 6145 + 1.137500000000000 0.4625000000000000 6146 + 1.137500000000000 0.4750000000000000 6147 + 1.137500000000000 0.4875000000000000 6148 + 1.137500000000000 0.5000000000000000 6149 + 1.125000000000000 0.000000000000000 6150 + 1.125000000000000 0.01250000000000000 6151 + 1.125000000000000 0.02500000000000000 6152 + 1.125000000000000 0.03750000000000001 6153 + 1.125000000000000 0.05000000000000000 6154 + 1.125000000000000 0.06250000000000000 6155 + 1.125000000000000 0.07500000000000001 6156 + 1.125000000000000 0.08750000000000001 6157 + 1.125000000000000 0.1000000000000000 6158 + 1.125000000000000 0.1125000000000000 6159 + 1.125000000000000 0.1250000000000000 6160 + 1.125000000000000 0.1375000000000000 6161 + 1.125000000000000 0.1500000000000000 6162 + 1.125000000000000 0.1625000000000000 6163 + 1.125000000000000 0.1750000000000000 6164 + 1.125000000000000 0.1875000000000000 6165 + 1.125000000000000 0.2000000000000000 6166 + 1.125000000000000 0.2125000000000000 6167 + 1.125000000000000 0.2250000000000000 6168 + 1.125000000000000 0.2375000000000000 6169 + 1.125000000000000 0.2500000000000000 6170 + 1.125000000000000 0.2625000000000000 6171 + 1.125000000000000 0.2750000000000000 6172 + 1.125000000000000 0.2875000000000000 6173 + 1.125000000000000 0.3000000000000000 6174 + 1.125000000000000 0.3125000000000000 6175 + 1.125000000000000 0.3250000000000000 6176 + 1.125000000000000 0.3375000000000000 6177 + 1.125000000000000 0.3500000000000000 6178 + 1.125000000000000 0.3625000000000000 6179 + 1.125000000000000 0.3750000000000000 6180 + 1.125000000000000 0.3875000000000000 6181 + 1.125000000000000 0.4000000000000000 6182 + 1.125000000000000 0.4125000000000000 6183 + 1.125000000000000 0.4250000000000000 6184 + 1.125000000000000 0.4375000000000000 6185 + 1.125000000000000 0.4500000000000000 6186 + 1.125000000000000 0.4625000000000000 6187 + 1.125000000000000 0.4749999999999999 6188 + 1.125000000000000 0.4875000000000000 6189 + 1.125000000000000 0.5000000000000000 6190 + 1.112500000000000 0.000000000000000 6191 + 1.112500000000000 0.01250000000000000 6192 + 1.112500000000000 0.02500000000000000 6193 + 1.112500000000000 0.03750000000000001 6194 + 1.112500000000000 0.05000000000000000 6195 + 1.112500000000000 0.06250000000000000 6196 + 1.112500000000000 0.07500000000000001 6197 + 1.112500000000000 0.08750000000000004 6198 + 1.112500000000000 0.1000000000000000 6199 + 1.112500000000000 0.1125000000000000 6200 + 1.112500000000000 0.1250000000000000 6201 + 1.112500000000000 0.1375000000000000 6202 + 1.112500000000000 0.1500000000000000 6203 + 1.112500000000000 0.1625000000000000 6204 + 1.112500000000000 0.1750000000000000 6205 + 1.112500000000000 0.1875000000000000 6206 + 1.112500000000000 0.2000000000000000 6207 + 1.112500000000000 0.2125000000000000 6208 + 1.112500000000000 0.2250000000000000 6209 + 1.112500000000000 0.2375000000000000 6210 + 1.112500000000000 0.2500000000000000 6211 + 1.112500000000000 0.2625000000000000 6212 + 1.112500000000000 0.2750000000000000 6213 + 1.112500000000000 0.2875000000000000 6214 + 1.112500000000000 0.3000000000000000 6215 + 1.112500000000000 0.3125000000000000 6216 + 1.112500000000000 0.3250000000000000 6217 + 1.112500000000000 0.3375000000000000 6218 + 1.112500000000000 0.3500000000000001 6219 + 1.112500000000000 0.3625000000000000 6220 + 1.112500000000000 0.3750000000000000 6221 + 1.112500000000000 0.3875000000000000 6222 + 1.112500000000000 0.4000000000000000 6223 + 1.112500000000000 0.4125000000000000 6224 + 1.112500000000000 0.4250000000000000 6225 + 1.112500000000000 0.4375000000000000 6226 + 1.112500000000000 0.4499999999999999 6227 + 1.112500000000000 0.4625000000000000 6228 + 1.112500000000000 0.4750000000000000 6229 + 1.112500000000000 0.4875000000000000 6230 + 1.112500000000000 0.5000000000000000 6231 + 1.100000000000000 0.000000000000000 6232 + 1.100000000000000 0.01250000000000000 6233 + 1.100000000000000 0.02500000000000000 6234 + 1.100000000000000 0.03750000000000001 6235 + 1.100000000000000 0.05000000000000000 6236 + 1.100000000000000 0.06250000000000000 6237 + 1.100000000000000 0.07500000000000001 6238 + 1.100000000000000 0.08750000000000004 6239 + 1.100000000000000 0.1000000000000000 6240 + 1.100000000000000 0.1125000000000000 6241 + 1.100000000000000 0.1250000000000000 6242 + 1.100000000000000 0.1375000000000000 6243 + 1.100000000000001 0.1500000000000000 6244 + 1.100000000000000 0.1625000000000000 6245 + 1.100000000000000 0.1750000000000000 6246 + 1.100000000000000 0.1875000000000000 6247 + 1.100000000000000 0.2000000000000000 6248 + 1.100000000000000 0.2125000000000000 6249 + 1.099999999999999 0.2250000000000001 6250 + 1.099999999999999 0.2375000000000000 6251 + 1.100000000000000 0.2500000000000000 6252 + 1.100000000000000 0.2625000000000000 6253 + 1.100000000000000 0.2750000000000000 6254 + 1.100000000000000 0.2875000000000000 6255 + 1.100000000000000 0.3000000000000000 6256 + 1.100000000000000 0.3125000000000000 6257 + 1.100000000000000 0.3250000000000000 6258 + 1.100000000000000 0.3375000000000000 6259 + 1.100000000000000 0.3500000000000000 6260 + 1.100000000000000 0.3625000000000000 6261 + 1.099999999999999 0.3750000000000000 6262 + 1.099999999999999 0.3874999999999999 6263 + 1.099999999999999 0.4000000000000000 6264 + 1.099999999999999 0.4125000000000000 6265 + 1.100000000000000 0.4250000000000000 6266 + 1.100000000000000 0.4375000000000000 6267 + 1.100000000000000 0.4500000000000000 6268 + 1.100000000000000 0.4625000000000000 6269 + 1.100000000000000 0.4750000000000001 6270 + 1.100000000000000 0.4875000000000000 6271 + 1.100000000000000 0.5000000000000000 6272 + 1.087500000000000 0.000000000000000 6273 + 1.087500000000000 0.01250000000000000 6274 + 1.087500000000000 0.02500000000000000 6275 + 1.087500000000000 0.03750000000000001 6276 + 1.087500000000000 0.05000000000000000 6277 + 1.087500000000000 0.06250000000000000 6278 + 1.087500000000000 0.07500000000000001 6279 + 1.087500000000000 0.08750000000000004 6280 + 1.087500000000001 0.1000000000000000 6281 + 1.087500000000000 0.1125000000000000 6282 + 1.087500000000000 0.1250000000000000 6283 + 1.087500000000000 0.1375000000000000 6284 + 1.087500000000000 0.1500000000000000 6285 + 1.087500000000000 0.1625000000000000 6286 + 1.087500000000000 0.1750000000000000 6287 + 1.087500000000000 0.1875000000000000 6288 + 1.087500000000000 0.2000000000000000 6289 + 1.087500000000000 0.2125000000000000 6290 + 1.087500000000000 0.2250000000000000 6291 + 1.087500000000000 0.2375000000000000 6292 + 1.087500000000000 0.2500000000000000 6293 + 1.087500000000000 0.2625000000000000 6294 + 1.087500000000000 0.2750000000000000 6295 + 1.087500000000000 0.2875000000000000 6296 + 1.087500000000000 0.3000000000000000 6297 + 1.087500000000000 0.3125000000000000 6298 + 1.087500000000000 0.3250000000000000 6299 + 1.087499999999999 0.3375000000000000 6300 + 1.087499999999999 0.3500000000000001 6301 + 1.087500000000000 0.3625000000000000 6302 + 1.087500000000000 0.3750000000000000 6303 + 1.087500000000000 0.3874999999999999 6304 + 1.087500000000000 0.4000000000000000 6305 + 1.087500000000000 0.4125000000000000 6306 + 1.087500000000000 0.4250000000000000 6307 + 1.087500000000000 0.4375000000000000 6308 + 1.087500000000000 0.4500000000000001 6309 + 1.087500000000000 0.4625000000000000 6310 + 1.087500000000000 0.4750000000000000 6311 + 1.087500000000000 0.4875000000000000 6312 + 1.087500000000000 0.5000000000000000 6313 + 1.075000000000000 0.000000000000000 6314 + 1.075000000000000 0.01250000000000000 6315 + 1.075000000000000 0.02500000000000000 6316 + 1.075000000000000 0.03750000000000001 6317 + 1.075000000000000 0.05000000000000000 6318 + 1.075000000000000 0.06250000000000000 6319 + 1.075000000000000 0.07500000000000001 6320 + 1.075000000000000 0.08750000000000001 6321 + 1.075000000000000 0.1000000000000000 6322 + 1.075000000000000 0.1125000000000000 6323 + 1.075000000000000 0.1250000000000000 6324 + 1.075000000000000 0.1375000000000000 6325 + 1.075000000000000 0.1500000000000000 6326 + 1.075000000000000 0.1625000000000000 6327 + 1.075000000000000 0.1750000000000000 6328 + 1.075000000000000 0.1875000000000000 6329 + 1.075000000000000 0.2000000000000000 6330 + 1.075000000000000 0.2125000000000000 6331 + 1.075000000000000 0.2250000000000000 6332 + 1.074999999999999 0.2375000000000000 6333 + 1.074999999999999 0.2500000000000000 6334 + 1.075000000000000 0.2625000000000000 6335 + 1.075000000000000 0.2750000000000000 6336 + 1.075000000000000 0.2875000000000000 6337 + 1.075000000000000 0.3000000000000000 6338 + 1.075000000000000 0.3125000000000000 6339 + 1.075000000000000 0.3250000000000000 6340 + 1.075000000000000 0.3375000000000000 6341 + 1.075000000000000 0.3500000000000000 6342 + 1.075000000000000 0.3625000000000000 6343 + 1.075000000000000 0.3750000000000000 6344 + 1.075000000000000 0.3875000000000000 6345 + 1.075000000000000 0.4000000000000000 6346 + 1.075000000000000 0.4125000000000001 6347 + 1.074999999999999 0.4250000000000000 6348 + 1.074999999999999 0.4375000000000000 6349 + 1.075000000000000 0.4500000000000000 6350 + 1.075000000000000 0.4625000000000000 6351 + 1.075000000000000 0.4750000000000000 6352 + 1.075000000000000 0.4875000000000000 6353 + 1.075000000000000 0.5000000000000000 6354 + 1.062500000000000 0.000000000000000 6355 + 1.062500000000000 0.01250000000000000 6356 + 1.062500000000000 0.02500000000000000 6357 + 1.062500000000000 0.03750000000000001 6358 + 1.062500000000000 0.05000000000000000 6359 + 1.062500000000000 0.06250000000000000 6360 + 1.062500000000000 0.07500000000000001 6361 + 1.062500000000000 0.08750000000000001 6362 + 1.062500000000000 0.1000000000000000 6363 + 1.062500000000000 0.1125000000000000 6364 + 1.062500000000000 0.1250000000000000 6365 + 1.062500000000000 0.1375000000000000 6366 + 1.062500000000000 0.1500000000000000 6367 + 1.062500000000000 0.1625000000000000 6368 + 1.062500000000000 0.1750000000000001 6369 + 1.062500000000000 0.1875000000000000 6370 + 1.062500000000000 0.2000000000000000 6371 + 1.062500000000000 0.2125000000000000 6372 + 1.062500000000000 0.2250000000000000 6373 + 1.062500000000000 0.2375000000000000 6374 + 1.062500000000000 0.2500000000000000 6375 + 1.062500000000000 0.2625000000000000 6376 + 1.062500000000000 0.2750000000000000 6377 + 1.062500000000000 0.2875000000000000 6378 + 1.062500000000000 0.3000000000000000 6379 + 1.062500000000000 0.3125000000000000 6380 + 1.062500000000000 0.3250000000000000 6381 + 1.062500000000000 0.3375000000000000 6382 + 1.062500000000000 0.3500000000000000 6383 + 1.062500000000000 0.3625000000000000 6384 + 1.062500000000000 0.3750000000000000 6385 + 1.062500000000000 0.3875000000000000 6386 + 1.062500000000000 0.4000000000000000 6387 + 1.062500000000000 0.4125000000000000 6388 + 1.062500000000000 0.4250000000000000 6389 + 1.062500000000000 0.4375000000000000 6390 + 1.062500000000000 0.4500000000000000 6391 + 1.062500000000000 0.4625000000000000 6392 + 1.062500000000000 0.4749999999999999 6393 + 1.062500000000000 0.4875000000000000 6394 + 1.062500000000000 0.5000000000000000 6395 + 1.050000000000000 0.000000000000000 6396 + 1.050000000000000 0.01250000000000000 6397 + 1.050000000000000 0.02500000000000000 6398 + 1.050000000000000 0.03750000000000001 6399 + 1.050000000000000 0.05000000000000000 6400 + 1.050000000000000 0.06250000000000000 6401 + 1.050000000000000 0.07500000000000001 6402 + 1.050000000000000 0.08750000000000001 6403 + 1.050000000000000 0.1000000000000000 6404 + 1.050000000000000 0.1125000000000000 6405 + 1.050000000000000 0.1250000000000000 6406 + 1.050000000000000 0.1375000000000000 6407 + 1.050000000000000 0.1500000000000000 6408 + 1.050000000000000 0.1625000000000000 6409 + 1.050000000000000 0.1750000000000001 6410 + 1.050000000000000 0.1875000000000000 6411 + 1.050000000000000 0.2000000000000000 6412 + 1.050000000000000 0.2125000000000000 6413 + 1.050000000000000 0.2250000000000000 6414 + 1.050000000000000 0.2375000000000000 6415 + 1.050000000000000 0.2500000000000000 6416 + 1.050000000000000 0.2625000000000000 6417 + 1.050000000000000 0.2750000000000000 6418 + 1.050000000000000 0.2875000000000000 6419 + 1.050000000000000 0.3000000000000000 6420 + 1.050000000000000 0.3125000000000000 6421 + 1.050000000000000 0.3250000000000000 6422 + 1.050000000000000 0.3375000000000000 6423 + 1.050000000000000 0.3500000000000000 6424 + 1.050000000000000 0.3625000000000000 6425 + 1.050000000000000 0.3750000000000000 6426 + 1.050000000000000 0.3875000000000000 6427 + 1.050000000000000 0.4000000000000000 6428 + 1.050000000000000 0.4124999999999999 6429 + 1.050000000000000 0.4250000000000000 6430 + 1.050000000000000 0.4375000000000000 6431 + 1.050000000000000 0.4500000000000001 6432 + 1.050000000000000 0.4625000000000000 6433 + 1.050000000000000 0.4750000000000001 6434 + 1.050000000000000 0.4875000000000000 6435 + 1.050000000000000 0.5000000000000000 6436 + 1.037500000000000 0.000000000000000 6437 + 1.037500000000000 0.01250000000000000 6438 + 1.037500000000000 0.02500000000000000 6439 + 1.037500000000000 0.03750000000000001 6440 + 1.037500000000000 0.05000000000000000 6441 + 1.037500000000000 0.06250000000000000 6442 + 1.037500000000000 0.07500000000000001 6443 + 1.037500000000000 0.08750000000000001 6444 + 1.037500000000000 0.1000000000000000 6445 + 1.037499999999999 0.1125000000000000 6446 + 1.037500000000000 0.1250000000000000 6447 + 1.037500000000000 0.1375000000000000 6448 + 1.037500000000000 0.1500000000000000 6449 + 1.037500000000000 0.1625000000000000 6450 + 1.037500000000000 0.1750000000000000 6451 + 1.037500000000000 0.1875000000000000 6452 + 1.037500000000000 0.2000000000000000 6453 + 1.037500000000000 0.2125000000000000 6454 + 1.037500000000000 0.2250000000000000 6455 + 1.037500000000001 0.2375000000000000 6456 + 1.037500000000001 0.2500000000000000 6457 + 1.037500000000000 0.2625000000000000 6458 + 1.037500000000000 0.2750000000000000 6459 + 1.037500000000000 0.2875000000000000 6460 + 1.037500000000000 0.3000000000000000 6461 + 1.037500000000000 0.3125000000000000 6462 + 1.037500000000000 0.3250000000000000 6463 + 1.037500000000000 0.3375000000000000 6464 + 1.037500000000000 0.3499999999999999 6465 + 1.037500000000000 0.3625000000000000 6466 + 1.037500000000000 0.3750000000000000 6467 + 1.037500000000000 0.3875000000000000 6468 + 1.037500000000000 0.4000000000000000 6469 + 1.037500000000000 0.4125000000000000 6470 + 1.037500000000001 0.4250000000000000 6471 + 1.037500000000001 0.4375000000000000 6472 + 1.037500000000000 0.4500000000000000 6473 + 1.037500000000000 0.4625000000000000 6474 + 1.037500000000000 0.4750000000000000 6475 + 1.037500000000000 0.4875000000000000 6476 + 1.037500000000000 0.5000000000000000 6477 + 1.025000000000000 0.000000000000000 6478 + 1.025000000000000 0.01250000000000000 6479 + 1.025000000000000 0.02500000000000000 6480 + 1.025000000000000 0.03750000000000001 6481 + 1.025000000000000 0.05000000000000000 6482 + 1.025000000000000 0.06250000000000000 6483 + 1.025000000000000 0.07500000000000001 6484 + 1.025000000000000 0.08749999999999998 6485 + 1.025000000000000 0.1000000000000000 6486 + 1.025000000000000 0.1125000000000000 6487 + 1.025000000000000 0.1250000000000000 6488 + 1.025000000000000 0.1375000000000000 6489 + 1.025000000000000 0.1500000000000000 6490 + 1.025000000000000 0.1625000000000000 6491 + 1.025000000000000 0.1750000000000000 6492 + 1.025000000000001 0.1875000000000000 6493 + 1.025000000000000 0.2000000000000000 6494 + 1.025000000000000 0.2125000000000000 6495 + 1.025000000000000 0.2250000000000000 6496 + 1.025000000000000 0.2375000000000000 6497 + 1.024999999999999 0.2500000000000000 6498 + 1.025000000000000 0.2625000000000000 6499 + 1.025000000000000 0.2750000000000000 6500 + 1.025000000000000 0.2875000000000000 6501 + 1.025000000000000 0.3000000000000000 6502 + 1.025000000000000 0.3125000000000000 6503 + 1.025000000000000 0.3250000000000000 6504 + 1.025000000000000 0.3375000000000000 6505 + 1.025000000000000 0.3499999999999999 6506 + 1.025000000000000 0.3625000000000000 6507 + 1.025000000000000 0.3750000000000000 6508 + 1.025000000000000 0.3875000000000000 6509 + 1.025000000000000 0.4000000000000000 6510 + 1.025000000000000 0.4125000000000000 6511 + 1.024999999999999 0.4250000000000000 6512 + 1.024999999999999 0.4375000000000000 6513 + 1.025000000000000 0.4499999999999999 6514 + 1.025000000000000 0.4625000000000000 6515 + 1.025000000000000 0.4749999999999999 6516 + 1.025000000000000 0.4875000000000000 6517 + 1.025000000000000 0.5000000000000000 6518 + 1.012500000000000 0.000000000000000 6519 + 1.012500000000000 0.01250000000000000 6520 + 1.012500000000000 0.02500000000000000 6521 + 1.012500000000000 0.03750000000000001 6522 + 1.012500000000000 0.05000000000000000 6523 + 1.012500000000000 0.06250000000000000 6524 + 1.012500000000000 0.07500000000000001 6525 + 1.012500000000000 0.08750000000000001 6526 + 1.012500000000000 0.1000000000000000 6527 + 1.012500000000000 0.1125000000000000 6528 + 1.012500000000000 0.1250000000000000 6529 + 1.012500000000000 0.1375000000000000 6530 + 1.012500000000000 0.1500000000000000 6531 + 1.012500000000000 0.1625000000000000 6532 + 1.012500000000000 0.1750000000000000 6533 + 1.012500000000000 0.1875000000000000 6534 + 1.012500000000000 0.2000000000000000 6535 + 1.012500000000000 0.2125000000000000 6536 + 1.012500000000000 0.2250000000000000 6537 + 1.012500000000000 0.2375000000000000 6538 + 1.012500000000000 0.2500000000000000 6539 + 1.012500000000000 0.2625000000000000 6540 + 1.012500000000000 0.2750000000000000 6541 + 1.012500000000000 0.2875000000000000 6542 + 1.012500000000000 0.3000000000000000 6543 + 1.012500000000000 0.3125000000000000 6544 + 1.012500000000000 0.3250000000000000 6545 + 1.012500000000000 0.3375000000000000 6546 + 1.012500000000000 0.3500000000000000 6547 + 1.012500000000000 0.3625000000000000 6548 + 1.012500000000000 0.3750000000000000 6549 + 1.012500000000000 0.3875000000000000 6550 + 1.012500000000000 0.4000000000000000 6551 + 1.012500000000000 0.4125000000000000 6552 + 1.012500000000000 0.4250000000000000 6553 + 1.012500000000000 0.4375000000000000 6554 + 1.012500000000000 0.4500000000000001 6555 + 1.012500000000000 0.4625000000000000 6556 + 1.012500000000000 0.4750000000000000 6557 + 1.012500000000000 0.4875000000000000 6558 + 1.012500000000000 0.5000000000000000 6559 + 1.000000000000000 0.000000000000000 6560 + 0.9999999999999998 0.01250000000000000 6561 + 1.000000000000000 0.02500000000000000 6562 + 0.9999999999999996 0.03750000000000001 6563 + 0.9999999999999998 0.05000000000000000 6564 + 1.000000000000000 0.06250000000000000 6565 + 1.000000000000000 0.07500000000000001 6566 + 0.9999999999999998 0.08750000000000001 6567 + 1.000000000000000 0.1000000000000000 6568 + 1.000000000000000 0.1125000000000000 6569 + 1.000000000000000 0.1250000000000000 6570 + 1.000000000000000 0.1375000000000000 6571 + 1.000000000000000 0.1500000000000000 6572 + 1.000000000000000 0.1625000000000000 6573 + 1.000000000000000 0.1750000000000000 6574 + 1.000000000000000 0.1875000000000000 6575 + 1.000000000000000 0.2000000000000000 6576 + 1.000000000000000 0.2125000000000000 6577 + 0.9999999999999998 0.2250000000000000 6578 + 0.9999999999999998 0.2375000000000000 6579 + 1.000000000000000 0.2500000000000000 6580 + 1.000000000000000 0.2625000000000000 6581 + 1.000000000000000 0.2750000000000000 6582 + 1.000000000000000 0.2875000000000000 6583 + 1.000000000000000 0.3000000000000000 6584 + 1.000000000000000 0.3125000000000000 6585 + 1.000000000000000 0.3250000000000000 6586 + 1.000000000000000 0.3375000000000000 6587 + 1.000000000000000 0.3500000000000000 6588 + 1.000000000000000 0.3625000000000000 6589 + 0.9999999999999998 0.3750000000000000 6590 + 0.9999999999999998 0.3875000000000001 6591 + 0.9999999999999998 0.4000000000000000 6592 + 0.9999999999999998 0.4125000000000000 6593 + 1.000000000000000 0.4250000000000000 6594 + 1.000000000000000 0.4375000000000000 6595 + 1.000000000000000 0.4500000000000001 6596 + 1.000000000000000 0.4625000000000000 6597 + 1.000000000000000 0.4750000000000000 6598 + 1.000000000000000 0.4875000000000000 6599 + 1.000000000000000 0.5000000000000000 6600 + 0.9875000000000000 0.000000000000000 6601 + 0.9874999999999998 0.01250000000000000 6602 + 0.9875000000000000 0.02500000000000000 6603 + 0.9875000000000000 0.03750000000000001 6604 + 0.9875000000000003 0.05000000000000000 6605 + 0.9875000000000002 0.06250000000000000 6606 + 0.9875000000000002 0.07500000000000001 6607 + 0.9875000000000000 0.08750000000000001 6608 + 0.9875000000000000 0.1000000000000000 6609 + 0.9875000000000003 0.1125000000000000 6610 + 0.9874999999999998 0.1250000000000000 6611 + 0.9874999999999998 0.1375000000000000 6612 + 0.9874999999999999 0.1500000000000000 6613 + 0.9874999999999997 0.1625000000000000 6614 + 0.9874999999999998 0.1750000000000000 6615 + 0.9874999999999998 0.1875000000000000 6616 + 0.9874999999999998 0.2000000000000000 6617 + 0.9874999999999998 0.2125000000000000 6618 + 0.9875000000000003 0.2250000000000000 6619 + 0.9874999999999997 0.2375000000000000 6620 + 0.9875000000000002 0.2500000000000000 6621 + 0.9874999999999998 0.2625000000000000 6622 + 0.9874999999999998 0.2750000000000000 6623 + 0.9874999999999998 0.2875000000000000 6624 + 0.9874999999999998 0.3000000000000000 6625 + 0.9874999999999998 0.3125000000000000 6626 + 0.9874999999999999 0.3250000000000000 6627 + 0.9874999999999998 0.3375000000000000 6628 + 0.9874999999999998 0.3500000000000000 6629 + 0.9874999999999998 0.3625000000000000 6630 + 0.9874999999999998 0.3750000000000000 6631 + 0.9874999999999998 0.3875000000000000 6632 + 0.9874999999999998 0.4000000000000000 6633 + 0.9874999999999997 0.4125000000000000 6634 + 0.9874999999999998 0.4250000000000000 6635 + 0.9874999999999998 0.4375000000000000 6636 + 0.9874999999999998 0.4500000000000000 6637 + 0.9874999999999998 0.4625000000000000 6638 + 0.9874999999999998 0.4750000000000001 6639 + 0.9874999999999998 0.4875000000000000 6640 + 0.9874999999999998 0.5000000000000000 6641 + 0.9750000000000001 0.000000000000000 6642 + 0.9750000000000001 0.01250000000000000 6643 + 0.9750000000000001 0.02500000000000000 6644 + 0.9750000000000000 0.03750000000000001 6645 + 0.9749999999999998 0.05000000000000000 6646 + 0.9750000000000001 0.06250000000000000 6647 + 0.9750000000000001 0.07500000000000001 6648 + 0.9749999999999999 0.08750000000000001 6649 + 0.9750000000000003 0.1000000000000000 6650 + 0.9750000000000001 0.1125000000000000 6651 + 0.9750000000000001 0.1250000000000000 6652 + 0.9750000000000004 0.1375000000000000 6653 + 0.9750000000000004 0.1500000000000000 6654 + 0.9750000000000001 0.1625000000000000 6655 + 0.9750000000000001 0.1750000000000000 6656 + 0.9750000000000001 0.1875000000000000 6657 + 0.9750000000000001 0.2000000000000000 6658 + 0.9750000000000001 0.2125000000000000 6659 + 0.9750000000000001 0.2250000000000001 6660 + 0.9749999999999998 0.2375000000000000 6661 + 0.9749999999999998 0.2500000000000000 6662 + 0.9750000000000001 0.2625000000000000 6663 + 0.9750000000000001 0.2750000000000000 6664 + 0.9750000000000001 0.2875000000000000 6665 + 0.9750000000000001 0.3000000000000000 6666 + 0.9750000000000001 0.3125000000000000 6667 + 0.9750000000000004 0.3250000000000000 6668 + 0.9750000000000004 0.3375000000000000 6669 + 0.9750000000000001 0.3500000000000000 6670 + 0.9750000000000001 0.3625000000000000 6671 + 0.9750000000000001 0.3750000000000000 6672 + 0.9750000000000001 0.3875000000000000 6673 + 0.9750000000000001 0.4000000000000000 6674 + 0.9750000000000001 0.4125000000000000 6675 + 0.9749999999999998 0.4250000000000000 6676 + 0.9749999999999998 0.4375000000000000 6677 + 0.9750000000000001 0.4500000000000000 6678 + 0.9750000000000001 0.4625000000000000 6679 + 0.9750000000000001 0.4750000000000001 6680 + 0.9750000000000001 0.4875000000000000 6681 + 0.9750000000000002 0.5000000000000000 6682 + 0.9625000000000000 0.000000000000000 6683 + 0.9624999999999999 0.01250000000000000 6684 + 0.9624999999999999 0.02500000000000000 6685 + 0.9625000000000000 0.03750000000000001 6686 + 0.9625000000000002 0.05000000000000000 6687 + 0.9624999999999999 0.06250000000000000 6688 + 0.9624999999999999 0.07500000000000001 6689 + 0.9625000000000001 0.08750000000000001 6690 + 0.9625000000000001 0.1000000000000000 6691 + 0.9624999999999999 0.1125000000000000 6692 + 0.9624999999999999 0.1250000000000000 6693 + 0.9624999999999996 0.1375000000000000 6694 + 0.9624999999999996 0.1500000000000000 6695 + 0.9624999999999999 0.1625000000000000 6696 + 0.9624999999999999 0.1750000000000000 6697 + 0.9624999999999999 0.1875000000000000 6698 + 0.9624999999999999 0.2000000000000000 6699 + 0.9624999999999999 0.2125000000000000 6700 + 0.9624999999999999 0.2250000000000000 6701 + 0.9625000000000002 0.2375000000000000 6702 + 0.9625000000000002 0.2500000000000000 6703 + 0.9624999999999999 0.2625000000000000 6704 + 0.9624999999999999 0.2750000000000000 6705 + 0.9624999999999999 0.2875000000000000 6706 + 0.9624999999999999 0.3000000000000000 6707 + 0.9624999999999999 0.3125000000000000 6708 + 0.9624999999999996 0.3250000000000000 6709 + 0.9624999999999996 0.3375000000000000 6710 + 0.9624999999999999 0.3500000000000000 6711 + 0.9624999999999999 0.3625000000000000 6712 + 0.9624999999999999 0.3750000000000000 6713 + 0.9624999999999999 0.3875000000000000 6714 + 0.9624999999999999 0.4000000000000000 6715 + 0.9624999999999999 0.4124999999999999 6716 + 0.9625000000000002 0.4250000000000000 6717 + 0.9625000000000002 0.4375000000000000 6718 + 0.9624999999999999 0.4500000000000001 6719 + 0.9624999999999999 0.4625000000000000 6720 + 0.9624999999999999 0.4750000000000000 6721 + 0.9624999999999999 0.4875000000000000 6722 + 0.9624999999999999 0.5000000000000000 6723 + 0.9500000000000001 0.000000000000000 6724 + 0.9499999999999998 0.01250000000000000 6725 + 0.9499999999999996 0.02500000000000000 6726 + 0.9500000000000002 0.03750000000000001 6727 + 0.9500000000000002 0.05000000000000000 6728 + 0.9500000000000002 0.06250000000000000 6729 + 0.9500000000000002 0.07500000000000001 6730 + 0.9500000000000002 0.08750000000000001 6731 + 0.9500000000000004 0.1000000000000000 6732 + 0.9500000000000001 0.1125000000000000 6733 + 0.9500000000000001 0.1250000000000000 6734 + 0.9500000000000001 0.1375000000000000 6735 + 0.9500000000000002 0.1500000000000000 6736 + 0.9500000000000000 0.1625000000000000 6737 + 0.9499999999999997 0.1750000000000000 6738 + 0.9499999999999997 0.1875000000000000 6739 + 0.9500000000000002 0.2000000000000000 6740 + 0.9499999999999998 0.2125000000000000 6741 + 0.9499999999999998 0.2250000000000000 6742 + 0.9499999999999998 0.2375000000000000 6743 + 0.9499999999999997 0.2500000000000000 6744 + 0.9500000000000002 0.2625000000000000 6745 + 0.9500000000000002 0.2750000000000000 6746 + 0.9499999999999997 0.2875000000000000 6747 + 0.9499999999999997 0.3000000000000000 6748 + 0.9500000000000001 0.3125000000000000 6749 + 0.9500000000000001 0.3250000000000000 6750 + 0.9500000000000001 0.3375000000000000 6751 + 0.9500000000000002 0.3500000000000000 6752 + 0.9499999999999997 0.3625000000000000 6753 + 0.9499999999999997 0.3750000000000000 6754 + 0.9499999999999997 0.3875000000000000 6755 + 0.9500000000000002 0.4000000000000000 6756 + 0.9499999999999998 0.4124999999999999 6757 + 0.9499999999999998 0.4250000000000000 6758 + 0.9499999999999998 0.4375000000000000 6759 + 0.9499999999999997 0.4500000000000000 6760 + 0.9500000000000002 0.4625000000000000 6761 + 0.9500000000000002 0.4750000000000000 6762 + 0.9500000000000002 0.4875000000000000 6763 + 0.9500000000000000 0.5000000000000000 6764 + 0.9375000000000000 0.000000000000000 6765 + 0.9374999999999999 0.01250000000000000 6766 + 0.9375000000000001 0.02500000000000000 6767 + 0.9375000000000000 0.03750000000000001 6768 + 0.9375000000000000 0.05000000000000000 6769 + 0.9375000000000000 0.06250000000000000 6770 + 0.9375000000000000 0.07500000000000001 6771 + 0.9375000000000000 0.08750000000000001 6772 + 0.9374999999999998 0.1000000000000000 6773 + 0.9375000000000001 0.1125000000000000 6774 + 0.9375000000000001 0.1250000000000000 6775 + 0.9375000000000001 0.1375000000000000 6776 + 0.9375000000000000 0.1500000000000000 6777 + 0.9374999999999998 0.1625000000000000 6778 + 0.9375000000000000 0.1750000000000000 6779 + 0.9375000000000000 0.1875000000000000 6780 + 0.9375000000000000 0.2000000000000000 6781 + 0.9374999999999999 0.2125000000000000 6782 + 0.9374999999999999 0.2250000000000000 6783 + 0.9374999999999999 0.2375000000000000 6784 + 0.9375000000000000 0.2500000000000000 6785 + 0.9375000000000000 0.2625000000000000 6786 + 0.9375000000000000 0.2750000000000000 6787 + 0.9375000000000000 0.2875000000000000 6788 + 0.9375000000000000 0.3000000000000000 6789 + 0.9375000000000001 0.3125000000000000 6790 + 0.9375000000000001 0.3250000000000000 6791 + 0.9375000000000001 0.3375000000000000 6792 + 0.9375000000000000 0.3500000000000000 6793 + 0.9375000000000000 0.3625000000000000 6794 + 0.9375000000000000 0.3750000000000000 6795 + 0.9375000000000000 0.3875000000000000 6796 + 0.9375000000000000 0.4000000000000000 6797 + 0.9374999999999999 0.4125000000000000 6798 + 0.9374999999999999 0.4250000000000000 6799 + 0.9374999999999999 0.4375000000000000 6800 + 0.9375000000000000 0.4500000000000001 6801 + 0.9375000000000000 0.4625000000000000 6802 + 0.9375000000000000 0.4750000000000001 6803 + 0.9375000000000000 0.4875000000000000 6804 + 0.9375000000000000 0.5000000000000000 6805 + 0.9250000000000000 0.000000000000000 6806 + 0.9249999999999999 0.01250000000000000 6807 + 0.9250000000000002 0.02500000000000000 6808 + 0.9250000000000003 0.03750000000000001 6809 + 0.9250000000000003 0.05000000000000000 6810 + 0.9249999999999998 0.06250000000000000 6811 + 0.9249999999999998 0.07500000000000001 6812 + 0.9249999999999998 0.08750000000000001 6813 + 0.9250000000000000 0.1000000000000000 6814 + 0.9250000000000002 0.1125000000000000 6815 + 0.9250000000000002 0.1250000000000000 6816 + 0.9249999999999998 0.1375000000000000 6817 + 0.9249999999999998 0.1500000000000000 6818 + 0.9250000000000000 0.1625000000000000 6819 + 0.9250000000000003 0.1750000000000000 6820 + 0.9249999999999998 0.1875000000000000 6821 + 0.9249999999999998 0.2000000000000000 6822 + 0.9249999999999999 0.2125000000000000 6823 + 0.9249999999999999 0.2250000000000001 6824 + 0.9250000000000003 0.2375000000000000 6825 + 0.9249999999999998 0.2500000000000000 6826 + 0.9249999999999998 0.2625000000000000 6827 + 0.9250000000000003 0.2750000000000000 6828 + 0.9250000000000003 0.2875000000000000 6829 + 0.9250000000000002 0.3000000000000000 6830 + 0.9250000000000002 0.3125000000000000 6831 + 0.9249999999999998 0.3250000000000000 6832 + 0.9249999999999998 0.3375000000000000 6833 + 0.9250000000000003 0.3500000000000000 6834 + 0.9250000000000003 0.3625000000000000 6835 + 0.9249999999999998 0.3750000000000000 6836 + 0.9249999999999998 0.3875000000000000 6837 + 0.9249999999999999 0.4000000000000000 6838 + 0.9249999999999999 0.4125000000000000 6839 + 0.9250000000000003 0.4250000000000000 6840 + 0.9250000000000003 0.4375000000000000 6841 + 0.9249999999999998 0.4500000000000000 6842 + 0.9249999999999998 0.4625000000000000 6843 + 0.9250000000000003 0.4750000000000000 6844 + 0.9250000000000003 0.4875000000000000 6845 + 0.9250000000000000 0.5000000000000000 6846 + 0.9125000000000001 0.000000000000000 6847 + 0.9125000000000004 0.01250000000000000 6848 + 0.9124999999999999 0.02500000000000000 6849 + 0.9125000000000003 0.03750000000000001 6850 + 0.9125000000000001 0.05000000000000000 6851 + 0.9125000000000001 0.06250000000000000 6852 + 0.9125000000000001 0.07500000000000001 6853 + 0.9125000000000000 0.08750000000000001 6854 + 0.9125000000000000 0.1000000000000000 6855 + 0.9124999999999998 0.1125000000000000 6856 + 0.9125000000000001 0.1250000000000000 6857 + 0.9125000000000001 0.1375000000000000 6858 + 0.9125000000000001 0.1500000000000000 6859 + 0.9125000000000003 0.1625000000000000 6860 + 0.9125000000000001 0.1750000000000000 6861 + 0.9125000000000004 0.1875000000000000 6862 + 0.9125000000000004 0.2000000000000000 6863 + 0.9125000000000004 0.2125000000000000 6864 + 0.9125000000000001 0.2250000000000001 6865 + 0.9125000000000001 0.2375000000000000 6866 + 0.9125000000000001 0.2500000000000000 6867 + 0.9125000000000001 0.2625000000000000 6868 + 0.9125000000000001 0.2750000000000000 6869 + 0.9124999999999998 0.2875000000000000 6870 + 0.9124999999999998 0.3000000000000000 6871 + 0.9124999999999998 0.3125000000000000 6872 + 0.9125000000000001 0.3250000000000000 6873 + 0.9125000000000001 0.3375000000000000 6874 + 0.9125000000000001 0.3500000000000000 6875 + 0.9125000000000001 0.3625000000000000 6876 + 0.9125000000000001 0.3750000000000000 6877 + 0.9125000000000004 0.3875000000000001 6878 + 0.9125000000000004 0.4000000000000000 6879 + 0.9125000000000004 0.4125000000000000 6880 + 0.9125000000000001 0.4250000000000000 6881 + 0.9125000000000001 0.4375000000000000 6882 + 0.9125000000000001 0.4500000000000001 6883 + 0.9125000000000001 0.4625000000000000 6884 + 0.9125000000000001 0.4750000000000001 6885 + 0.9124999999999998 0.4875000000000000 6886 + 0.9125000000000001 0.5000000000000000 6887 + 0.9000000000000000 0.000000000000000 6888 + 0.8999999999999999 0.01250000000000000 6889 + 0.9000000000000001 0.02500000000000000 6890 + 0.9000000000000001 0.03750000000000001 6891 + 0.9000000000000004 0.05000000000000000 6892 + 0.8999999999999999 0.06250000000000000 6893 + 0.8999999999999999 0.07500000000000001 6894 + 0.9000000000000000 0.08750000000000001 6895 + 0.9000000000000000 0.1000000000000000 6896 + 0.8999999999999999 0.1125000000000000 6897 + 0.9000000000000004 0.1250000000000000 6898 + 0.8999999999999999 0.1375000000000000 6899 + 0.8999999999999999 0.1500000000000000 6900 + 0.9000000000000001 0.1625000000000000 6901 + 0.8999999999999999 0.1750000000000000 6902 + 0.9000000000000000 0.1875000000000000 6903 + 0.9000000000000000 0.2000000000000000 6904 + 0.8999999999999999 0.2125000000000000 6905 + 0.8999999999999999 0.2250000000000000 6906 + 0.8999999999999999 0.2375000000000000 6907 + 0.9000000000000004 0.2500000000000000 6908 + 0.8999999999999999 0.2625000000000000 6909 + 0.9000000000000002 0.2750000000000000 6910 + 0.9000000000000002 0.2875000000000000 6911 + 0.9000000000000004 0.3000000000000000 6912 + 0.9000000000000004 0.3125000000000000 6913 + 0.8999999999999999 0.3250000000000000 6914 + 0.8999999999999999 0.3375000000000000 6915 + 0.9000000000000004 0.3500000000000000 6916 + 0.9000000000000004 0.3625000000000000 6917 + 0.9000000000000000 0.3750000000000000 6918 + 0.9000000000000000 0.3875000000000001 6919 + 0.8999999999999999 0.4000000000000000 6920 + 0.8999999999999999 0.4125000000000000 6921 + 0.9000000000000004 0.4250000000000000 6922 + 0.9000000000000004 0.4375000000000000 6923 + 0.8999999999999999 0.4500000000000001 6924 + 0.8999999999999999 0.4625000000000000 6925 + 0.9000000000000002 0.4749999999999999 6926 + 0.9000000000000002 0.4875000000000000 6927 + 0.9000000000000001 0.5000000000000000 6928 + 0.8875000000000001 0.000000000000000 6929 + 0.8875000000000002 0.01250000000000000 6930 + 0.8875000000000000 0.02500000000000000 6931 + 0.8875000000000000 0.03750000000000001 6932 + 0.8875000000000002 0.05000000000000000 6933 + 0.8875000000000002 0.06250000000000000 6934 + 0.8875000000000002 0.07500000000000001 6935 + 0.8874999999999996 0.08750000000000001 6936 + 0.8875000000000001 0.1000000000000000 6937 + 0.8874999999999997 0.1125000000000000 6938 + 0.8874999999999997 0.1250000000000000 6939 + 0.8875000000000002 0.1375000000000000 6940 + 0.8875000000000002 0.1500000000000000 6941 + 0.8875000000000000 0.1625000000000000 6942 + 0.8874999999999997 0.1750000000000000 6943 + 0.8875000000000001 0.1875000000000000 6944 + 0.8875000000000001 0.2000000000000000 6945 + 0.8875000000000002 0.2125000000000000 6946 + 0.8875000000000002 0.2250000000000000 6947 + 0.8874999999999997 0.2375000000000000 6948 + 0.8874999999999997 0.2500000000000000 6949 + 0.8875000000000002 0.2625000000000000 6950 + 0.8874999999999998 0.2750000000000000 6951 + 0.8874999999999998 0.2875000000000000 6952 + 0.8874999999999997 0.3000000000000000 6953 + 0.8874999999999997 0.3125000000000000 6954 + 0.8874999999999997 0.3250000000000000 6955 + 0.8874999999999997 0.3375000000000000 6956 + 0.8874999999999997 0.3500000000000000 6957 + 0.8874999999999997 0.3625000000000000 6958 + 0.8875000000000001 0.3750000000000000 6959 + 0.8875000000000001 0.3875000000000000 6960 + 0.8874999999999997 0.4000000000000000 6961 + 0.8874999999999997 0.4125000000000000 6962 + 0.8874999999999997 0.4250000000000000 6963 + 0.8874999999999997 0.4375000000000000 6964 + 0.8874999999999997 0.4500000000000000 6965 + 0.8874999999999997 0.4625000000000000 6966 + 0.8874999999999994 0.4750000000000001 6967 + 0.8874999999999994 0.4875000000000000 6968 + 0.8874999999999997 0.5000000000000000 6969 + 0.8750000000000000 0.000000000000000 6970 + 0.8750000000000000 0.01250000000000000 6971 + 0.8750000000000002 0.02500000000000000 6972 + 0.8750000000000002 0.03750000000000001 6973 + 0.8750000000000000 0.05000000000000000 6974 + 0.8750000000000000 0.06250000000000000 6975 + 0.8750000000000003 0.07500000000000001 6976 + 0.8750000000000001 0.08750000000000001 6977 + 0.8750000000000000 0.1000000000000000 6978 + 0.8750000000000000 0.1125000000000000 6979 + 0.8750000000000000 0.1250000000000000 6980 + 0.8750000000000000 0.1375000000000000 6981 + 0.8750000000000000 0.1500000000000000 6982 + 0.8750000000000002 0.1625000000000000 6983 + 0.8750000000000001 0.1750000000000000 6984 + 0.8750000000000001 0.1875000000000000 6985 + 0.8750000000000000 0.2000000000000000 6986 + 0.8750000000000000 0.2125000000000000 6987 + 0.8750000000000000 0.2250000000000000 6988 + 0.8750000000000000 0.2375000000000000 6989 + 0.8750000000000000 0.2500000000000000 6990 + 0.8750000000000000 0.2625000000000000 6991 + 0.8750000000000000 0.2750000000000000 6992 + 0.8750000000000003 0.2875000000000000 6993 + 0.8750000000000003 0.3000000000000000 6994 + 0.8750000000000000 0.3125000000000000 6995 + 0.8750000000000000 0.3250000000000000 6996 + 0.8750000000000000 0.3375000000000000 6997 + 0.8750000000000004 0.3500000000000000 6998 + 0.8750000000000000 0.3625000000000000 6999 + 0.8750000000000000 0.3750000000000000 7000 + 0.8750000000000001 0.3875000000000000 7001 + 0.8750000000000001 0.4000000000000000 7002 + 0.8750000000000004 0.4125000000000001 7003 + 0.8750000000000004 0.4250000000000000 7004 + 0.8750000000000000 0.4375000000000000 7005 + 0.8750000000000000 0.4500000000000000 7006 + 0.8750000000000004 0.4625000000000000 7007 + 0.8750000000000004 0.4750000000000001 7008 + 0.8750000000000003 0.4875000000000000 7009 + 0.8750000000000002 0.5000000000000000 7010 + 0.8625000000000000 0.000000000000000 7011 + 0.8624999999999998 0.01250000000000000 7012 + 0.8625000000000000 0.02500000000000000 7013 + 0.8625000000000000 0.03750000000000001 7014 + 0.8624999999999998 0.05000000000000000 7015 + 0.8624999999999998 0.06250000000000000 7016 + 0.8624999999999999 0.07500000000000001 7017 + 0.8624999999999997 0.08750000000000001 7018 + 0.8625000000000003 0.1000000000000000 7019 + 0.8625000000000003 0.1125000000000000 7020 + 0.8624999999999998 0.1250000000000000 7021 + 0.8624999999999998 0.1375000000000000 7022 + 0.8625000000000003 0.1500000000000000 7023 + 0.8625000000000000 0.1625000000000000 7024 + 0.8624999999999997 0.1750000000000000 7025 + 0.8625000000000002 0.1875000000000000 7026 + 0.8624999999999998 0.2000000000000000 7027 + 0.8624999999999998 0.2125000000000000 7028 + 0.8625000000000003 0.2250000000000001 7029 + 0.8624999999999998 0.2375000000000000 7030 + 0.8624999999999998 0.2500000000000000 7031 + 0.8624999999999998 0.2625000000000000 7032 + 0.8624999999999998 0.2750000000000000 7033 + 0.8624999999999999 0.2875000000000000 7034 + 0.8624999999999999 0.3000000000000000 7035 + 0.8624999999999998 0.3125000000000000 7036 + 0.8624999999999998 0.3250000000000000 7037 + 0.8624999999999998 0.3375000000000000 7038 + 0.8624999999999998 0.3500000000000000 7039 + 0.8624999999999998 0.3625000000000000 7040 + 0.8624999999999998 0.3750000000000000 7041 + 0.8625000000000002 0.3875000000000000 7042 + 0.8625000000000002 0.4000000000000000 7043 + 0.8624999999999998 0.4125000000000000 7044 + 0.8624999999999998 0.4250000000000000 7045 + 0.8624999999999998 0.4375000000000000 7046 + 0.8624999999999998 0.4500000000000000 7047 + 0.8624999999999998 0.4625000000000000 7048 + 0.8624999999999998 0.4750000000000001 7049 + 0.8624999999999999 0.4875000000000000 7050 + 0.8624999999999998 0.5000000000000000 7051 + 0.8500000000000001 0.000000000000000 7052 + 0.8500000000000001 0.01250000000000000 7053 + 0.8500000000000001 0.02500000000000000 7054 + 0.8499999999999999 0.03750000000000001 7055 + 0.8500000000000004 0.05000000000000000 7056 + 0.8500000000000004 0.06250000000000000 7057 + 0.8500000000000004 0.07500000000000001 7058 + 0.8499999999999999 0.08750000000000001 7059 + 0.8500000000000001 0.1000000000000000 7060 + 0.8500000000000001 0.1125000000000000 7061 + 0.8500000000000001 0.1250000000000000 7062 + 0.8500000000000001 0.1375000000000000 7063 + 0.8500000000000001 0.1500000000000000 7064 + 0.8500000000000003 0.1625000000000000 7065 + 0.8499999999999998 0.1750000000000000 7066 + 0.8499999999999998 0.1875000000000000 7067 + 0.8499999999999998 0.2000000000000000 7068 + 0.8500000000000001 0.2125000000000000 7069 + 0.8500000000000001 0.2250000000000000 7070 + 0.8500000000000001 0.2375000000000000 7071 + 0.8500000000000001 0.2500000000000000 7072 + 0.8500000000000001 0.2625000000000000 7073 + 0.8500000000000001 0.2750000000000000 7074 + 0.8500000000000001 0.2875000000000000 7075 + 0.8500000000000004 0.3000000000000000 7076 + 0.8500000000000004 0.3125000000000000 7077 + 0.8500000000000004 0.3250000000000000 7078 + 0.8500000000000001 0.3375000000000000 7079 + 0.8500000000000005 0.3500000000000000 7080 + 0.8500000000000001 0.3625000000000000 7081 + 0.8500000000000001 0.3750000000000000 7082 + 0.8500000000000001 0.3875000000000001 7083 + 0.8500000000000005 0.4000000000000000 7084 + 0.8500000000000001 0.4125000000000000 7085 + 0.8500000000000002 0.4250000000000000 7086 + 0.8500000000000002 0.4375000000000000 7087 + 0.8500000000000002 0.4500000000000001 7088 + 0.8500000000000001 0.4625000000000000 7089 + 0.8500000000000001 0.4750000000000000 7090 + 0.8500000000000005 0.4875000000000000 7091 + 0.8500000000000003 0.5000000000000000 7092 + 0.8375000000000000 0.000000000000000 7093 + 0.8374999999999999 0.01250000000000000 7094 + 0.8374999999999999 0.02500000000000000 7095 + 0.8375000000000001 0.03750000000000001 7096 + 0.8375000000000000 0.05000000000000000 7097 + 0.8375000000000000 0.06250000000000000 7098 + 0.8374999999999999 0.07500000000000001 7099 + 0.8375000000000001 0.08750000000000001 7100 + 0.8374999999999999 0.1000000000000000 7101 + 0.8374999999999999 0.1125000000000000 7102 + 0.8374999999999999 0.1250000000000000 7103 + 0.8374999999999999 0.1375000000000000 7104 + 0.8374999999999999 0.1500000000000000 7105 + 0.8375000000000000 0.1625000000000000 7106 + 0.8374999999999998 0.1750000000000000 7107 + 0.8374999999999998 0.1875000000000000 7108 + 0.8374999999999999 0.2000000000000000 7109 + 0.8374999999999999 0.2125000000000000 7110 + 0.8374999999999999 0.2250000000000000 7111 + 0.8374999999999999 0.2375000000000000 7112 + 0.8374999999999999 0.2500000000000000 7113 + 0.8374999999999999 0.2625000000000000 7114 + 0.8374999999999999 0.2750000000000000 7115 + 0.8375000000000000 0.2875000000000000 7116 + 0.8375000000000000 0.3000000000000000 7117 + 0.8374999999999999 0.3125000000000000 7118 + 0.8374999999999999 0.3250000000000000 7119 + 0.8374999999999999 0.3375000000000000 7120 + 0.8374999999999999 0.3500000000000000 7121 + 0.8374999999999999 0.3625000000000000 7122 + 0.8374999999999999 0.3750000000000000 7123 + 0.8374999999999999 0.3875000000000000 7124 + 0.8374999999999998 0.4000000000000000 7125 + 0.8374999999999998 0.4125000000000001 7126 + 0.8374999999999998 0.4250000000000000 7127 + 0.8374999999999999 0.4375000000000000 7128 + 0.8374999999999999 0.4500000000000001 7129 + 0.8374999999999999 0.4625000000000000 7130 + 0.8374999999999999 0.4750000000000000 7131 + 0.8374999999999999 0.4875000000000000 7132 + 0.8374999999999999 0.5000000000000000 7133 + 0.8250000000000001 0.000000000000000 7134 + 0.8250000000000002 0.01250000000000000 7135 + 0.8250000000000002 0.02500000000000000 7136 + 0.8250000000000000 0.03750000000000001 7137 + 0.8250000000000001 0.05000000000000000 7138 + 0.8250000000000001 0.06250000000000000 7139 + 0.8250000000000000 0.07500000000000001 7140 + 0.8250000000000000 0.08750000000000001 7141 + 0.8250000000000002 0.1000000000000000 7142 + 0.8250000000000000 0.1125000000000000 7143 + 0.8250000000000000 0.1250000000000000 7144 + 0.8250000000000000 0.1375000000000000 7145 + 0.8250000000000000 0.1500000000000000 7146 + 0.8250000000000001 0.1625000000000000 7147 + 0.8249999999999998 0.1750000000000000 7148 + 0.8249999999999998 0.1875000000000000 7149 + 0.8249999999999997 0.2000000000000000 7150 + 0.8249999999999997 0.2125000000000000 7151 + 0.8250000000000000 0.2250000000000000 7152 + 0.8249999999999997 0.2375000000000000 7153 + 0.8249999999999997 0.2500000000000000 7154 + 0.8249999999999997 0.2625000000000000 7155 + 0.8249999999999997 0.2750000000000000 7156 + 0.8249999999999996 0.2875000000000000 7157 + 0.8249999999999996 0.3000000000000000 7158 + 0.8249999999999997 0.3125000000000000 7159 + 0.8249999999999997 0.3250000000000000 7160 + 0.8249999999999997 0.3375000000000000 7161 + 0.8249999999999997 0.3500000000000000 7162 + 0.8249999999999997 0.3625000000000000 7163 + 0.8249999999999997 0.3750000000000000 7164 + 0.8249999999999997 0.3875000000000000 7165 + 0.8249999999999998 0.4000000000000000 7166 + 0.8249999999999994 0.4125000000000000 7167 + 0.8249999999999994 0.4250000000000000 7168 + 0.8249999999999997 0.4375000000000000 7169 + 0.8249999999999997 0.4500000000000000 7170 + 0.8249999999999997 0.4625000000000000 7171 + 0.8249999999999995 0.4750000000000000 7172 + 0.8249999999999995 0.4875000000000000 7173 + 0.8249999999999995 0.5000000000000000 7174 + 0.8125000000000000 0.000000000000000 7175 + 0.8125000000000000 0.01250000000000000 7176 + 0.8124999999999999 0.02500000000000000 7177 + 0.8124999999999999 0.03750000000000001 7178 + 0.8125000000000001 0.05000000000000000 7179 + 0.8125000000000000 0.06250000000000000 7180 + 0.8125000000000000 0.07500000000000001 7181 + 0.8125000000000000 0.08750000000000001 7182 + 0.8125000000000000 0.1000000000000000 7183 + 0.8125000000000000 0.1125000000000000 7184 + 0.8125000000000000 0.1250000000000000 7185 + 0.8125000000000000 0.1375000000000000 7186 + 0.8124999999999999 0.1500000000000000 7187 + 0.8125000000000001 0.1625000000000000 7188 + 0.8124999999999999 0.1750000000000000 7189 + 0.8125000000000000 0.1875000000000000 7190 + 0.8125000000000000 0.2000000000000000 7191 + 0.8125000000000000 0.2125000000000000 7192 + 0.8125000000000000 0.2250000000000000 7193 + 0.8125000000000000 0.2375000000000000 7194 + 0.8125000000000000 0.2500000000000000 7195 + 0.8125000000000000 0.2625000000000000 7196 + 0.8125000000000000 0.2750000000000000 7197 + 0.8125000000000001 0.2875000000000000 7198 + 0.8125000000000001 0.3000000000000000 7199 + 0.8125000000000001 0.3125000000000000 7200 + 0.8125000000000000 0.3250000000000000 7201 + 0.8125000000000000 0.3375000000000000 7202 + 0.8125000000000000 0.3500000000000000 7203 + 0.8125000000000000 0.3625000000000000 7204 + 0.8125000000000000 0.3750000000000000 7205 + 0.8125000000000000 0.3875000000000000 7206 + 0.8125000000000000 0.4000000000000000 7207 + 0.8125000000000000 0.4125000000000000 7208 + 0.8124999999999999 0.4250000000000000 7209 + 0.8124999999999999 0.4375000000000000 7210 + 0.8124999999999999 0.4500000000000000 7211 + 0.8125000000000000 0.4625000000000000 7212 + 0.8125000000000000 0.4750000000000000 7213 + 0.8125000000000000 0.4875000000000000 7214 + 0.8125000000000000 0.5000000000000000 7215 + 0.8000000000000000 0.000000000000000 7216 + 0.8000000000000000 0.01250000000000000 7217 + 0.7999999999999999 0.02500000000000000 7218 + 0.7999999999999999 0.03750000000000001 7219 + 0.8000000000000002 0.05000000000000000 7220 + 0.8000000000000000 0.06250000000000000 7221 + 0.8000000000000000 0.07500000000000001 7222 + 0.8000000000000000 0.08750000000000001 7223 + 0.8000000000000000 0.1000000000000000 7224 + 0.8000000000000000 0.1125000000000000 7225 + 0.8000000000000000 0.1250000000000000 7226 + 0.7999999999999998 0.1375000000000000 7227 + 0.7999999999999999 0.1500000000000000 7228 + 0.7999999999999997 0.1625000000000000 7229 + 0.7999999999999999 0.1750000000000000 7230 + 0.7999999999999998 0.1875000000000000 7231 + 0.7999999999999998 0.2000000000000000 7232 + 0.7999999999999998 0.2125000000000000 7233 + 0.7999999999999998 0.2250000000000000 7234 + 0.7999999999999998 0.2375000000000001 7235 + 0.7999999999999998 0.2500000000000000 7236 + 0.7999999999999998 0.2625000000000000 7237 + 0.7999999999999998 0.2750000000000000 7238 + 0.7999999999999997 0.2875000000000000 7239 + 0.7999999999999997 0.3000000000000000 7240 + 0.7999999999999997 0.3125000000000000 7241 + 0.7999999999999998 0.3250000000000000 7242 + 0.7999999999999998 0.3375000000000000 7243 + 0.7999999999999998 0.3500000000000000 7244 + 0.7999999999999998 0.3625000000000000 7245 + 0.7999999999999996 0.3750000000000000 7246 + 0.7999999999999996 0.3874999999999999 7247 + 0.7999999999999996 0.4000000000000000 7248 + 0.7999999999999996 0.4125000000000001 7249 + 0.7999999999999995 0.4250000000000000 7250 + 0.7999999999999995 0.4375000000000000 7251 + 0.7999999999999995 0.4500000000000001 7252 + 0.7999999999999996 0.4625000000000000 7253 + 0.7999999999999996 0.4750000000000000 7254 + 0.7999999999999996 0.4875000000000000 7255 + 0.7999999999999996 0.5000000000000000 7256 + 0.7875000000000001 0.000000000000000 7257 + 0.7875000000000001 0.01250000000000000 7258 + 0.7875000000000000 0.02500000000000000 7259 + 0.7875000000000000 0.03750000000000001 7260 + 0.7875000000000002 0.05000000000000000 7261 + 0.7875000000000001 0.06250000000000000 7262 + 0.7875000000000001 0.07500000000000001 7263 + 0.7875000000000001 0.08750000000000001 7264 + 0.7875000000000001 0.1000000000000000 7265 + 0.7875000000000001 0.1125000000000000 7266 + 0.7875000000000001 0.1250000000000000 7267 + 0.7875000000000001 0.1375000000000000 7268 + 0.7875000000000001 0.1500000000000000 7269 + 0.7875000000000001 0.1625000000000000 7270 + 0.7875000000000000 0.1750000000000000 7271 + 0.7875000000000000 0.1875000000000000 7272 + 0.7875000000000000 0.2000000000000000 7273 + 0.7875000000000001 0.2125000000000000 7274 + 0.7875000000000001 0.2250000000000001 7275 + 0.7875000000000001 0.2375000000000001 7276 + 0.7875000000000001 0.2500000000000000 7277 + 0.7875000000000001 0.2625000000000000 7278 + 0.7875000000000001 0.2750000000000000 7279 + 0.7875000000000001 0.2875000000000000 7280 + 0.7875000000000001 0.3000000000000000 7281 + 0.7875000000000001 0.3125000000000000 7282 + 0.7875000000000001 0.3250000000000000 7283 + 0.7875000000000002 0.3375000000000000 7284 + 0.7875000000000002 0.3500000000000000 7285 + 0.7875000000000002 0.3625000000000000 7286 + 0.7875000000000001 0.3750000000000000 7287 + 0.7875000000000001 0.3875000000000000 7288 + 0.7875000000000001 0.4000000000000000 7289 + 0.7875000000000001 0.4124999999999999 7290 + 0.7875000000000001 0.4250000000000000 7291 + 0.7875000000000001 0.4375000000000000 7292 + 0.7875000000000001 0.4500000000000000 7293 + 0.7875000000000001 0.4625000000000000 7294 + 0.7875000000000001 0.4749999999999999 7295 + 0.7875000000000000 0.4875000000000000 7296 + 0.7875000000000001 0.5000000000000000 7297 + 0.7750000000000000 0.000000000000000 7298 + 0.7750000000000002 0.01250000000000000 7299 + 0.7749999999999999 0.02500000000000000 7300 + 0.7749999999999999 0.03750000000000001 7301 + 0.7749999999999999 0.05000000000000000 7302 + 0.7749999999999999 0.06250000000000000 7303 + 0.7749999999999999 0.07500000000000001 7304 + 0.7750000000000001 0.08750000000000001 7305 + 0.7750000000000001 0.1000000000000000 7306 + 0.7749999999999999 0.1125000000000000 7307 + 0.7749999999999999 0.1250000000000000 7308 + 0.7750000000000000 0.1375000000000000 7309 + 0.7750000000000000 0.1500000000000000 7310 + 0.7749999999999998 0.1625000000000000 7311 + 0.7749999999999999 0.1750000000000000 7312 + 0.7749999999999999 0.1875000000000000 7313 + 0.7749999999999999 0.2000000000000000 7314 + 0.7749999999999999 0.2125000000000000 7315 + 0.7749999999999999 0.2250000000000000 7316 + 0.7749999999999999 0.2375000000000000 7317 + 0.7749999999999999 0.2500000000000000 7318 + 0.7749999999999999 0.2625000000000000 7319 + 0.7749999999999999 0.2750000000000000 7320 + 0.7749999999999999 0.2875000000000000 7321 + 0.7749999999999998 0.3000000000000000 7322 + 0.7749999999999998 0.3125000000000000 7323 + 0.7749999999999998 0.3250000000000000 7324 + 0.7749999999999999 0.3375000000000000 7325 + 0.7749999999999999 0.3500000000000000 7326 + 0.7749999999999997 0.3625000000000000 7327 + 0.7749999999999999 0.3750000000000000 7328 + 0.7749999999999997 0.3875000000000000 7329 + 0.7749999999999997 0.4000000000000000 7330 + 0.7749999999999997 0.4125000000000001 7331 + 0.7749999999999999 0.4250000000000000 7332 + 0.7749999999999999 0.4375000000000000 7333 + 0.7749999999999996 0.4500000000000000 7334 + 0.7749999999999996 0.4625000000000000 7335 + 0.7749999999999996 0.4750000000000000 7336 + 0.7749999999999997 0.4875000000000000 7337 + 0.7749999999999997 0.5000000000000000 7338 + 0.7625000000000001 0.000000000000000 7339 + 0.7624999999999998 0.01250000000000000 7340 + 0.7625000000000000 0.02500000000000000 7341 + 0.7625000000000002 0.03750000000000001 7342 + 0.7625000000000000 0.05000000000000000 7343 + 0.7625000000000000 0.06250000000000000 7344 + 0.7625000000000002 0.07500000000000001 7345 + 0.7625000000000000 0.08750000000000001 7346 + 0.7625000000000000 0.1000000000000000 7347 + 0.7625000000000002 0.1125000000000000 7348 + 0.7625000000000000 0.1250000000000000 7349 + 0.7625000000000001 0.1375000000000000 7350 + 0.7625000000000001 0.1500000000000000 7351 + 0.7624999999999998 0.1625000000000000 7352 + 0.7625000000000000 0.1750000000000000 7353 + 0.7625000000000000 0.1875000000000000 7354 + 0.7625000000000000 0.2000000000000000 7355 + 0.7625000000000000 0.2125000000000000 7356 + 0.7625000000000000 0.2250000000000000 7357 + 0.7624999999999997 0.2375000000000001 7358 + 0.7625000000000000 0.2500000000000000 7359 + 0.7625000000000000 0.2625000000000000 7360 + 0.7625000000000000 0.2750000000000000 7361 + 0.7625000000000000 0.2875000000000000 7362 + 0.7624999999999998 0.3000000000000000 7363 + 0.7624999999999998 0.3125000000000000 7364 + 0.7624999999999998 0.3250000000000000 7365 + 0.7624999999999997 0.3375000000000000 7366 + 0.7624999999999997 0.3500000000000000 7367 + 0.7624999999999997 0.3625000000000000 7368 + 0.7624999999999997 0.3750000000000000 7369 + 0.7624999999999997 0.3874999999999999 7370 + 0.7624999999999997 0.4000000000000000 7371 + 0.7624999999999997 0.4125000000000000 7372 + 0.7624999999999997 0.4250000000000000 7373 + 0.7624999999999997 0.4375000000000000 7374 + 0.7624999999999996 0.4500000000000001 7375 + 0.7624999999999996 0.4625000000000000 7376 + 0.7624999999999996 0.4750000000000001 7377 + 0.7624999999999997 0.4875000000000000 7378 + 0.7624999999999997 0.5000000000000000 7379 + 0.7500000000000000 0.000000000000000 7380 + 0.7500000000000000 0.01250000000000000 7381 + 0.7499999999999998 0.02500000000000000 7382 + 0.7500000000000002 0.03750000000000001 7383 + 0.7500000000000000 0.05000000000000000 7384 + 0.7500000000000000 0.06250000000000000 7385 + 0.7500000000000000 0.07500000000000001 7386 + 0.7500000000000000 0.08750000000000001 7387 + 0.7499999999999999 0.1000000000000000 7388 + 0.7500000000000001 0.1125000000000000 7389 + 0.7500000000000001 0.1250000000000000 7390 + 0.7500000000000000 0.1375000000000000 7391 + 0.7500000000000000 0.1500000000000000 7392 + 0.7500000000000000 0.1625000000000000 7393 + 0.7500000000000000 0.1750000000000000 7394 + 0.7500000000000000 0.1875000000000000 7395 + 0.7500000000000000 0.2000000000000000 7396 + 0.7500000000000000 0.2125000000000000 7397 + 0.7500000000000000 0.2250000000000000 7398 + 0.7499999999999998 0.2375000000000000 7399 + 0.7499999999999999 0.2500000000000000 7400 + 0.7499999999999999 0.2625000000000000 7401 + 0.7499999999999999 0.2750000000000000 7402 + 0.7499999999999999 0.2875000000000000 7403 + 0.7500000000000000 0.3000000000000000 7404 + 0.7500000000000000 0.3125000000000000 7405 + 0.7499999999999998 0.3250000000000000 7406 + 0.7499999999999998 0.3375000000000000 7407 + 0.7500000000000000 0.3500000000000000 7408 + 0.7500000000000000 0.3625000000000000 7409 + 0.7499999999999998 0.3750000000000000 7410 + 0.7499999999999998 0.3875000000000000 7411 + 0.7499999999999998 0.4000000000000000 7412 + 0.7499999999999997 0.4125000000000000 7413 + 0.7499999999999997 0.4250000000000000 7414 + 0.7499999999999997 0.4375000000000000 7415 + 0.7499999999999998 0.4500000000000001 7416 + 0.7499999999999998 0.4625000000000000 7417 + 0.7499999999999998 0.4750000000000001 7418 + 0.7499999999999998 0.4875000000000000 7419 + 0.7499999999999998 0.5000000000000000 7420 + 0.7375000000000000 0.000000000000000 7421 + 0.7375000000000000 0.01250000000000000 7422 + 0.7375000000000000 0.02500000000000000 7423 + 0.7375000000000000 0.03750000000000001 7424 + 0.7375000000000000 0.05000000000000000 7425 + 0.7375000000000000 0.06250000000000000 7426 + 0.7375000000000000 0.07500000000000001 7427 + 0.7374999999999998 0.08750000000000001 7428 + 0.7374999999999999 0.1000000000000000 7429 + 0.7375000000000002 0.1125000000000000 7430 + 0.7375000000000002 0.1250000000000000 7431 + 0.7374999999999998 0.1375000000000000 7432 + 0.7374999999999998 0.1500000000000000 7433 + 0.7375000000000000 0.1625000000000000 7434 + 0.7374999999999998 0.1750000000000000 7435 + 0.7374999999999998 0.1875000000000000 7436 + 0.7374999999999998 0.2000000000000000 7437 + 0.7375000000000000 0.2125000000000000 7438 + 0.7375000000000000 0.2250000000000000 7439 + 0.7374999999999998 0.2375000000000000 7440 + 0.7374999999999999 0.2500000000000000 7441 + 0.7374999999999999 0.2625000000000000 7442 + 0.7374999999999999 0.2750000000000000 7443 + 0.7374999999999999 0.2875000000000000 7444 + 0.7374999999999998 0.3000000000000000 7445 + 0.7374999999999998 0.3125000000000000 7446 + 0.7374999999999998 0.3250000000000000 7447 + 0.7374999999999998 0.3375000000000000 7448 + 0.7374999999999998 0.3500000000000000 7449 + 0.7374999999999998 0.3625000000000000 7450 + 0.7374999999999998 0.3750000000000000 7451 + 0.7374999999999998 0.3875000000000001 7452 + 0.7374999999999998 0.4000000000000000 7453 + 0.7374999999999997 0.4125000000000000 7454 + 0.7375000000000002 0.4250000000000000 7455 + 0.7374999999999997 0.4375000000000000 7456 + 0.7374999999999998 0.4499999999999999 7457 + 0.7374999999999998 0.4625000000000000 7458 + 0.7374999999999998 0.4750000000000001 7459 + 0.7374999999999998 0.4875000000000000 7460 + 0.7374999999999998 0.5000000000000000 7461 + 0.7250000000000001 0.000000000000000 7462 + 0.7250000000000001 0.01250000000000000 7463 + 0.7250000000000001 0.02500000000000000 7464 + 0.7250000000000001 0.03750000000000001 7465 + 0.7250000000000001 0.05000000000000000 7466 + 0.7250000000000001 0.06250000000000000 7467 + 0.7250000000000001 0.07500000000000001 7468 + 0.7250000000000001 0.08750000000000001 7469 + 0.7250000000000000 0.1000000000000000 7470 + 0.7250000000000002 0.1125000000000000 7471 + 0.7250000000000002 0.1250000000000000 7472 + 0.7250000000000001 0.1375000000000000 7473 + 0.7250000000000001 0.1500000000000000 7474 + 0.7250000000000001 0.1625000000000000 7475 + 0.7250000000000001 0.1750000000000000 7476 + 0.7250000000000001 0.1875000000000000 7477 + 0.7250000000000001 0.2000000000000000 7478 + 0.7250000000000001 0.2125000000000000 7479 + 0.7250000000000001 0.2250000000000000 7480 + 0.7250000000000000 0.2375000000000000 7481 + 0.7250000000000000 0.2500000000000000 7482 + 0.7250000000000000 0.2625000000000000 7483 + 0.7249999999999999 0.2750000000000000 7484 + 0.7250000000000001 0.2875000000000000 7485 + 0.7250000000000001 0.3000000000000000 7486 + 0.7249999999999999 0.3125000000000000 7487 + 0.7250000000000001 0.3250000000000000 7488 + 0.7250000000000001 0.3375000000000000 7489 + 0.7249999999999999 0.3500000000000000 7490 + 0.7250000000000001 0.3625000000000000 7491 + 0.7249999999999998 0.3750000000000000 7492 + 0.7249999999999998 0.3875000000000000 7493 + 0.7249999999999998 0.4000000000000000 7494 + 0.7249999999999999 0.4125000000000000 7495 + 0.7249999999999999 0.4250000000000000 7496 + 0.7249999999999999 0.4375000000000000 7497 + 0.7249999999999999 0.4499999999999999 7498 + 0.7249999999999999 0.4625000000000000 7499 + 0.7250000000000001 0.4750000000000001 7500 + 0.7249999999999999 0.4875000000000000 7501 + 0.7249999999999999 0.5000000000000000 7502 + 0.7125000000000000 0.000000000000000 7503 + 0.7124999999999999 0.01250000000000000 7504 + 0.7124999999999999 0.02500000000000000 7505 + 0.7125000000000001 0.03750000000000001 7506 + 0.7124999999999999 0.05000000000000000 7507 + 0.7124999999999998 0.06250000000000000 7508 + 0.7124999999999998 0.07500000000000001 7509 + 0.7125000000000000 0.08750000000000001 7510 + 0.7124999999999999 0.1000000000000000 7511 + 0.7124999999999999 0.1125000000000000 7512 + 0.7124999999999999 0.1250000000000000 7513 + 0.7124999999999999 0.1375000000000000 7514 + 0.7124999999999999 0.1500000000000000 7515 + 0.7125000000000001 0.1625000000000000 7516 + 0.7124999999999999 0.1750000000000000 7517 + 0.7124999999999999 0.1875000000000000 7518 + 0.7124999999999999 0.2000000000000000 7519 + 0.7125000000000000 0.2125000000000000 7520 + 0.7125000000000000 0.2250000000000000 7521 + 0.7125000000000000 0.2375000000000000 7522 + 0.7125000000000000 0.2500000000000000 7523 + 0.7124999999999999 0.2625000000000000 7524 + 0.7124999999999999 0.2750000000000000 7525 + 0.7124999999999999 0.2875000000000000 7526 + 0.7124999999999999 0.3000000000000000 7527 + 0.7124999999999999 0.3125000000000000 7528 + 0.7124999999999999 0.3250000000000000 7529 + 0.7124999999999999 0.3375000000000000 7530 + 0.7124999999999999 0.3500000000000000 7531 + 0.7124999999999999 0.3625000000000000 7532 + 0.7124999999999998 0.3750000000000000 7533 + 0.7124999999999998 0.3875000000000000 7534 + 0.7124999999999998 0.4000000000000000 7535 + 0.7124999999999999 0.4124999999999999 7536 + 0.7124999999999999 0.4250000000000000 7537 + 0.7124999999999999 0.4375000000000000 7538 + 0.7124999999999999 0.4500000000000000 7539 + 0.7124999999999999 0.4625000000000000 7540 + 0.7124999999999999 0.4750000000000000 7541 + 0.7124999999999999 0.4875000000000000 7542 + 0.7124999999999999 0.5000000000000000 7543 + 0.7000000000000001 0.000000000000000 7544 + 0.7000000000000000 0.01250000000000000 7545 + 0.7000000000000002 0.02500000000000000 7546 + 0.7000000000000000 0.03750000000000001 7547 + 0.7000000000000002 0.05000000000000000 7548 + 0.6999999999999998 0.06250000000000000 7549 + 0.6999999999999998 0.07500000000000001 7550 + 0.7000000000000001 0.08750000000000001 7551 + 0.7000000000000000 0.1000000000000000 7552 + 0.7000000000000000 0.1125000000000000 7553 + 0.7000000000000000 0.1250000000000000 7554 + 0.7000000000000000 0.1375000000000000 7555 + 0.7000000000000000 0.1500000000000000 7556 + 0.7000000000000000 0.1625000000000000 7557 + 0.6999999999999997 0.1750000000000000 7558 + 0.7000000000000000 0.1875000000000000 7559 + 0.7000000000000001 0.2000000000000000 7560 + 0.7000000000000001 0.2125000000000000 7561 + 0.7000000000000001 0.2250000000000000 7562 + 0.6999999999999997 0.2375000000000000 7563 + 0.6999999999999997 0.2500000000000000 7564 + 0.6999999999999997 0.2625000000000000 7565 + 0.6999999999999997 0.2750000000000000 7566 + 0.6999999999999997 0.2875000000000000 7567 + 0.6999999999999997 0.3000000000000000 7568 + 0.6999999999999997 0.3125000000000000 7569 + 0.6999999999999997 0.3250000000000000 7570 + 0.6999999999999997 0.3375000000000000 7571 + 0.6999999999999998 0.3500000000000000 7572 + 0.6999999999999998 0.3625000000000000 7573 + 0.6999999999999998 0.3750000000000000 7574 + 0.6999999999999997 0.3874999999999999 7575 + 0.6999999999999997 0.4000000000000000 7576 + 0.6999999999999997 0.4125000000000001 7577 + 0.6999999999999997 0.4250000000000000 7578 + 0.6999999999999997 0.4375000000000000 7579 + 0.6999999999999997 0.4500000000000000 7580 + 0.6999999999999997 0.4625000000000000 7581 + 0.6999999999999997 0.4750000000000001 7582 + 0.6999999999999996 0.4875000000000000 7583 + 0.6999999999999996 0.5000000000000000 7584 + 0.6875000000000000 0.000000000000000 7585 + 0.6875000000000000 0.01250000000000000 7586 + 0.6875000000000000 0.02500000000000000 7587 + 0.6875000000000000 0.03750000000000001 7588 + 0.6875000000000000 0.05000000000000000 7589 + 0.6874999999999999 0.06250000000000000 7590 + 0.6874999999999999 0.07500000000000001 7591 + 0.6875000000000001 0.08750000000000001 7592 + 0.6875000000000000 0.1000000000000000 7593 + 0.6875000000000000 0.1125000000000000 7594 + 0.6875000000000000 0.1250000000000000 7595 + 0.6875000000000000 0.1375000000000000 7596 + 0.6875000000000000 0.1500000000000000 7597 + 0.6875000000000000 0.1625000000000000 7598 + 0.6875000000000000 0.1750000000000000 7599 + 0.6875000000000000 0.1875000000000000 7600 + 0.6875000000000000 0.2000000000000000 7601 + 0.6875000000000001 0.2125000000000000 7602 + 0.6875000000000001 0.2250000000000000 7603 + 0.6875000000000001 0.2375000000000000 7604 + 0.6875000000000001 0.2500000000000000 7605 + 0.6875000000000000 0.2625000000000000 7606 + 0.6875000000000000 0.2750000000000000 7607 + 0.6875000000000000 0.2875000000000000 7608 + 0.6875000000000000 0.3000000000000000 7609 + 0.6875000000000000 0.3125000000000000 7610 + 0.6875000000000000 0.3250000000000000 7611 + 0.6875000000000000 0.3375000000000000 7612 + 0.6875000000000000 0.3500000000000000 7613 + 0.6875000000000000 0.3625000000000000 7614 + 0.6874999999999999 0.3750000000000000 7615 + 0.6874999999999999 0.3875000000000001 7616 + 0.6874999999999999 0.4000000000000000 7617 + 0.6875000000000000 0.4125000000000001 7618 + 0.6875000000000000 0.4250000000000000 7619 + 0.6875000000000000 0.4375000000000000 7620 + 0.6875000000000000 0.4500000000000000 7621 + 0.6875000000000000 0.4625000000000000 7622 + 0.6875000000000000 0.4750000000000001 7623 + 0.6875000000000000 0.4875000000000000 7624 + 0.6875000000000000 0.5000000000000000 7625 + 0.6750000000000000 0.000000000000000 7626 + 0.6750000000000000 0.01250000000000000 7627 + 0.6749999999999997 0.02500000000000000 7628 + 0.6750000000000002 0.03750000000000001 7629 + 0.6749999999999999 0.05000000000000000 7630 + 0.6750000000000000 0.06250000000000000 7631 + 0.6749999999999998 0.07500000000000001 7632 + 0.6750000000000000 0.08750000000000001 7633 + 0.6750000000000000 0.1000000000000000 7634 + 0.6750000000000000 0.1125000000000000 7635 + 0.6750000000000000 0.1250000000000000 7636 + 0.6749999999999998 0.1375000000000000 7637 + 0.6749999999999998 0.1500000000000000 7638 + 0.6750000000000000 0.1625000000000000 7639 + 0.6750000000000002 0.1750000000000000 7640 + 0.6749999999999997 0.1875000000000000 7641 + 0.6750000000000002 0.2000000000000000 7642 + 0.6749999999999998 0.2125000000000000 7643 + 0.6749999999999998 0.2250000000000000 7644 + 0.6749999999999998 0.2375000000000000 7645 + 0.6749999999999998 0.2500000000000000 7646 + 0.6749999999999998 0.2625000000000000 7647 + 0.6749999999999998 0.2750000000000000 7648 + 0.6749999999999998 0.2875000000000000 7649 + 0.6749999999999998 0.3000000000000000 7650 + 0.6749999999999998 0.3125000000000000 7651 + 0.6749999999999998 0.3250000000000000 7652 + 0.6749999999999999 0.3375000000000000 7653 + 0.6749999999999999 0.3500000000000000 7654 + 0.6749999999999999 0.3625000000000000 7655 + 0.6749999999999998 0.3750000000000000 7656 + 0.6749999999999998 0.3875000000000000 7657 + 0.6749999999999998 0.4000000000000000 7658 + 0.6749999999999998 0.4125000000000001 7659 + 0.6749999999999998 0.4250000000000000 7660 + 0.6749999999999998 0.4375000000000000 7661 + 0.6749999999999998 0.4499999999999999 7662 + 0.6749999999999998 0.4625000000000000 7663 + 0.6749999999999998 0.4750000000000000 7664 + 0.6749999999999997 0.4875000000000000 7665 + 0.6749999999999997 0.5000000000000000 7666 + 0.6625000000000001 0.000000000000000 7667 + 0.6625000000000001 0.01250000000000000 7668 + 0.6625000000000001 0.02500000000000000 7669 + 0.6625000000000003 0.03750000000000001 7670 + 0.6625000000000000 0.05000000000000000 7671 + 0.6625000000000000 0.06250000000000000 7672 + 0.6625000000000001 0.07500000000000001 7673 + 0.6625000000000001 0.08750000000000001 7674 + 0.6625000000000001 0.1000000000000000 7675 + 0.6625000000000001 0.1125000000000000 7676 + 0.6625000000000001 0.1250000000000000 7677 + 0.6625000000000001 0.1375000000000000 7678 + 0.6625000000000001 0.1500000000000000 7679 + 0.6625000000000001 0.1625000000000000 7680 + 0.6625000000000001 0.1750000000000000 7681 + 0.6625000000000002 0.1875000000000000 7682 + 0.6625000000000002 0.2000000000000000 7683 + 0.6625000000000002 0.2125000000000000 7684 + 0.6625000000000002 0.2250000000000000 7685 + 0.6625000000000001 0.2375000000000000 7686 + 0.6625000000000001 0.2500000000000000 7687 + 0.6625000000000001 0.2625000000000000 7688 + 0.6625000000000001 0.2750000000000000 7689 + 0.6625000000000001 0.2875000000000000 7690 + 0.6625000000000001 0.3000000000000000 7691 + 0.6625000000000001 0.3125000000000000 7692 + 0.6625000000000001 0.3250000000000000 7693 + 0.6625000000000001 0.3375000000000000 7694 + 0.6625000000000001 0.3500000000000000 7695 + 0.6625000000000000 0.3625000000000000 7696 + 0.6625000000000000 0.3750000000000000 7697 + 0.6625000000000000 0.3874999999999999 7698 + 0.6625000000000001 0.4000000000000000 7699 + 0.6625000000000001 0.4125000000000001 7700 + 0.6625000000000001 0.4250000000000000 7701 + 0.6625000000000001 0.4375000000000000 7702 + 0.6625000000000001 0.4500000000000001 7703 + 0.6625000000000001 0.4625000000000000 7704 + 0.6625000000000001 0.4750000000000000 7705 + 0.6625000000000001 0.4875000000000000 7706 + 0.6625000000000001 0.5000000000000000 7707 + 0.6500000000000000 0.000000000000000 7708 + 0.6500000000000000 0.01250000000000000 7709 + 0.6499999999999999 0.02500000000000000 7710 + 0.6499999999999999 0.03750000000000001 7711 + 0.6499999999999999 0.05000000000000000 7712 + 0.6499999999999999 0.06250000000000000 7713 + 0.6499999999999999 0.07500000000000001 7714 + 0.6500000000000000 0.08750000000000001 7715 + 0.6500000000000000 0.1000000000000000 7716 + 0.6500000000000001 0.1125000000000000 7717 + 0.6500000000000001 0.1250000000000000 7718 + 0.6499999999999999 0.1375000000000000 7719 + 0.6499999999999998 0.1500000000000000 7720 + 0.6500000000000001 0.1625000000000000 7721 + 0.6499999999999998 0.1750000000000000 7722 + 0.6499999999999998 0.1875000000000000 7723 + 0.6499999999999999 0.2000000000000000 7724 + 0.6499999999999999 0.2125000000000000 7725 + 0.6499999999999999 0.2250000000000000 7726 + 0.6499999999999999 0.2375000000000000 7727 + 0.6499999999999999 0.2500000000000000 7728 + 0.6499999999999999 0.2625000000000000 7729 + 0.6499999999999999 0.2750000000000000 7730 + 0.6499999999999999 0.2875000000000000 7731 + 0.6499999999999999 0.3000000000000000 7732 + 0.6500000000000000 0.3125000000000000 7733 + 0.6500000000000000 0.3250000000000000 7734 + 0.6500000000000000 0.3375000000000000 7735 + 0.6500000000000000 0.3500000000000000 7736 + 0.6499999999999997 0.3625000000000000 7737 + 0.6499999999999997 0.3750000000000000 7738 + 0.6499999999999997 0.3875000000000000 7739 + 0.6499999999999999 0.4000000000000000 7740 + 0.6499999999999999 0.4125000000000000 7741 + 0.6499999999999999 0.4250000000000000 7742 + 0.6499999999999999 0.4375000000000000 7743 + 0.6499999999999999 0.4500000000000001 7744 + 0.6499999999999999 0.4625000000000000 7745 + 0.6499999999999999 0.4750000000000000 7746 + 0.6499999999999998 0.4875000000000000 7747 + 0.6499999999999998 0.5000000000000000 7748 + 0.6375000000000001 0.000000000000000 7749 + 0.6375000000000001 0.01250000000000000 7750 + 0.6375000000000000 0.02500000000000000 7751 + 0.6375000000000002 0.03750000000000001 7752 + 0.6375000000000000 0.05000000000000000 7753 + 0.6375000000000002 0.06250000000000000 7754 + 0.6375000000000000 0.07500000000000001 7755 + 0.6375000000000001 0.08750000000000001 7756 + 0.6375000000000001 0.1000000000000000 7757 + 0.6375000000000002 0.1125000000000000 7758 + 0.6375000000000002 0.1250000000000000 7759 + 0.6375000000000002 0.1375000000000000 7760 + 0.6374999999999998 0.1500000000000000 7761 + 0.6375000000000002 0.1625000000000000 7762 + 0.6374999999999998 0.1750000000000000 7763 + 0.6374999999999998 0.1875000000000000 7764 + 0.6374999999999997 0.2000000000000000 7765 + 0.6374999999999997 0.2125000000000000 7766 + 0.6374999999999997 0.2250000000000000 7767 + 0.6375000000000000 0.2375000000000000 7768 + 0.6375000000000000 0.2500000000000000 7769 + 0.6375000000000000 0.2625000000000000 7770 + 0.6375000000000002 0.2750000000000000 7771 + 0.6375000000000002 0.2875000000000000 7772 + 0.6375000000000002 0.3000000000000000 7773 + 0.6375000000000001 0.3125000000000000 7774 + 0.6375000000000001 0.3250000000000000 7775 + 0.6375000000000001 0.3375000000000000 7776 + 0.6375000000000001 0.3500000000000000 7777 + 0.6374999999999997 0.3625000000000000 7778 + 0.6374999999999997 0.3750000000000000 7779 + 0.6374999999999997 0.3875000000000001 7780 + 0.6374999999999997 0.4000000000000000 7781 + 0.6375000000000000 0.4125000000000001 7782 + 0.6374999999999997 0.4250000000000000 7783 + 0.6374999999999997 0.4375000000000000 7784 + 0.6375000000000000 0.4500000000000000 7785 + 0.6375000000000002 0.4625000000000000 7786 + 0.6375000000000000 0.4750000000000000 7787 + 0.6374999999999998 0.4875000000000000 7788 + 0.6374999999999998 0.5000000000000000 7789 + 0.6250000000000000 0.000000000000000 7790 + 0.6250000000000001 0.01250000000000000 7791 + 0.6250000000000000 0.02500000000000000 7792 + 0.6250000000000000 0.03750000000000001 7793 + 0.6250000000000000 0.05000000000000000 7794 + 0.6250000000000000 0.06250000000000000 7795 + 0.6250000000000000 0.07500000000000001 7796 + 0.6250000000000001 0.08750000000000001 7797 + 0.6250000000000000 0.1000000000000000 7798 + 0.6250000000000000 0.1125000000000000 7799 + 0.6250000000000000 0.1250000000000000 7800 + 0.6249999999999999 0.1375000000000000 7801 + 0.6249999999999999 0.1500000000000000 7802 + 0.6250000000000002 0.1625000000000000 7803 + 0.6249999999999998 0.1750000000000000 7804 + 0.6250000000000000 0.1875000000000000 7805 + 0.6250000000000000 0.2000000000000000 7806 + 0.6250000000000000 0.2125000000000000 7807 + 0.6250000000000000 0.2250000000000000 7808 + 0.6250000000000000 0.2375000000000000 7809 + 0.6250000000000000 0.2500000000000000 7810 + 0.6250000000000000 0.2625000000000000 7811 + 0.6250000000000000 0.2750000000000000 7812 + 0.6250000000000000 0.2875000000000000 7813 + 0.6250000000000001 0.3000000000000000 7814 + 0.6250000000000001 0.3125000000000000 7815 + 0.6250000000000001 0.3250000000000000 7816 + 0.6249999999999998 0.3375000000000000 7817 + 0.6249999999999998 0.3500000000000000 7818 + 0.6250000000000000 0.3625000000000000 7819 + 0.6250000000000000 0.3750000000000000 7820 + 0.6250000000000000 0.3874999999999999 7821 + 0.6250000000000000 0.4000000000000000 7822 + 0.6250000000000000 0.4125000000000001 7823 + 0.6250000000000000 0.4250000000000000 7824 + 0.6250000000000000 0.4375000000000000 7825 + 0.6249999999999999 0.4499999999999999 7826 + 0.6249999999999999 0.4625000000000000 7827 + 0.6249999999999999 0.4750000000000000 7828 + 0.6250000000000000 0.4875000000000000 7829 + 0.6249999999999999 0.5000000000000000 7830 + 0.6125000000000000 0.000000000000000 7831 + 0.6124999999999998 0.01250000000000000 7832 + 0.6124999999999999 0.02500000000000000 7833 + 0.6125000000000002 0.03750000000000001 7834 + 0.6125000000000000 0.05000000000000000 7835 + 0.6125000000000000 0.06250000000000000 7836 + 0.6125000000000003 0.07500000000000001 7837 + 0.6125000000000000 0.08750000000000001 7838 + 0.6125000000000000 0.1000000000000000 7839 + 0.6124999999999999 0.1125000000000000 7840 + 0.6124999999999999 0.1250000000000000 7841 + 0.6124999999999999 0.1375000000000000 7842 + 0.6124999999999998 0.1500000000000000 7843 + 0.6125000000000000 0.1625000000000000 7844 + 0.6124999999999998 0.1750000000000000 7845 + 0.6125000000000000 0.1875000000000000 7846 + 0.6125000000000000 0.2000000000000000 7847 + 0.6125000000000000 0.2125000000000000 7848 + 0.6125000000000000 0.2250000000000000 7849 + 0.6125000000000003 0.2375000000000000 7850 + 0.6125000000000003 0.2500000000000000 7851 + 0.6125000000000003 0.2625000000000000 7852 + 0.6125000000000002 0.2750000000000000 7853 + 0.6125000000000002 0.2875000000000000 7854 + 0.6125000000000002 0.3000000000000000 7855 + 0.6125000000000002 0.3125000000000000 7856 + 0.6124999999999998 0.3250000000000000 7857 + 0.6124999999999998 0.3375000000000000 7858 + 0.6124999999999998 0.3500000000000000 7859 + 0.6125000000000000 0.3625000000000000 7860 + 0.6125000000000000 0.3750000000000000 7861 + 0.6125000000000000 0.3875000000000000 7862 + 0.6125000000000000 0.4000000000000000 7863 + 0.6125000000000000 0.4125000000000000 7864 + 0.6125000000000000 0.4250000000000000 7865 + 0.6124999999999999 0.4375000000000000 7866 + 0.6124999999999999 0.4500000000000000 7867 + 0.6124999999999999 0.4625000000000000 7868 + 0.6124999999999999 0.4750000000000000 7869 + 0.6124999999999998 0.4875000000000000 7870 + 0.6124999999999999 0.5000000000000000 7871 + 0.6000000000000001 0.000000000000000 7872 + 0.6000000000000001 0.01250000000000000 7873 + 0.6000000000000002 0.02500000000000000 7874 + 0.6000000000000000 0.03750000000000001 7875 + 0.6000000000000001 0.05000000000000000 7876 + 0.6000000000000001 0.06250000000000000 7877 + 0.6000000000000001 0.07500000000000001 7878 + 0.6000000000000001 0.08750000000000001 7879 + 0.6000000000000003 0.1000000000000000 7880 + 0.6000000000000000 0.1125000000000000 7881 + 0.6000000000000000 0.1250000000000000 7882 + 0.5999999999999999 0.1375000000000000 7883 + 0.5999999999999999 0.1500000000000000 7884 + 0.6000000000000001 0.1625000000000000 7885 + 0.5999999999999999 0.1750000000000000 7886 + 0.5999999999999999 0.1875000000000000 7887 + 0.5999999999999999 0.2000000000000000 7888 + 0.6000000000000001 0.2125000000000000 7889 + 0.6000000000000001 0.2250000000000000 7890 + 0.6000000000000001 0.2375000000000000 7891 + 0.5999999999999998 0.2500000000000000 7892 + 0.5999999999999998 0.2625000000000000 7893 + 0.5999999999999998 0.2750000000000000 7894 + 0.5999999999999998 0.2875000000000000 7895 + 0.5999999999999996 0.3000000000000000 7896 + 0.5999999999999996 0.3125000000000000 7897 + 0.5999999999999996 0.3250000000000000 7898 + 0.5999999999999999 0.3375000000000000 7899 + 0.5999999999999999 0.3500000000000000 7900 + 0.5999999999999996 0.3625000000000000 7901 + 0.5999999999999999 0.3750000000000000 7902 + 0.5999999999999999 0.3875000000000001 7903 + 0.5999999999999999 0.4000000000000000 7904 + 0.6000000000000000 0.4125000000000000 7905 + 0.6000000000000000 0.4250000000000000 7906 + 0.5999999999999995 0.4375000000000000 7907 + 0.5999999999999996 0.4500000000000000 7908 + 0.5999999999999996 0.4625000000000000 7909 + 0.5999999999999996 0.4750000000000000 7910 + 0.5999999999999996 0.4875000000000000 7911 + 0.5999999999999996 0.5000000000000000 7912 + 0.5875000000000000 0.000000000000000 7913 + 0.5874999999999999 0.01250000000000000 7914 + 0.5875000000000000 0.02500000000000000 7915 + 0.5875000000000000 0.03750000000000001 7916 + 0.5874999999999999 0.05000000000000000 7917 + 0.5874999999999999 0.06250000000000000 7918 + 0.5875000000000001 0.07500000000000001 7919 + 0.5874999999999999 0.08750000000000001 7920 + 0.5875000000000001 0.1000000000000000 7921 + 0.5875000000000000 0.1125000000000000 7922 + 0.5875000000000000 0.1250000000000000 7923 + 0.5875000000000000 0.1375000000000000 7924 + 0.5874999999999999 0.1500000000000000 7925 + 0.5874999999999999 0.1625000000000000 7926 + 0.5874999999999999 0.1750000000000000 7927 + 0.5874999999999999 0.1875000000000000 7928 + 0.5874999999999999 0.2000000000000000 7929 + 0.5874999999999999 0.2125000000000000 7930 + 0.5875000000000001 0.2250000000000000 7931 + 0.5875000000000001 0.2375000000000000 7932 + 0.5875000000000001 0.2500000000000000 7933 + 0.5875000000000001 0.2625000000000000 7934 + 0.5875000000000002 0.2750000000000000 7935 + 0.5875000000000002 0.2875000000000000 7936 + 0.5875000000000002 0.3000000000000000 7937 + 0.5875000000000002 0.3125000000000000 7938 + 0.5874999999999999 0.3250000000000000 7939 + 0.5874999999999999 0.3375000000000000 7940 + 0.5874999999999999 0.3500000000000000 7941 + 0.5874999999999999 0.3625000000000000 7942 + 0.5874999999999999 0.3750000000000000 7943 + 0.5874999999999999 0.3875000000000000 7944 + 0.5875000000000001 0.4000000000000000 7945 + 0.5875000000000001 0.4125000000000000 7946 + 0.5875000000000001 0.4250000000000000 7947 + 0.5875000000000000 0.4375000000000000 7948 + 0.5875000000000000 0.4500000000000000 7949 + 0.5875000000000000 0.4625000000000000 7950 + 0.5875000000000000 0.4750000000000000 7951 + 0.5874999999999999 0.4875000000000000 7952 + 0.5875000000000000 0.5000000000000000 7953 + 0.5750000000000001 0.000000000000000 7954 + 0.5750000000000002 0.01250000000000000 7955 + 0.5750000000000000 0.02500000000000000 7956 + 0.5750000000000000 0.03750000000000001 7957 + 0.5750000000000002 0.05000000000000000 7958 + 0.5750000000000001 0.06250000000000000 7959 + 0.5750000000000001 0.07500000000000001 7960 + 0.5750000000000002 0.08750000000000001 7961 + 0.5750000000000000 0.1000000000000000 7962 + 0.5749999999999997 0.1125000000000000 7963 + 0.5749999999999997 0.1250000000000000 7964 + 0.5749999999999997 0.1375000000000000 7965 + 0.5750000000000000 0.1500000000000000 7966 + 0.5750000000000001 0.1625000000000000 7967 + 0.5750000000000000 0.1750000000000000 7968 + 0.5750000000000000 0.1875000000000000 7969 + 0.5750000000000002 0.2000000000000000 7970 + 0.5750000000000002 0.2125000000000000 7971 + 0.5750000000000002 0.2250000000000000 7972 + 0.5749999999999998 0.2375000000000000 7973 + 0.5749999999999998 0.2500000000000000 7974 + 0.5749999999999998 0.2625000000000000 7975 + 0.5749999999999997 0.2750000000000000 7976 + 0.5749999999999997 0.2875000000000000 7977 + 0.5749999999999997 0.3000000000000000 7978 + 0.5749999999999997 0.3125000000000000 7979 + 0.5749999999999997 0.3250000000000000 7980 + 0.5749999999999997 0.3375000000000000 7981 + 0.5749999999999997 0.3500000000000000 7982 + 0.5750000000000000 0.3625000000000000 7983 + 0.5750000000000000 0.3750000000000000 7984 + 0.5750000000000000 0.3874999999999999 7985 + 0.5749999999999996 0.4000000000000000 7986 + 0.5750000000000001 0.4125000000000000 7987 + 0.5750000000000001 0.4250000000000000 7988 + 0.5750000000000001 0.4375000000000000 7989 + 0.5749999999999997 0.4499999999999999 7990 + 0.5749999999999997 0.4625000000000000 7991 + 0.5749999999999997 0.4750000000000001 7992 + 0.5749999999999997 0.4875000000000000 7993 + 0.5749999999999997 0.5000000000000000 7994 + 0.5625000000000000 0.000000000000000 7995 + 0.5625000000000000 0.01250000000000000 7996 + 0.5625000000000000 0.02500000000000000 7997 + 0.5625000000000002 0.03750000000000001 7998 + 0.5625000000000000 0.05000000000000000 7999 + 0.5625000000000000 0.06250000000000000 8000 + 0.5625000000000001 0.07500000000000001 8001 + 0.5624999999999998 0.08750000000000001 8002 + 0.5625000000000000 0.1000000000000000 8003 + 0.5625000000000001 0.1125000000000000 8004 + 0.5625000000000000 0.1250000000000000 8005 + 0.5625000000000000 0.1375000000000000 8006 + 0.5625000000000000 0.1500000000000000 8007 + 0.5624999999999999 0.1625000000000000 8008 + 0.5625000000000000 0.1750000000000000 8009 + 0.5625000000000000 0.1875000000000000 8010 + 0.5625000000000000 0.2000000000000000 8011 + 0.5625000000000000 0.2125000000000000 8012 + 0.5625000000000000 0.2250000000000000 8013 + 0.5625000000000000 0.2375000000000000 8014 + 0.5624999999999999 0.2500000000000000 8015 + 0.5624999999999999 0.2625000000000000 8016 + 0.5624999999999999 0.2750000000000000 8017 + 0.5624999999999999 0.2875000000000000 8018 + 0.5625000000000000 0.3000000000000000 8019 + 0.5625000000000000 0.3125000000000000 8020 + 0.5625000000000000 0.3250000000000000 8021 + 0.5625000000000000 0.3375000000000000 8022 + 0.5625000000000000 0.3500000000000000 8023 + 0.5625000000000000 0.3625000000000000 8024 + 0.5625000000000000 0.3750000000000000 8025 + 0.5625000000000002 0.3875000000000000 8026 + 0.5625000000000002 0.4000000000000000 8027 + 0.5625000000000002 0.4125000000000000 8028 + 0.5625000000000002 0.4250000000000000 8029 + 0.5625000000000001 0.4375000000000000 8030 + 0.5625000000000001 0.4500000000000001 8031 + 0.5625000000000001 0.4625000000000000 8032 + 0.5625000000000001 0.4750000000000001 8033 + 0.5625000000000000 0.4875000000000000 8034 + 0.5625000000000001 0.5000000000000000 8035 + 0.5500000000000000 0.000000000000000 8036 + 0.5500000000000003 0.01250000000000000 8037 + 0.5499999999999998 0.02500000000000000 8038 + 0.5500000000000000 0.03750000000000001 8039 + 0.5500000000000002 0.05000000000000000 8040 + 0.5500000000000002 0.06250000000000000 8041 + 0.5499999999999998 0.07500000000000001 8042 + 0.5500000000000000 0.08750000000000001 8043 + 0.5500000000000000 0.1000000000000000 8044 + 0.5499999999999998 0.1125000000000000 8045 + 0.5500000000000000 0.1250000000000000 8046 + 0.5499999999999998 0.1375000000000000 8047 + 0.5500000000000000 0.1500000000000000 8048 + 0.5500000000000002 0.1625000000000000 8049 + 0.5500000000000000 0.1750000000000000 8050 + 0.5500000000000000 0.1875000000000000 8051 + 0.5500000000000000 0.2000000000000000 8052 + 0.5500000000000000 0.2125000000000000 8053 + 0.5499999999999999 0.2250000000000000 8054 + 0.5499999999999999 0.2375000000000000 8055 + 0.5499999999999999 0.2500000000000000 8056 + 0.5499999999999999 0.2625000000000000 8057 + 0.5499999999999999 0.2750000000000000 8058 + 0.5499999999999998 0.2875000000000000 8059 + 0.5499999999999998 0.3000000000000000 8060 + 0.5499999999999998 0.3125000000000000 8061 + 0.5499999999999998 0.3250000000000000 8062 + 0.5499999999999998 0.3375000000000000 8063 + 0.5499999999999998 0.3500000000000000 8064 + 0.5499999999999998 0.3625000000000000 8065 + 0.5499999999999998 0.3750000000000000 8066 + 0.5499999999999998 0.3875000000000000 8067 + 0.5499999999999998 0.4000000000000000 8068 + 0.5499999999999998 0.4125000000000000 8069 + 0.5499999999999997 0.4250000000000000 8070 + 0.5499999999999997 0.4375000000000000 8071 + 0.5499999999999997 0.4500000000000000 8072 + 0.5499999999999997 0.4625000000000000 8073 + 0.5499999999999997 0.4750000000000001 8074 + 0.5499999999999998 0.4875000000000000 8075 + 0.5499999999999998 0.5000000000000000 8076 + 0.5375000000000000 0.000000000000000 8077 + 0.5375000000000001 0.01250000000000000 8078 + 0.5374999999999999 0.02500000000000000 8079 + 0.5375000000000001 0.03750000000000001 8080 + 0.5374999999999998 0.05000000000000000 8081 + 0.5374999999999998 0.06250000000000000 8082 + 0.5374999999999999 0.07500000000000001 8083 + 0.5374999999999999 0.08750000000000001 8084 + 0.5375000000000001 0.1000000000000000 8085 + 0.5374999999999999 0.1125000000000000 8086 + 0.5374999999999999 0.1250000000000000 8087 + 0.5375000000000001 0.1375000000000000 8088 + 0.5375000000000001 0.1500000000000000 8089 + 0.5374999999999999 0.1625000000000000 8090 + 0.5375000000000001 0.1750000000000000 8091 + 0.5375000000000001 0.1875000000000000 8092 + 0.5375000000000001 0.2000000000000000 8093 + 0.5375000000000000 0.2125000000000000 8094 + 0.5375000000000000 0.2250000000000000 8095 + 0.5375000000000000 0.2375000000000000 8096 + 0.5375000000000000 0.2500000000000000 8097 + 0.5374999999999996 0.2625000000000000 8098 + 0.5374999999999999 0.2750000000000000 8099 + 0.5374999999999996 0.2875000000000000 8100 + 0.5374999999999999 0.3000000000000000 8101 + 0.5374999999999999 0.3125000000000000 8102 + 0.5374999999999999 0.3250000000000000 8103 + 0.5374999999999999 0.3375000000000000 8104 + 0.5375000000000001 0.3500000000000000 8105 + 0.5375000000000001 0.3625000000000000 8106 + 0.5375000000000001 0.3750000000000000 8107 + 0.5374999999999998 0.3875000000000001 8108 + 0.5374999999999998 0.4000000000000000 8109 + 0.5374999999999998 0.4125000000000000 8110 + 0.5374999999999998 0.4250000000000000 8111 + 0.5374999999999996 0.4375000000000000 8112 + 0.5374999999999996 0.4500000000000000 8113 + 0.5374999999999996 0.4625000000000000 8114 + 0.5374999999999996 0.4750000000000001 8115 + 0.5374999999999999 0.4875000000000000 8116 + 0.5374999999999999 0.5000000000000000 8117 + 0.5250000000000000 0.000000000000000 8118 + 0.5249999999999999 0.01250000000000000 8119 + 0.5249999999999999 0.02500000000000000 8120 + 0.5250000000000001 0.03750000000000001 8121 + 0.5250000000000002 0.05000000000000000 8122 + 0.5250000000000002 0.06250000000000000 8123 + 0.5249999999999999 0.07500000000000001 8124 + 0.5250000000000001 0.08750000000000001 8125 + 0.5249999999999999 0.1000000000000000 8126 + 0.5249999999999999 0.1125000000000000 8127 + 0.5249999999999999 0.1250000000000000 8128 + 0.5249999999999999 0.1375000000000000 8129 + 0.5250000000000001 0.1500000000000000 8130 + 0.5250000000000001 0.1625000000000000 8131 + 0.5249999999999999 0.1750000000000000 8132 + 0.5250000000000000 0.1875000000000000 8133 + 0.5250000000000000 0.2000000000000000 8134 + 0.5250000000000000 0.2125000000000000 8135 + 0.5250000000000000 0.2250000000000000 8136 + 0.5249999999999999 0.2375000000000000 8137 + 0.5249999999999999 0.2500000000000000 8138 + 0.5249999999999999 0.2625000000000000 8139 + 0.5249999999999999 0.2750000000000000 8140 + 0.5249999999999999 0.2875000000000000 8141 + 0.5249999999999999 0.3000000000000000 8142 + 0.5249999999999999 0.3125000000000000 8143 + 0.5249999999999999 0.3250000000000000 8144 + 0.5249999999999999 0.3375000000000000 8145 + 0.5249999999999999 0.3500000000000000 8146 + 0.5249999999999998 0.3625000000000000 8147 + 0.5249999999999998 0.3750000000000000 8148 + 0.5249999999999998 0.3874999999999999 8149 + 0.5249999999999999 0.4000000000000000 8150 + 0.5249999999999999 0.4125000000000000 8151 + 0.5249999999999999 0.4250000000000000 8152 + 0.5249999999999999 0.4375000000000000 8153 + 0.5249999999999999 0.4500000000000000 8154 + 0.5249999999999999 0.4625000000000000 8155 + 0.5249999999999999 0.4749999999999999 8156 + 0.5249999999999999 0.4875000000000000 8157 + 0.5249999999999999 0.5000000000000000 8158 + 0.5125000000000001 0.000000000000000 8159 + 0.5124999999999998 0.01250000000000000 8160 + 0.5125000000000000 0.02500000000000000 8161 + 0.5125000000000002 0.03750000000000001 8162 + 0.5125000000000000 0.05000000000000000 8163 + 0.5125000000000000 0.06250000000000000 8164 + 0.5125000000000002 0.07500000000000001 8165 + 0.5125000000000001 0.08750000000000001 8166 + 0.5125000000000001 0.1000000000000000 8167 + 0.5125000000000002 0.1125000000000000 8168 + 0.5125000000000002 0.1250000000000000 8169 + 0.5125000000000002 0.1375000000000000 8170 + 0.5125000000000002 0.1500000000000000 8171 + 0.5125000000000000 0.1625000000000000 8172 + 0.5125000000000001 0.1750000000000000 8173 + 0.5125000000000001 0.1875000000000000 8174 + 0.5125000000000001 0.2000000000000000 8175 + 0.5124999999999997 0.2125000000000000 8176 + 0.5125000000000000 0.2250000000000000 8177 + 0.5124999999999997 0.2375000000000000 8178 + 0.5125000000000000 0.2500000000000000 8179 + 0.5125000000000000 0.2625000000000000 8180 + 0.5125000000000000 0.2750000000000000 8181 + 0.5125000000000000 0.2875000000000000 8182 + 0.5125000000000002 0.3000000000000000 8183 + 0.5125000000000002 0.3125000000000000 8184 + 0.5125000000000002 0.3250000000000000 8185 + 0.5125000000000002 0.3375000000000000 8186 + 0.5124999999999998 0.3500000000000000 8187 + 0.5124999999999998 0.3625000000000000 8188 + 0.5124999999999998 0.3750000000000000 8189 + 0.5124999999999997 0.3875000000000000 8190 + 0.5124999999999997 0.4000000000000000 8191 + 0.5124999999999997 0.4125000000000001 8192 + 0.5124999999999997 0.4250000000000000 8193 + 0.5125000000000000 0.4375000000000000 8194 + 0.5125000000000000 0.4500000000000000 8195 + 0.5125000000000000 0.4625000000000000 8196 + 0.5125000000000000 0.4750000000000001 8197 + 0.5125000000000002 0.4875000000000000 8198 + 0.5125000000000000 0.5000000000000000 8199 + 0.5000000000000000 0.000000000000000 8200 + 0.4999999999999999 0.01250000000000000 8201 + 0.5000000000000000 0.02500000000000000 8202 + 0.5000000000000000 0.03750000000000001 8203 + 0.5000000000000000 0.05000000000000000 8204 + 0.5000000000000000 0.06250000000000000 8205 + 0.5000000000000000 0.07500000000000001 8206 + 0.5000000000000001 0.08750000000000001 8207 + 0.4999999999999999 0.1000000000000000 8208 + 0.5000000000000000 0.1125000000000000 8209 + 0.5000000000000000 0.1250000000000000 8210 + 0.5000000000000000 0.1375000000000000 8211 + 0.5000000000000001 0.1500000000000000 8212 + 0.5000000000000000 0.1625000000000000 8213 + 0.5000000000000001 0.1750000000000000 8214 + 0.5000000000000001 0.1875000000000000 8215 + 0.5000000000000000 0.2000000000000000 8216 + 0.5000000000000000 0.2125000000000000 8217 + 0.5000000000000000 0.2250000000000000 8218 + 0.5000000000000000 0.2375000000000000 8219 + 0.5000000000000000 0.2500000000000000 8220 + 0.5000000000000000 0.2625000000000000 8221 + 0.5000000000000000 0.2750000000000000 8222 + 0.5000000000000000 0.2875000000000000 8223 + 0.5000000000000000 0.3000000000000000 8224 + 0.4999999999999999 0.3125000000000000 8225 + 0.4999999999999999 0.3250000000000000 8226 + 0.4999999999999999 0.3375000000000000 8227 + 0.4999999999999999 0.3500000000000000 8228 + 0.4999999999999998 0.3625000000000000 8229 + 0.4999999999999998 0.3750000000000000 8230 + 0.4999999999999998 0.3875000000000000 8231 + 0.5000000000000000 0.4000000000000000 8232 + 0.5000000000000000 0.4125000000000000 8233 + 0.5000000000000000 0.4250000000000000 8234 + 0.5000000000000000 0.4375000000000000 8235 + 0.5000000000000000 0.4500000000000000 8236 + 0.5000000000000000 0.4625000000000000 8237 + 0.5000000000000000 0.4749999999999999 8238 + 0.5000000000000001 0.4875000000000000 8239 + 0.4999999999999999 0.5000000000000000 8240 + 0.4875000000000000 0.000000000000000 8241 + 0.4875000000000000 0.01250000000000000 8242 + 0.4875000000000000 0.02500000000000000 8243 + 0.4875000000000000 0.03750000000000001 8244 + 0.4874999999999999 0.05000000000000000 8245 + 0.4875000000000000 0.06250000000000000 8246 + 0.4875000000000000 0.07500000000000001 8247 + 0.4874999999999999 0.08750000000000001 8248 + 0.4875000000000002 0.1000000000000000 8249 + 0.4875000000000002 0.1125000000000000 8250 + 0.4875000000000002 0.1250000000000000 8251 + 0.4875000000000002 0.1375000000000000 8252 + 0.4875000000000000 0.1500000000000000 8253 + 0.4874999999999999 0.1625000000000000 8254 + 0.4875000000000000 0.1750000000000000 8255 + 0.4875000000000000 0.1875000000000000 8256 + 0.4874999999999999 0.2000000000000000 8257 + 0.4874999999999999 0.2125000000000000 8258 + 0.4874999999999999 0.2250000000000000 8259 + 0.4875000000000000 0.2375000000000000 8260 + 0.4875000000000000 0.2500000000000000 8261 + 0.4875000000000000 0.2625000000000000 8262 + 0.4875000000000000 0.2750000000000000 8263 + 0.4875000000000002 0.2875000000000000 8264 + 0.4875000000000002 0.3000000000000000 8265 + 0.4875000000000000 0.3125000000000000 8266 + 0.4875000000000000 0.3250000000000000 8267 + 0.4875000000000000 0.3375000000000000 8268 + 0.4875000000000000 0.3500000000000000 8269 + 0.4874999999999999 0.3625000000000000 8270 + 0.4874999999999999 0.3750000000000000 8271 + 0.4874999999999999 0.3875000000000000 8272 + 0.4875000000000000 0.4000000000000000 8273 + 0.4875000000000000 0.4124999999999999 8274 + 0.4875000000000000 0.4250000000000000 8275 + 0.4875000000000000 0.4375000000000000 8276 + 0.4875000000000000 0.4500000000000001 8277 + 0.4875000000000000 0.4625000000000000 8278 + 0.4875000000000000 0.4750000000000000 8279 + 0.4875000000000000 0.4875000000000000 8280 + 0.4875000000000000 0.5000000000000000 8281 + 0.4750000000000000 0.000000000000000 8282 + 0.4749999999999999 0.01250000000000000 8283 + 0.4750000000000000 0.02500000000000000 8284 + 0.4750000000000000 0.03750000000000001 8285 + 0.4750000000000001 0.05000000000000000 8286 + 0.4750000000000001 0.06250000000000000 8287 + 0.4750000000000000 0.07500000000000001 8288 + 0.4750000000000001 0.08750000000000001 8289 + 0.4749999999999999 0.1000000000000000 8290 + 0.4749999999999999 0.1125000000000000 8291 + 0.4749999999999999 0.1250000000000000 8292 + 0.4749999999999999 0.1375000000000000 8293 + 0.4749999999999999 0.1500000000000000 8294 + 0.4750000000000000 0.1625000000000000 8295 + 0.4749999999999997 0.1750000000000000 8296 + 0.4749999999999999 0.1875000000000000 8297 + 0.4749999999999999 0.2000000000000000 8298 + 0.4749999999999999 0.2125000000000000 8299 + 0.4749999999999999 0.2250000000000000 8300 + 0.4750000000000000 0.2375000000000000 8301 + 0.4750000000000000 0.2500000000000000 8302 + 0.4749999999999998 0.2625000000000000 8303 + 0.4749999999999999 0.2750000000000000 8304 + 0.4749999999999999 0.2875000000000000 8305 + 0.4749999999999999 0.3000000000000000 8306 + 0.4749999999999999 0.3125000000000000 8307 + 0.4749999999999997 0.3250000000000000 8308 + 0.4749999999999997 0.3375000000000000 8309 + 0.4749999999999997 0.3500000000000000 8310 + 0.4749999999999996 0.3625000000000000 8311 + 0.4749999999999996 0.3750000000000000 8312 + 0.4749999999999996 0.3875000000000000 8313 + 0.4749999999999998 0.4000000000000000 8314 + 0.4749999999999998 0.4124999999999999 8315 + 0.4749999999999998 0.4250000000000000 8316 + 0.4749999999999996 0.4375000000000000 8317 + 0.4749999999999996 0.4500000000000001 8318 + 0.4749999999999996 0.4625000000000000 8319 + 0.4749999999999996 0.4750000000000001 8320 + 0.4749999999999997 0.4875000000000000 8321 + 0.4749999999999996 0.5000000000000000 8322 + 0.4625000000000000 0.000000000000000 8323 + 0.4625000000000000 0.01250000000000000 8324 + 0.4625000000000000 0.02500000000000000 8325 + 0.4625000000000000 0.03750000000000001 8326 + 0.4624999999999999 0.05000000000000000 8327 + 0.4624999999999999 0.06250000000000000 8328 + 0.4625000000000001 0.07500000000000001 8329 + 0.4625000000000000 0.08750000000000001 8330 + 0.4625000000000002 0.1000000000000000 8331 + 0.4625000000000001 0.1125000000000000 8332 + 0.4625000000000001 0.1250000000000000 8333 + 0.4625000000000001 0.1375000000000000 8334 + 0.4625000000000001 0.1500000000000000 8335 + 0.4625000000000001 0.1625000000000000 8336 + 0.4625000000000000 0.1750000000000000 8337 + 0.4625000000000000 0.1875000000000000 8338 + 0.4625000000000000 0.2000000000000000 8339 + 0.4624999999999999 0.2125000000000000 8340 + 0.4624999999999999 0.2250000000000000 8341 + 0.4624999999999999 0.2375000000000000 8342 + 0.4624999999999999 0.2500000000000000 8343 + 0.4625000000000001 0.2625000000000000 8344 + 0.4625000000000001 0.2750000000000000 8345 + 0.4625000000000001 0.2875000000000000 8346 + 0.4625000000000001 0.3000000000000000 8347 + 0.4625000000000001 0.3125000000000000 8348 + 0.4625000000000001 0.3250000000000000 8349 + 0.4625000000000001 0.3375000000000000 8350 + 0.4625000000000000 0.3500000000000000 8351 + 0.4625000000000000 0.3625000000000000 8352 + 0.4625000000000000 0.3750000000000000 8353 + 0.4625000000000001 0.3875000000000000 8354 + 0.4625000000000001 0.4000000000000000 8355 + 0.4624999999999999 0.4125000000000001 8356 + 0.4625000000000001 0.4250000000000000 8357 + 0.4625000000000001 0.4375000000000000 8358 + 0.4625000000000001 0.4500000000000000 8359 + 0.4625000000000001 0.4625000000000000 8360 + 0.4625000000000001 0.4749999999999999 8361 + 0.4625000000000001 0.4875000000000000 8362 + 0.4625000000000001 0.5000000000000000 8363 + 0.4500000000000000 0.000000000000000 8364 + 0.4500000000000000 0.01250000000000000 8365 + 0.4499999999999998 0.02500000000000000 8366 + 0.4500000000000000 0.03750000000000001 8367 + 0.4500000000000001 0.05000000000000000 8368 + 0.4500000000000001 0.06250000000000000 8369 + 0.4500000000000000 0.07500000000000001 8370 + 0.4500000000000001 0.08750000000000001 8371 + 0.4500000000000001 0.1000000000000000 8372 + 0.4500000000000000 0.1125000000000000 8373 + 0.4500000000000000 0.1250000000000000 8374 + 0.4499999999999998 0.1375000000000000 8375 + 0.4499999999999998 0.1500000000000000 8376 + 0.4499999999999999 0.1625000000000000 8377 + 0.4500000000000000 0.1750000000000000 8378 + 0.4500000000000000 0.1875000000000000 8379 + 0.4500000000000000 0.2000000000000000 8380 + 0.4500000000000000 0.2125000000000000 8381 + 0.4500000000000000 0.2250000000000000 8382 + 0.4499999999999999 0.2375000000000000 8383 + 0.4499999999999999 0.2500000000000000 8384 + 0.4499999999999999 0.2625000000000000 8385 + 0.4500000000000000 0.2750000000000000 8386 + 0.4500000000000000 0.2875000000000000 8387 + 0.4500000000000000 0.3000000000000000 8388 + 0.4500000000000000 0.3125000000000000 8389 + 0.4500000000000000 0.3250000000000000 8390 + 0.4499999999999998 0.3375000000000000 8391 + 0.4499999999999998 0.3500000000000000 8392 + 0.4499999999999998 0.3625000000000000 8393 + 0.4499999999999997 0.3750000000000000 8394 + 0.4499999999999997 0.3875000000000000 8395 + 0.4499999999999997 0.4000000000000000 8396 + 0.4499999999999997 0.4125000000000000 8397 + 0.4499999999999997 0.4250000000000000 8398 + 0.4499999999999999 0.4375000000000000 8399 + 0.4499999999999997 0.4500000000000001 8400 + 0.4499999999999999 0.4625000000000000 8401 + 0.4499999999999997 0.4750000000000000 8402 + 0.4499999999999997 0.4875000000000000 8403 + 0.4499999999999997 0.5000000000000000 8404 + 0.4375000000000000 0.000000000000000 8405 + 0.4375000000000000 0.01250000000000000 8406 + 0.4375000000000001 0.02500000000000000 8407 + 0.4375000000000001 0.03750000000000001 8408 + 0.4374999999999999 0.05000000000000000 8409 + 0.4374999999999999 0.06250000000000000 8410 + 0.4375000000000000 0.07500000000000001 8411 + 0.4374999999999999 0.08750000000000001 8412 + 0.4375000000000001 0.1000000000000000 8413 + 0.4375000000000000 0.1125000000000000 8414 + 0.4375000000000000 0.1250000000000000 8415 + 0.4375000000000001 0.1375000000000000 8416 + 0.4375000000000001 0.1500000000000000 8417 + 0.4374999999999999 0.1625000000000000 8418 + 0.4375000000000000 0.1750000000000000 8419 + 0.4375000000000000 0.1875000000000000 8420 + 0.4375000000000000 0.2000000000000000 8421 + 0.4375000000000000 0.2125000000000000 8422 + 0.4375000000000000 0.2250000000000000 8423 + 0.4375000000000002 0.2375000000000000 8424 + 0.4375000000000002 0.2500000000000000 8425 + 0.4375000000000002 0.2625000000000000 8426 + 0.4375000000000002 0.2750000000000000 8427 + 0.4375000000000002 0.2875000000000000 8428 + 0.4375000000000002 0.3000000000000000 8429 + 0.4375000000000002 0.3125000000000000 8430 + 0.4375000000000002 0.3250000000000000 8431 + 0.4375000000000001 0.3375000000000000 8432 + 0.4375000000000001 0.3500000000000000 8433 + 0.4375000000000001 0.3625000000000000 8434 + 0.4375000000000000 0.3750000000000000 8435 + 0.4375000000000000 0.3875000000000000 8436 + 0.4375000000000000 0.4000000000000000 8437 + 0.4375000000000002 0.4125000000000001 8438 + 0.4375000000000000 0.4250000000000000 8439 + 0.4375000000000002 0.4375000000000000 8440 + 0.4375000000000002 0.4500000000000000 8441 + 0.4375000000000002 0.4625000000000000 8442 + 0.4375000000000002 0.4750000000000001 8443 + 0.4375000000000002 0.4875000000000000 8444 + 0.4375000000000002 0.5000000000000000 8445 + 0.4250000000000000 0.000000000000000 8446 + 0.4250000000000000 0.01250000000000000 8447 + 0.4249999999999999 0.02500000000000000 8448 + 0.4250000000000001 0.03750000000000001 8449 + 0.4250000000000002 0.05000000000000000 8450 + 0.4250000000000002 0.06250000000000000 8451 + 0.4250000000000000 0.07500000000000001 8452 + 0.4249999999999999 0.08750000000000001 8453 + 0.4249999999999999 0.1000000000000000 8454 + 0.4250000000000000 0.1125000000000000 8455 + 0.4250000000000000 0.1250000000000000 8456 + 0.4249999999999999 0.1375000000000000 8457 + 0.4249999999999999 0.1500000000000000 8458 + 0.4250000000000000 0.1625000000000000 8459 + 0.4249999999999998 0.1750000000000000 8460 + 0.4249999999999998 0.1875000000000000 8461 + 0.4249999999999998 0.2000000000000000 8462 + 0.4249999999999998 0.2125000000000000 8463 + 0.4249999999999998 0.2250000000000000 8464 + 0.4250000000000000 0.2375000000000000 8465 + 0.4250000000000000 0.2500000000000000 8466 + 0.4250000000000000 0.2625000000000000 8467 + 0.4250000000000000 0.2750000000000000 8468 + 0.4250000000000000 0.2875000000000000 8469 + 0.4250000000000000 0.3000000000000000 8470 + 0.4250000000000000 0.3125000000000000 8471 + 0.4249999999999998 0.3250000000000000 8472 + 0.4249999999999999 0.3375000000000000 8473 + 0.4249999999999999 0.3500000000000001 8474 + 0.4249999999999999 0.3625000000000000 8475 + 0.4249999999999998 0.3750000000000000 8476 + 0.4249999999999998 0.3875000000000000 8477 + 0.4249999999999998 0.4000000000000000 8478 + 0.4249999999999998 0.4125000000000000 8479 + 0.4249999999999998 0.4250000000000000 8480 + 0.4249999999999998 0.4375000000000000 8481 + 0.4249999999999998 0.4500000000000001 8482 + 0.4249999999999998 0.4625000000000000 8483 + 0.4249999999999998 0.4750000000000000 8484 + 0.4249999999999998 0.4875000000000000 8485 + 0.4249999999999998 0.5000000000000000 8486 + 0.4125000000000000 0.000000000000000 8487 + 0.4125000000000000 0.01250000000000000 8488 + 0.4125000000000000 0.02500000000000000 8489 + 0.4125000000000000 0.03750000000000001 8490 + 0.4124999999999999 0.05000000000000000 8491 + 0.4124999999999999 0.06250000000000000 8492 + 0.4124999999999999 0.07500000000000001 8493 + 0.4124999999999998 0.08750000000000001 8494 + 0.4125000000000000 0.1000000000000000 8495 + 0.4124999999999997 0.1125000000000000 8496 + 0.4124999999999999 0.1250000000000000 8497 + 0.4124999999999999 0.1375000000000000 8498 + 0.4124999999999999 0.1500000000000000 8499 + 0.4125000000000000 0.1625000000000000 8500 + 0.4125000000000000 0.1750000000000000 8501 + 0.4124999999999998 0.1875000000000000 8502 + 0.4124999999999998 0.2000000000000000 8503 + 0.4124999999999998 0.2125000000000000 8504 + 0.4124999999999999 0.2250000000000001 8505 + 0.4124999999999999 0.2375000000000000 8506 + 0.4124999999999999 0.2500000000000000 8507 + 0.4124999999999999 0.2625000000000000 8508 + 0.4124999999999999 0.2750000000000000 8509 + 0.4124999999999997 0.2875000000000000 8510 + 0.4124999999999997 0.3000000000000000 8511 + 0.4124999999999997 0.3125000000000000 8512 + 0.4124999999999996 0.3250000000000000 8513 + 0.4124999999999996 0.3375000000000000 8514 + 0.4124999999999996 0.3500000000000000 8515 + 0.4124999999999996 0.3625000000000000 8516 + 0.4124999999999996 0.3750000000000000 8517 + 0.4124999999999996 0.3875000000000000 8518 + 0.4124999999999996 0.4000000000000000 8519 + 0.4124999999999996 0.4125000000000000 8520 + 0.4124999999999994 0.4250000000000000 8521 + 0.4124999999999994 0.4375000000000000 8522 + 0.4124999999999994 0.4500000000000000 8523 + 0.4124999999999994 0.4625000000000000 8524 + 0.4124999999999994 0.4750000000000000 8525 + 0.4124999999999995 0.4875000000000000 8526 + 0.4124999999999995 0.5000000000000000 8527 + 0.4000000000000000 0.000000000000000 8528 + 0.4000000000000001 0.01250000000000000 8529 + 0.4000000000000000 0.02500000000000000 8530 + 0.4000000000000000 0.03750000000000001 8531 + 0.4000000000000001 0.05000000000000000 8532 + 0.4000000000000001 0.06250000000000000 8533 + 0.4000000000000001 0.07500000000000001 8534 + 0.4000000000000001 0.08750000000000002 8535 + 0.3999999999999999 0.1000000000000000 8536 + 0.4000000000000000 0.1125000000000000 8537 + 0.4000000000000000 0.1250000000000000 8538 + 0.4000000000000000 0.1375000000000000 8539 + 0.3999999999999999 0.1500000000000000 8540 + 0.4000000000000000 0.1625000000000000 8541 + 0.3999999999999999 0.1750000000000000 8542 + 0.3999999999999999 0.1875000000000000 8543 + 0.4000000000000001 0.2000000000000000 8544 + 0.4000000000000001 0.2125000000000000 8545 + 0.4000000000000001 0.2250000000000001 8546 + 0.3999999999999999 0.2375000000000000 8547 + 0.3999999999999999 0.2500000000000000 8548 + 0.3999999999999999 0.2625000000000000 8549 + 0.3999999999999999 0.2750000000000000 8550 + 0.3999999999999999 0.2875000000000000 8551 + 0.3999999999999999 0.3000000000000000 8552 + 0.4000000000000000 0.3125000000000000 8553 + 0.4000000000000000 0.3250000000000000 8554 + 0.4000000000000000 0.3375000000000000 8555 + 0.4000000000000000 0.3500000000000000 8556 + 0.3999999999999999 0.3625000000000000 8557 + 0.3999999999999999 0.3750000000000000 8558 + 0.3999999999999999 0.3875000000000000 8559 + 0.3999999999999999 0.4000000000000000 8560 + 0.3999999999999999 0.4125000000000000 8561 + 0.3999999999999999 0.4250000000000000 8562 + 0.3999999999999999 0.4375000000000000 8563 + 0.3999999999999999 0.4500000000000000 8564 + 0.3999999999999999 0.4625000000000000 8565 + 0.3999999999999999 0.4749999999999999 8566 + 0.3999999999999999 0.4875000000000000 8567 + 0.3999999999999999 0.5000000000000000 8568 + 0.3875000000000000 0.000000000000000 8569 + 0.3875000000000001 0.01250000000000000 8570 + 0.3875000000000001 0.02500000000000000 8571 + 0.3875000000000001 0.03750000000000001 8572 + 0.3875000000000000 0.05000000000000000 8573 + 0.3875000000000000 0.06250000000000000 8574 + 0.3874999999999998 0.07500000000000001 8575 + 0.3874999999999999 0.08750000000000001 8576 + 0.3874999999999999 0.1000000000000000 8577 + 0.3874999999999998 0.1125000000000000 8578 + 0.3875000000000000 0.1250000000000000 8579 + 0.3875000000000000 0.1375000000000000 8580 + 0.3874999999999997 0.1500000000000000 8581 + 0.3874999999999998 0.1625000000000000 8582 + 0.3874999999999999 0.1750000000000000 8583 + 0.3874999999999999 0.1875000000000000 8584 + 0.3874999999999999 0.2000000000000000 8585 + 0.3874999999999999 0.2125000000000000 8586 + 0.3875000000000000 0.2250000000000000 8587 + 0.3874999999999997 0.2375000000000000 8588 + 0.3874999999999997 0.2500000000000000 8589 + 0.3874999999999997 0.2625000000000000 8590 + 0.3874999999999997 0.2750000000000000 8591 + 0.3874999999999998 0.2875000000000000 8592 + 0.3874999999999998 0.3000000000000000 8593 + 0.3874999999999998 0.3125000000000000 8594 + 0.3874999999999997 0.3250000000000000 8595 + 0.3874999999999997 0.3375000000000000 8596 + 0.3874999999999997 0.3500000000000001 8597 + 0.3874999999999997 0.3625000000000000 8598 + 0.3874999999999997 0.3750000000000000 8599 + 0.3874999999999997 0.3875000000000000 8600 + 0.3874999999999997 0.4000000000000000 8601 + 0.3874999999999997 0.4124999999999999 8602 + 0.3874999999999995 0.4250000000000000 8603 + 0.3874999999999995 0.4375000000000000 8604 + 0.3874999999999995 0.4500000000000000 8605 + 0.3874999999999995 0.4625000000000000 8606 + 0.3874999999999995 0.4750000000000000 8607 + 0.3874999999999996 0.4875000000000000 8608 + 0.3874999999999996 0.5000000000000000 8609 + 0.3750000000000000 0.000000000000000 8610 + 0.3750000000000000 0.01250000000000000 8611 + 0.3749999999999999 0.02500000000000000 8612 + 0.3749999999999999 0.03750000000000001 8613 + 0.3750000000000001 0.05000000000000000 8614 + 0.3750000000000001 0.06250000000000000 8615 + 0.3750000000000001 0.07500000000000001 8616 + 0.3749999999999999 0.08750000000000001 8617 + 0.3750000000000001 0.1000000000000000 8618 + 0.3750000000000000 0.1125000000000000 8619 + 0.3750000000000000 0.1250000000000000 8620 + 0.3750000000000000 0.1375000000000000 8621 + 0.3750000000000000 0.1500000000000000 8622 + 0.3750000000000001 0.1625000000000000 8623 + 0.3749999999999999 0.1750000000000000 8624 + 0.3749999999999999 0.1875000000000000 8625 + 0.3749999999999999 0.2000000000000000 8626 + 0.3749999999999999 0.2125000000000000 8627 + 0.3750000000000000 0.2250000000000000 8628 + 0.3750000000000000 0.2375000000000000 8629 + 0.3750000000000000 0.2500000000000000 8630 + 0.3750000000000000 0.2625000000000000 8631 + 0.3750000000000000 0.2750000000000000 8632 + 0.3750000000000001 0.2875000000000000 8633 + 0.3750000000000001 0.3000000000000000 8634 + 0.3750000000000001 0.3125000000000000 8635 + 0.3750000000000001 0.3250000000000000 8636 + 0.3750000000000001 0.3375000000000000 8637 + 0.3750000000000000 0.3500000000000000 8638 + 0.3750000000000000 0.3625000000000000 8639 + 0.3750000000000000 0.3750000000000000 8640 + 0.3750000000000000 0.3875000000000001 8641 + 0.3750000000000000 0.4000000000000000 8642 + 0.3749999999999999 0.4125000000000000 8643 + 0.3749999999999999 0.4250000000000000 8644 + 0.3749999999999999 0.4375000000000000 8645 + 0.3749999999999999 0.4500000000000000 8646 + 0.3749999999999999 0.4625000000000000 8647 + 0.3750000000000000 0.4750000000000000 8648 + 0.3750000000000000 0.4875000000000000 8649 + 0.3750000000000000 0.5000000000000000 8650 + 0.3625000000000000 0.000000000000000 8651 + 0.3625000000000000 0.01250000000000000 8652 + 0.3625000000000002 0.02500000000000000 8653 + 0.3625000000000000 0.03750000000000001 8654 + 0.3624999999999999 0.05000000000000000 8655 + 0.3624999999999999 0.06250000000000000 8656 + 0.3624999999999999 0.07500000000000001 8657 + 0.3624999999999999 0.08750000000000002 8658 + 0.3624999999999999 0.1000000000000000 8659 + 0.3625000000000000 0.1125000000000000 8660 + 0.3624999999999998 0.1250000000000000 8661 + 0.3624999999999998 0.1375000000000000 8662 + 0.3625000000000000 0.1500000000000000 8663 + 0.3625000000000001 0.1625000000000000 8664 + 0.3625000000000000 0.1750000000000000 8665 + 0.3625000000000000 0.1875000000000000 8666 + 0.3625000000000000 0.2000000000000000 8667 + 0.3624999999999998 0.2125000000000000 8668 + 0.3625000000000000 0.2250000000000000 8669 + 0.3624999999999998 0.2375000000000000 8670 + 0.3624999999999998 0.2500000000000000 8671 + 0.3624999999999999 0.2625000000000000 8672 + 0.3624999999999999 0.2750000000000000 8673 + 0.3624999999999999 0.2875000000000000 8674 + 0.3624999999999999 0.3000000000000000 8675 + 0.3624999999999998 0.3125000000000000 8676 + 0.3624999999999998 0.3250000000000000 8677 + 0.3624999999999998 0.3375000000000000 8678 + 0.3624999999999998 0.3500000000000000 8679 + 0.3624999999999998 0.3625000000000000 8680 + 0.3624999999999998 0.3750000000000000 8681 + 0.3624999999999998 0.3875000000000000 8682 + 0.3624999999999998 0.4000000000000000 8683 + 0.3624999999999998 0.4125000000000001 8684 + 0.3624999999999996 0.4250000000000000 8685 + 0.3624999999999996 0.4375000000000000 8686 + 0.3624999999999996 0.4500000000000000 8687 + 0.3624999999999996 0.4625000000000000 8688 + 0.3624999999999997 0.4750000000000000 8689 + 0.3624999999999997 0.4875000000000000 8690 + 0.3624999999999997 0.5000000000000000 8691 + 0.3500000000000000 0.000000000000000 8692 + 0.3499999999999999 0.01250000000000000 8693 + 0.3499999999999998 0.02500000000000000 8694 + 0.3500000000000000 0.03750000000000001 8695 + 0.3500000000000001 0.05000000000000000 8696 + 0.3500000000000001 0.06250000000000000 8697 + 0.3500000000000001 0.07500000000000001 8698 + 0.3500000000000000 0.08750000000000001 8699 + 0.3499999999999999 0.1000000000000000 8700 + 0.3500000000000000 0.1125000000000000 8701 + 0.3500000000000000 0.1250000000000000 8702 + 0.3500000000000000 0.1375000000000000 8703 + 0.3500000000000000 0.1500000000000000 8704 + 0.3500000000000000 0.1625000000000000 8705 + 0.3499999999999999 0.1750000000000000 8706 + 0.3499999999999999 0.1875000000000000 8707 + 0.3499999999999999 0.2000000000000000 8708 + 0.3499999999999999 0.2125000000000000 8709 + 0.3499999999999997 0.2250000000000000 8710 + 0.3499999999999997 0.2375000000000000 8711 + 0.3499999999999997 0.2500000000000000 8712 + 0.3499999999999997 0.2625000000000000 8713 + 0.3499999999999997 0.2750000000000000 8714 + 0.3499999999999999 0.2875000000000000 8715 + 0.3499999999999999 0.3000000000000000 8716 + 0.3499999999999999 0.3125000000000000 8717 + 0.3499999999999999 0.3250000000000000 8718 + 0.3499999999999999 0.3375000000000000 8719 + 0.3499999999999998 0.3500000000000000 8720 + 0.3499999999999998 0.3625000000000000 8721 + 0.3499999999999998 0.3750000000000000 8722 + 0.3499999999999998 0.3875000000000000 8723 + 0.3499999999999998 0.4000000000000000 8724 + 0.3499999999999999 0.4125000000000001 8725 + 0.3499999999999999 0.4250000000000000 8726 + 0.3499999999999999 0.4375000000000000 8727 + 0.3499999999999996 0.4500000000000000 8728 + 0.3499999999999999 0.4625000000000000 8729 + 0.3499999999999997 0.4750000000000000 8730 + 0.3499999999999997 0.4875000000000000 8731 + 0.3499999999999997 0.5000000000000000 8732 + 0.3375000000000000 0.000000000000000 8733 + 0.3375000000000000 0.01250000000000000 8734 + 0.3374999999999999 0.02500000000000000 8735 + 0.3375000000000000 0.03750000000000001 8736 + 0.3374999999999999 0.05000000000000000 8737 + 0.3374999999999999 0.06250000000000000 8738 + 0.3374999999999999 0.07500000000000001 8739 + 0.3375000000000000 0.08750000000000001 8740 + 0.3375000000000000 0.1000000000000000 8741 + 0.3375000000000001 0.1125000000000000 8742 + 0.3375000000000001 0.1250000000000000 8743 + 0.3374999999999999 0.1375000000000000 8744 + 0.3374999999999999 0.1500000000000000 8745 + 0.3375000000000000 0.1625000000000000 8746 + 0.3374999999999999 0.1750000000000000 8747 + 0.3374999999999999 0.1875000000000000 8748 + 0.3375000000000000 0.2000000000000000 8749 + 0.3375000000000000 0.2125000000000000 8750 + 0.3375000000000000 0.2250000000000000 8751 + 0.3374999999999997 0.2375000000000000 8752 + 0.3374999999999999 0.2500000000000000 8753 + 0.3374999999999999 0.2625000000000000 8754 + 0.3374999999999999 0.2750000000000000 8755 + 0.3374999999999999 0.2875000000000000 8756 + 0.3374999999999999 0.3000000000000000 8757 + 0.3374999999999999 0.3125000000000000 8758 + 0.3374999999999999 0.3250000000000000 8759 + 0.3374999999999999 0.3375000000000000 8760 + 0.3374999999999999 0.3500000000000000 8761 + 0.3374999999999997 0.3625000000000000 8762 + 0.3374999999999997 0.3750000000000000 8763 + 0.3374999999999997 0.3875000000000000 8764 + 0.3374999999999997 0.4000000000000000 8765 + 0.3374999999999997 0.4125000000000000 8766 + 0.3374999999999997 0.4250000000000000 8767 + 0.3374999999999997 0.4375000000000000 8768 + 0.3374999999999997 0.4500000000000000 8769 + 0.3374999999999997 0.4625000000000000 8770 + 0.3374999999999997 0.4750000000000000 8771 + 0.3374999999999997 0.4875000000000000 8772 + 0.3374999999999997 0.5000000000000000 8773 + 0.3250000000000000 0.000000000000000 8774 + 0.3250000000000000 0.01250000000000000 8775 + 0.3249999999999999 0.02500000000000000 8776 + 0.3250000000000001 0.03750000000000001 8777 + 0.3250000000000000 0.05000000000000000 8778 + 0.3250000000000000 0.06250000000000000 8779 + 0.3250000000000000 0.07500000000000001 8780 + 0.3250000000000000 0.08750000000000001 8781 + 0.3250000000000000 0.1000000000000000 8782 + 0.3250000000000001 0.1125000000000000 8783 + 0.3250000000000001 0.1250000000000000 8784 + 0.3250000000000001 0.1375000000000000 8785 + 0.3250000000000000 0.1500000000000000 8786 + 0.3249999999999998 0.1625000000000000 8787 + 0.3250000000000000 0.1750000000000000 8788 + 0.3250000000000000 0.1875000000000000 8789 + 0.3249999999999998 0.2000000000000000 8790 + 0.3249999999999998 0.2125000000000000 8791 + 0.3249999999999998 0.2250000000000000 8792 + 0.3249999999999998 0.2375000000000000 8793 + 0.3250000000000000 0.2500000000000000 8794 + 0.3249999999999997 0.2625000000000000 8795 + 0.3250000000000000 0.2750000000000000 8796 + 0.3249999999999997 0.2875000000000000 8797 + 0.3249999999999997 0.3000000000000000 8798 + 0.3249999999999999 0.3125000000000000 8799 + 0.3249999999999999 0.3250000000000000 8800 + 0.3249999999999999 0.3375000000000000 8801 + 0.3249999999999999 0.3500000000000000 8802 + 0.3250000000000000 0.3625000000000000 8803 + 0.3250000000000000 0.3750000000000000 8804 + 0.3250000000000000 0.3875000000000000 8805 + 0.3250000000000000 0.4000000000000000 8806 + 0.3250000000000000 0.4125000000000001 8807 + 0.3249999999999998 0.4250000000000000 8808 + 0.3249999999999998 0.4375000000000000 8809 + 0.3249999999999998 0.4500000000000001 8810 + 0.3249999999999998 0.4625000000000000 8811 + 0.3249999999999997 0.4749999999999999 8812 + 0.3249999999999997 0.4875000000000000 8813 + 0.3249999999999998 0.5000000000000000 8814 + 0.3125000000000000 0.000000000000000 8815 + 0.3125000000000000 0.01250000000000000 8816 + 0.3125000000000001 0.02500000000000000 8817 + 0.3125000000000001 0.03750000000000001 8818 + 0.3124999999999999 0.05000000000000000 8819 + 0.3124999999999999 0.06250000000000000 8820 + 0.3124999999999999 0.07500000000000001 8821 + 0.3124999999999999 0.08749999999999999 8822 + 0.3125000000000001 0.1000000000000000 8823 + 0.3125000000000000 0.1125000000000000 8824 + 0.3125000000000000 0.1250000000000000 8825 + 0.3125000000000000 0.1375000000000000 8826 + 0.3124999999999998 0.1500000000000000 8827 + 0.3124999999999999 0.1625000000000000 8828 + 0.3124999999999998 0.1750000000000000 8829 + 0.3124999999999998 0.1875000000000000 8830 + 0.3125000000000000 0.2000000000000000 8831 + 0.3125000000000000 0.2125000000000000 8832 + 0.3125000000000000 0.2250000000000000 8833 + 0.3125000000000000 0.2375000000000001 8834 + 0.3125000000000000 0.2500000000000000 8835 + 0.3124999999999999 0.2625000000000000 8836 + 0.3124999999999999 0.2750000000000000 8837 + 0.3124999999999999 0.2875000000000000 8838 + 0.3124999999999999 0.3000000000000000 8839 + 0.3124999999999998 0.3125000000000000 8840 + 0.3124999999999998 0.3250000000000000 8841 + 0.3124999999999998 0.3375000000000000 8842 + 0.3124999999999998 0.3500000000000000 8843 + 0.3124999999999998 0.3625000000000000 8844 + 0.3124999999999998 0.3750000000000000 8845 + 0.3124999999999998 0.3875000000000000 8846 + 0.3124999999999998 0.4000000000000000 8847 + 0.3124999999999998 0.4125000000000000 8848 + 0.3125000000000000 0.4250000000000000 8849 + 0.3124999999999998 0.4375000000000000 8850 + 0.3124999999999998 0.4500000000000001 8851 + 0.3124999999999998 0.4625000000000000 8852 + 0.3124999999999999 0.4750000000000000 8853 + 0.3124999999999999 0.4875000000000000 8854 + 0.3124999999999998 0.5000000000000000 8855 + 0.3000000000000000 0.000000000000000 8856 + 0.3000000000000000 0.01250000000000000 8857 + 0.3000000000000000 0.02500000000000000 8858 + 0.3000000000000001 0.03750000000000001 8859 + 0.3000000000000000 0.05000000000000000 8860 + 0.3000000000000000 0.06250000000000000 8861 + 0.3000000000000000 0.07500000000000001 8862 + 0.2999999999999999 0.08750000000000001 8863 + 0.3000000000000000 0.1000000000000000 8864 + 0.3000000000000000 0.1125000000000000 8865 + 0.3000000000000000 0.1250000000000000 8866 + 0.3000000000000000 0.1375000000000000 8867 + 0.2999999999999999 0.1500000000000000 8868 + 0.3000000000000000 0.1625000000000000 8869 + 0.2999999999999999 0.1750000000000000 8870 + 0.2999999999999999 0.1875000000000000 8871 + 0.3000000000000000 0.2000000000000000 8872 + 0.3000000000000000 0.2125000000000000 8873 + 0.3000000000000000 0.2250000000000000 8874 + 0.2999999999999999 0.2375000000000000 8875 + 0.2999999999999999 0.2500000000000000 8876 + 0.3000000000000000 0.2625000000000000 8877 + 0.3000000000000000 0.2750000000000000 8878 + 0.3000000000000000 0.2875000000000000 8879 + 0.3000000000000000 0.3000000000000000 8880 + 0.2999999999999999 0.3125000000000000 8881 + 0.2999999999999999 0.3250000000000000 8882 + 0.2999999999999999 0.3375000000000000 8883 + 0.2999999999999999 0.3500000000000000 8884 + 0.2999999999999999 0.3625000000000000 8885 + 0.2999999999999999 0.3750000000000000 8886 + 0.2999999999999999 0.3875000000000001 8887 + 0.2999999999999999 0.4000000000000000 8888 + 0.2999999999999999 0.4124999999999999 8889 + 0.2999999999999999 0.4250000000000000 8890 + 0.2999999999999999 0.4375000000000000 8891 + 0.2999999999999999 0.4499999999999999 8892 + 0.2999999999999998 0.4625000000000000 8893 + 0.3000000000000000 0.4750000000000001 8894 + 0.3000000000000000 0.4875000000000000 8895 + 0.2999999999999999 0.5000000000000000 8896 + 0.2875000000000000 0.000000000000000 8897 + 0.2875000000000001 0.01250000000000000 8898 + 0.2875000000000000 0.02500000000000000 8899 + 0.2875000000000001 0.03750000000000001 8900 + 0.2875000000000000 0.05000000000000000 8901 + 0.2875000000000000 0.06250000000000000 8902 + 0.2874999999999999 0.07500000000000001 8903 + 0.2875000000000000 0.08750000000000001 8904 + 0.2875000000000000 0.1000000000000000 8905 + 0.2874999999999999 0.1125000000000000 8906 + 0.2874999999999999 0.1250000000000000 8907 + 0.2874999999999999 0.1375000000000000 8908 + 0.2874999999999999 0.1500000000000000 8909 + 0.2874999999999998 0.1625000000000000 8910 + 0.2874999999999999 0.1750000000000000 8911 + 0.2874999999999999 0.1875000000000000 8912 + 0.2874999999999999 0.2000000000000000 8913 + 0.2874999999999999 0.2125000000000000 8914 + 0.2874999999999999 0.2250000000000000 8915 + 0.2874999999999998 0.2375000000000000 8916 + 0.2874999999999998 0.2500000000000000 8917 + 0.2874999999999998 0.2625000000000000 8918 + 0.2874999999999998 0.2750000000000000 8919 + 0.2874999999999998 0.2875000000000000 8920 + 0.2874999999999998 0.3000000000000000 8921 + 0.2874999999999998 0.3125000000000000 8922 + 0.2874999999999996 0.3250000000000000 8923 + 0.2874999999999997 0.3375000000000000 8924 + 0.2874999999999997 0.3500000000000000 8925 + 0.2874999999999997 0.3625000000000000 8926 + 0.2874999999999996 0.3750000000000000 8927 + 0.2874999999999996 0.3875000000000000 8928 + 0.2874999999999996 0.4000000000000000 8929 + 0.2874999999999996 0.4125000000000001 8930 + 0.2874999999999996 0.4250000000000000 8931 + 0.2874999999999996 0.4375000000000000 8932 + 0.2874999999999996 0.4500000000000001 8933 + 0.2874999999999996 0.4625000000000000 8934 + 0.2874999999999995 0.4749999999999999 8935 + 0.2874999999999995 0.4875000000000000 8936 + 0.2874999999999995 0.5000000000000000 8937 + 0.2750000000000000 0.000000000000000 8938 + 0.2750000000000001 0.01250000000000000 8939 + 0.2750000000000000 0.02500000000000000 8940 + 0.2750000000000000 0.03750000000000001 8941 + 0.2750000000000000 0.05000000000000000 8942 + 0.2750000000000000 0.06250000000000000 8943 + 0.2750000000000000 0.07500000000000001 8944 + 0.2750000000000000 0.08750000000000001 8945 + 0.2750000000000001 0.1000000000000000 8946 + 0.2750000000000000 0.1125000000000000 8947 + 0.2750000000000000 0.1250000000000000 8948 + 0.2750000000000000 0.1375000000000000 8949 + 0.2750000000000000 0.1500000000000000 8950 + 0.2750000000000000 0.1625000000000000 8951 + 0.2750000000000000 0.1750000000000000 8952 + 0.2750000000000000 0.1875000000000000 8953 + 0.2750000000000000 0.2000000000000000 8954 + 0.2749999999999999 0.2125000000000000 8955 + 0.2750000000000001 0.2250000000000000 8956 + 0.2750000000000001 0.2375000000000000 8957 + 0.2750000000000001 0.2500000000000000 8958 + 0.2750000000000001 0.2625000000000000 8959 + 0.2750000000000001 0.2750000000000000 8960 + 0.2749999999999999 0.2875000000000000 8961 + 0.2750000000000000 0.3000000000000000 8962 + 0.2749999999999999 0.3125000000000000 8963 + 0.2750000000000000 0.3250000000000000 8964 + 0.2749999999999999 0.3375000000000000 8965 + 0.2750000000000000 0.3500000000000000 8966 + 0.2750000000000000 0.3625000000000000 8967 + 0.2750000000000000 0.3750000000000000 8968 + 0.2750000000000000 0.3875000000000000 8969 + 0.2750000000000000 0.4000000000000000 8970 + 0.2749999999999999 0.4125000000000000 8971 + 0.2749999999999999 0.4250000000000000 8972 + 0.2749999999999999 0.4375000000000000 8973 + 0.2749999999999999 0.4499999999999999 8974 + 0.2749999999999999 0.4625000000000000 8975 + 0.2750000000000001 0.4750000000000000 8976 + 0.2750000000000001 0.4875000000000000 8977 + 0.2750000000000000 0.5000000000000000 8978 + 0.2625000000000000 0.000000000000000 8979 + 0.2624999999999999 0.01250000000000000 8980 + 0.2625000000000000 0.02500000000000000 8981 + 0.2625000000000001 0.03750000000000001 8982 + 0.2625000000000000 0.05000000000000000 8983 + 0.2625000000000000 0.06250000000000000 8984 + 0.2625000000000000 0.07500000000000001 8985 + 0.2624999999999999 0.08750000000000001 8986 + 0.2624999999999999 0.1000000000000000 8987 + 0.2625000000000000 0.1125000000000000 8988 + 0.2625000000000000 0.1250000000000000 8989 + 0.2624999999999998 0.1375000000000000 8990 + 0.2625000000000000 0.1500000000000000 8991 + 0.2624999999999998 0.1625000000000000 8992 + 0.2624999999999998 0.1750000000000000 8993 + 0.2624999999999998 0.1875000000000000 8994 + 0.2624999999999999 0.2000000000000000 8995 + 0.2624999999999999 0.2125000000000000 8996 + 0.2624999999999999 0.2250000000000000 8997 + 0.2624999999999999 0.2375000000000000 8998 + 0.2624999999999998 0.2500000000000000 8999 + 0.2624999999999997 0.2625000000000000 9000 + 0.2624999999999997 0.2750000000000000 9001 + 0.2624999999999997 0.2875000000000000 9002 + 0.2624999999999997 0.3000000000000000 9003 + 0.2624999999999998 0.3125000000000000 9004 + 0.2624999999999998 0.3250000000000000 9005 + 0.2624999999999998 0.3375000000000000 9006 + 0.2624999999999998 0.3500000000000001 9007 + 0.2624999999999997 0.3625000000000000 9008 + 0.2624999999999997 0.3750000000000000 9009 + 0.2624999999999997 0.3875000000000000 9010 + 0.2624999999999997 0.4000000000000000 9011 + 0.2624999999999997 0.4125000000000001 9012 + 0.2624999999999997 0.4250000000000000 9013 + 0.2624999999999997 0.4375000000000000 9014 + 0.2624999999999997 0.4500000000000001 9015 + 0.2624999999999997 0.4625000000000000 9016 + 0.2624999999999996 0.4750000000000000 9017 + 0.2624999999999996 0.4875000000000000 9018 + 0.2624999999999996 0.5000000000000000 9019 + 0.2500000000000000 0.000000000000000 9020 + 0.2500000000000000 0.01250000000000000 9021 + 0.2500000000000000 0.02500000000000000 9022 + 0.2499999999999999 0.03750000000000001 9023 + 0.2500000000000001 0.05000000000000000 9024 + 0.2500000000000001 0.06250000000000000 9025 + 0.2500000000000001 0.07500000000000001 9026 + 0.2499999999999999 0.08750000000000001 9027 + 0.2499999999999999 0.1000000000000000 9028 + 0.2500000000000000 0.1125000000000000 9029 + 0.2500000000000000 0.1250000000000000 9030 + 0.2500000000000000 0.1375000000000000 9031 + 0.2500000000000000 0.1500000000000000 9032 + 0.2500000000000000 0.1625000000000000 9033 + 0.2500000000000000 0.1750000000000000 9034 + 0.2499999999999999 0.1875000000000000 9035 + 0.2499999999999999 0.2000000000000000 9036 + 0.2499999999999999 0.2125000000000000 9037 + 0.2500000000000002 0.2250000000000000 9038 + 0.2499999999999999 0.2375000000000001 9039 + 0.2500000000000000 0.2500000000000000 9040 + 0.2500000000000000 0.2625000000000000 9041 + 0.2500000000000000 0.2750000000000000 9042 + 0.2500000000000000 0.2875000000000000 9043 + 0.2500000000000000 0.3000000000000000 9044 + 0.2500000000000000 0.3125000000000000 9045 + 0.2500000000000001 0.3250000000000000 9046 + 0.2500000000000001 0.3375000000000000 9047 + 0.2500000000000001 0.3500000000000000 9048 + 0.2500000000000001 0.3625000000000000 9049 + 0.2500000000000001 0.3750000000000000 9050 + 0.2500000000000001 0.3875000000000000 9051 + 0.2500000000000000 0.4000000000000000 9052 + 0.2500000000000000 0.4125000000000000 9053 + 0.2500000000000000 0.4250000000000000 9054 + 0.2500000000000000 0.4375000000000000 9055 + 0.2500000000000000 0.4500000000000001 9056 + 0.2500000000000000 0.4625000000000000 9057 + 0.2500000000000002 0.4750000000000001 9058 + 0.2500000000000002 0.4875000000000000 9059 + 0.2500000000000001 0.5000000000000000 9060 + 0.2375000000000000 0.000000000000000 9061 + 0.2375000000000000 0.01250000000000000 9062 + 0.2374999999999999 0.02500000000000000 9063 + 0.2375000000000000 0.03750000000000001 9064 + 0.2374999999999999 0.05000000000000000 9065 + 0.2374999999999999 0.06250000000000000 9066 + 0.2374999999999999 0.07500000000000001 9067 + 0.2374999999999999 0.08750000000000002 9068 + 0.2375000000000000 0.1000000000000000 9069 + 0.2374999999999999 0.1125000000000000 9070 + 0.2374999999999999 0.1250000000000000 9071 + 0.2374999999999999 0.1375000000000000 9072 + 0.2374999999999999 0.1500000000000000 9073 + 0.2374999999999999 0.1625000000000000 9074 + 0.2374999999999998 0.1750000000000000 9075 + 0.2374999999999999 0.1875000000000000 9076 + 0.2374999999999999 0.2000000000000000 9077 + 0.2374999999999999 0.2125000000000000 9078 + 0.2374999999999999 0.2250000000000001 9079 + 0.2374999999999999 0.2375000000000000 9080 + 0.2374999999999998 0.2500000000000000 9081 + 0.2374999999999998 0.2625000000000000 9082 + 0.2374999999999998 0.2750000000000000 9083 + 0.2374999999999998 0.2875000000000000 9084 + 0.2374999999999998 0.3000000000000000 9085 + 0.2374999999999998 0.3125000000000000 9086 + 0.2374999999999998 0.3250000000000000 9087 + 0.2374999999999998 0.3375000000000000 9088 + 0.2374999999999998 0.3500000000000000 9089 + 0.2374999999999997 0.3625000000000000 9090 + 0.2374999999999998 0.3750000000000000 9091 + 0.2374999999999997 0.3875000000000000 9092 + 0.2374999999999998 0.4000000000000000 9093 + 0.2374999999999998 0.4125000000000001 9094 + 0.2374999999999998 0.4250000000000000 9095 + 0.2374999999999997 0.4375000000000000 9096 + 0.2374999999999997 0.4499999999999999 9097 + 0.2374999999999997 0.4625000000000000 9098 + 0.2374999999999997 0.4750000000000000 9099 + 0.2374999999999997 0.4875000000000000 9100 + 0.2374999999999997 0.5000000000000000 9101 + 0.2250000000000000 0.000000000000000 9102 + 0.2250000000000000 0.01250000000000000 9103 + 0.2250000000000000 0.02500000000000000 9104 + 0.2250000000000000 0.03750000000000001 9105 + 0.2250000000000000 0.05000000000000000 9106 + 0.2250000000000000 0.06250000000000000 9107 + 0.2250000000000000 0.07500000000000001 9108 + 0.2250000000000000 0.08750000000000001 9109 + 0.2250000000000000 0.1000000000000000 9110 + 0.2250000000000000 0.1125000000000000 9111 + 0.2250000000000000 0.1250000000000000 9112 + 0.2249999999999999 0.1375000000000000 9113 + 0.2249999999999999 0.1500000000000000 9114 + 0.2249999999999999 0.1625000000000000 9115 + 0.2250000000000000 0.1750000000000000 9116 + 0.2250000000000000 0.1875000000000000 9117 + 0.2250000000000000 0.2000000000000000 9118 + 0.2249999999999999 0.2125000000000000 9119 + 0.2249999999999999 0.2250000000000000 9120 + 0.2249999999999999 0.2375000000000000 9121 + 0.2249999999999999 0.2500000000000000 9122 + 0.2249999999999999 0.2625000000000000 9123 + 0.2249999999999999 0.2750000000000000 9124 + 0.2249999999999999 0.2875000000000000 9125 + 0.2249999999999999 0.3000000000000000 9126 + 0.2249999999999999 0.3125000000000000 9127 + 0.2249999999999999 0.3250000000000000 9128 + 0.2249999999999999 0.3375000000000000 9129 + 0.2249999999999999 0.3500000000000001 9130 + 0.2249999999999999 0.3625000000000000 9131 + 0.2249999999999999 0.3750000000000000 9132 + 0.2249999999999999 0.3875000000000000 9133 + 0.2249999999999999 0.4000000000000000 9134 + 0.2249999999999998 0.4125000000000000 9135 + 0.2249999999999998 0.4250000000000000 9136 + 0.2249999999999998 0.4375000000000000 9137 + 0.2249999999999998 0.4499999999999999 9138 + 0.2249999999999998 0.4625000000000000 9139 + 0.2249999999999998 0.4750000000000001 9140 + 0.2249999999999998 0.4875000000000000 9141 + 0.2249999999999998 0.5000000000000000 9142 + 0.2125000000000000 0.000000000000000 9143 + 0.2125000000000000 0.01250000000000000 9144 + 0.2125000000000000 0.02500000000000000 9145 + 0.2125000000000000 0.03750000000000001 9146 + 0.2125000000000000 0.05000000000000000 9147 + 0.2125000000000000 0.06250000000000000 9148 + 0.2124999999999999 0.07500000000000001 9149 + 0.2125000000000000 0.08750000000000001 9150 + 0.2125000000000000 0.1000000000000000 9151 + 0.2125000000000000 0.1125000000000000 9152 + 0.2125000000000000 0.1250000000000000 9153 + 0.2125000000000000 0.1375000000000000 9154 + 0.2124999999999999 0.1500000000000000 9155 + 0.2124999999999999 0.1625000000000000 9156 + 0.2124999999999999 0.1750000000000000 9157 + 0.2124999999999999 0.1875000000000000 9158 + 0.2124999999999999 0.2000000000000000 9159 + 0.2124999999999999 0.2125000000000000 9160 + 0.2124999999999999 0.2250000000000000 9161 + 0.2124999999999999 0.2375000000000000 9162 + 0.2124999999999999 0.2500000000000000 9163 + 0.2124999999999999 0.2625000000000000 9164 + 0.2124999999999999 0.2750000000000000 9165 + 0.2124999999999999 0.2875000000000000 9166 + 0.2124999999999999 0.3000000000000000 9167 + 0.2124999999999999 0.3125000000000000 9168 + 0.2124999999999999 0.3250000000000000 9169 + 0.2124999999999999 0.3375000000000000 9170 + 0.2124999999999999 0.3500000000000000 9171 + 0.2124999999999999 0.3625000000000000 9172 + 0.2124999999999999 0.3750000000000000 9173 + 0.2124999999999999 0.3875000000000000 9174 + 0.2124999999999998 0.4000000000000000 9175 + 0.2124999999999998 0.4125000000000000 9176 + 0.2124999999999998 0.4250000000000000 9177 + 0.2124999999999998 0.4375000000000000 9178 + 0.2124999999999998 0.4500000000000000 9179 + 0.2124999999999998 0.4625000000000000 9180 + 0.2124999999999998 0.4750000000000000 9181 + 0.2124999999999998 0.4875000000000000 9182 + 0.2124999999999998 0.5000000000000000 9183 + 0.2000000000000000 0.000000000000000 9184 + 0.2000000000000001 0.01250000000000000 9185 + 0.2000000000000000 0.02500000000000000 9186 + 0.2000000000000001 0.03750000000000001 9187 + 0.2000000000000000 0.05000000000000000 9188 + 0.2000000000000000 0.06250000000000000 9189 + 0.2000000000000000 0.07500000000000001 9190 + 0.2000000000000000 0.08750000000000002 9191 + 0.2000000000000000 0.1000000000000000 9192 + 0.2000000000000000 0.1125000000000000 9193 + 0.2000000000000000 0.1250000000000000 9194 + 0.2000000000000000 0.1375000000000000 9195 + 0.2000000000000000 0.1500000000000000 9196 + 0.2000000000000000 0.1625000000000000 9197 + 0.2000000000000000 0.1750000000000000 9198 + 0.2000000000000000 0.1875000000000000 9199 + 0.2000000000000000 0.2000000000000000 9200 + 0.2000000000000000 0.2125000000000000 9201 + 0.2000000000000000 0.2250000000000001 9202 + 0.1999999999999998 0.2375000000000000 9203 + 0.2000000000000000 0.2500000000000000 9204 + 0.2000000000000000 0.2625000000000000 9205 + 0.1999999999999998 0.2750000000000000 9206 + 0.2000000000000000 0.2875000000000000 9207 + 0.2000000000000000 0.3000000000000000 9208 + 0.2000000000000000 0.3125000000000000 9209 + 0.2000000000000000 0.3250000000000000 9210 + 0.2000000000000000 0.3375000000000000 9211 + 0.1999999999999998 0.3500000000000000 9212 + 0.1999999999999998 0.3625000000000000 9213 + 0.1999999999999998 0.3750000000000000 9214 + 0.1999999999999998 0.3875000000000001 9215 + 0.1999999999999998 0.4000000000000000 9216 + 0.2000000000000000 0.4125000000000000 9217 + 0.1999999999999998 0.4250000000000000 9218 + 0.1999999999999998 0.4375000000000000 9219 + 0.1999999999999998 0.4500000000000000 9220 + 0.1999999999999998 0.4625000000000000 9221 + 0.1999999999999998 0.4750000000000000 9222 + 0.1999999999999998 0.4875000000000000 9223 + 0.1999999999999998 0.5000000000000000 9224 + 0.1875000000000000 0.000000000000000 9225 + 0.1875000000000000 0.01250000000000000 9226 + 0.1875000000000000 0.02500000000000000 9227 + 0.1875000000000000 0.03750000000000001 9228 + 0.1875000000000000 0.05000000000000000 9229 + 0.1875000000000000 0.06250000000000000 9230 + 0.1875000000000000 0.07500000000000001 9231 + 0.1875000000000000 0.08749999999999999 9232 + 0.1875000000000000 0.1000000000000000 9233 + 0.1875000000000000 0.1125000000000000 9234 + 0.1875000000000000 0.1250000000000000 9235 + 0.1875000000000000 0.1375000000000000 9236 + 0.1875000000000000 0.1500000000000000 9237 + 0.1875000000000000 0.1625000000000000 9238 + 0.1875000000000000 0.1750000000000000 9239 + 0.1875000000000000 0.1875000000000000 9240 + 0.1874999999999999 0.2000000000000000 9241 + 0.1874999999999999 0.2125000000000000 9242 + 0.1874999999999999 0.2250000000000000 9243 + 0.1874999999999999 0.2375000000000000 9244 + 0.1875000000000000 0.2500000000000000 9245 + 0.1875000000000000 0.2625000000000000 9246 + 0.1875000000000000 0.2750000000000000 9247 + 0.1875000000000000 0.2875000000000000 9248 + 0.1875000000000000 0.3000000000000000 9249 + 0.1874999999999999 0.3125000000000000 9250 + 0.1874999999999999 0.3250000000000000 9251 + 0.1874999999999999 0.3375000000000000 9252 + 0.1874999999999999 0.3500000000000001 9253 + 0.1874999999999999 0.3625000000000000 9254 + 0.1874999999999999 0.3750000000000000 9255 + 0.1874999999999999 0.3875000000000000 9256 + 0.1874999999999999 0.4000000000000000 9257 + 0.1874999999999999 0.4125000000000000 9258 + 0.1874999999999999 0.4250000000000000 9259 + 0.1874999999999999 0.4375000000000000 9260 + 0.1874999999999999 0.4499999999999999 9261 + 0.1874999999999999 0.4625000000000000 9262 + 0.1874999999999999 0.4750000000000001 9263 + 0.1874999999999999 0.4875000000000000 9264 + 0.1874999999999999 0.5000000000000000 9265 + 0.1750000000000000 0.000000000000000 9266 + 0.1750000000000000 0.01250000000000000 9267 + 0.1750000000000000 0.02500000000000000 9268 + 0.1750000000000000 0.03750000000000001 9269 + 0.1750000000000000 0.05000000000000000 9270 + 0.1749999999999999 0.06250000000000000 9271 + 0.1750000000000000 0.07500000000000001 9272 + 0.1750000000000000 0.08750000000000001 9273 + 0.1749999999999999 0.1000000000000000 9274 + 0.1750000000000000 0.1125000000000000 9275 + 0.1750000000000000 0.1250000000000000 9276 + 0.1750000000000000 0.1375000000000000 9277 + 0.1750000000000000 0.1500000000000000 9278 + 0.1750000000000000 0.1625000000000000 9279 + 0.1749999999999999 0.1750000000000000 9280 + 0.1749999999999999 0.1875000000000000 9281 + 0.1749999999999999 0.2000000000000000 9282 + 0.1749999999999999 0.2125000000000000 9283 + 0.1750000000000000 0.2250000000000000 9284 + 0.1750000000000000 0.2375000000000000 9285 + 0.1750000000000000 0.2500000000000000 9286 + 0.1750000000000000 0.2625000000000000 9287 + 0.1750000000000000 0.2750000000000000 9288 + 0.1749999999999999 0.2875000000000000 9289 + 0.1749999999999999 0.3000000000000000 9290 + 0.1749999999999999 0.3125000000000000 9291 + 0.1749999999999999 0.3250000000000000 9292 + 0.1749999999999999 0.3375000000000000 9293 + 0.1749999999999999 0.3500000000000000 9294 + 0.1749999999999999 0.3625000000000000 9295 + 0.1749999999999999 0.3750000000000000 9296 + 0.1749999999999999 0.3875000000000000 9297 + 0.1749999999999999 0.4000000000000000 9298 + 0.1749999999999999 0.4125000000000000 9299 + 0.1749999999999999 0.4250000000000000 9300 + 0.1749999999999999 0.4375000000000000 9301 + 0.1749999999999999 0.4500000000000000 9302 + 0.1749999999999999 0.4625000000000000 9303 + 0.1749999999999999 0.4750000000000000 9304 + 0.1749999999999999 0.4875000000000000 9305 + 0.1749999999999999 0.5000000000000000 9306 + 0.1625000000000000 0.000000000000000 9307 + 0.1625000000000000 0.01250000000000000 9308 + 0.1625000000000000 0.02500000000000000 9309 + 0.1625000000000000 0.03750000000000001 9310 + 0.1625000000000000 0.05000000000000000 9311 + 0.1625000000000000 0.06250000000000000 9312 + 0.1625000000000000 0.07500000000000001 9313 + 0.1625000000000000 0.08750000000000001 9314 + 0.1625000000000000 0.1000000000000000 9315 + 0.1624999999999999 0.1125000000000000 9316 + 0.1624999999999999 0.1250000000000000 9317 + 0.1624999999999999 0.1375000000000000 9318 + 0.1624999999999999 0.1500000000000000 9319 + 0.1624999999999999 0.1625000000000000 9320 + 0.1624999999999999 0.1750000000000000 9321 + 0.1624999999999999 0.1875000000000000 9322 + 0.1624999999999999 0.2000000000000000 9323 + 0.1624999999999999 0.2125000000000000 9324 + 0.1624999999999999 0.2250000000000000 9325 + 0.1624999999999999 0.2375000000000000 9326 + 0.1624999999999999 0.2500000000000000 9327 + 0.1624999999999998 0.2625000000000000 9328 + 0.1624999999999998 0.2750000000000000 9329 + 0.1624999999999998 0.2875000000000000 9330 + 0.1624999999999998 0.3000000000000000 9331 + 0.1624999999999998 0.3125000000000000 9332 + 0.1624999999999998 0.3250000000000001 9333 + 0.1624999999999998 0.3375000000000000 9334 + 0.1624999999999996 0.3500000000000000 9335 + 0.1624999999999998 0.3625000000000000 9336 + 0.1624999999999998 0.3750000000000000 9337 + 0.1624999999999996 0.3875000000000000 9338 + 0.1624999999999996 0.4000000000000000 9339 + 0.1624999999999996 0.4125000000000001 9340 + 0.1624999999999996 0.4250000000000000 9341 + 0.1624999999999996 0.4375000000000000 9342 + 0.1624999999999996 0.4500000000000000 9343 + 0.1624999999999996 0.4625000000000000 9344 + 0.1624999999999996 0.4750000000000000 9345 + 0.1624999999999996 0.4875000000000000 9346 + 0.1624999999999996 0.5000000000000000 9347 + 0.1500000000000000 0.000000000000000 9348 + 0.1500000000000000 0.01250000000000000 9349 + 0.1500000000000000 0.02500000000000000 9350 + 0.1500000000000000 0.03750000000000001 9351 + 0.1500000000000000 0.05000000000000000 9352 + 0.1500000000000000 0.06250000000000000 9353 + 0.1500000000000000 0.07500000000000001 9354 + 0.1500000000000000 0.08749999999999999 9355 + 0.1500000000000000 0.1000000000000000 9356 + 0.1500000000000000 0.1125000000000000 9357 + 0.1500000000000000 0.1250000000000000 9358 + 0.1500000000000000 0.1375000000000000 9359 + 0.1500000000000000 0.1500000000000000 9360 + 0.1500000000000000 0.1625000000000000 9361 + 0.1500000000000000 0.1750000000000000 9362 + 0.1500000000000000 0.1875000000000000 9363 + 0.1500000000000000 0.2000000000000000 9364 + 0.1500000000000000 0.2125000000000000 9365 + 0.1500000000000000 0.2250000000000000 9366 + 0.1500000000000000 0.2375000000000001 9367 + 0.1500000000000000 0.2500000000000000 9368 + 0.1500000000000000 0.2625000000000000 9369 + 0.1500000000000000 0.2750000000000000 9370 + 0.1500000000000000 0.2875000000000000 9371 + 0.1500000000000000 0.3000000000000000 9372 + 0.1500000000000000 0.3125000000000000 9373 + 0.1500000000000000 0.3250000000000000 9374 + 0.1500000000000000 0.3375000000000000 9375 + 0.1500000000000000 0.3500000000000000 9376 + 0.1500000000000000 0.3625000000000000 9377 + 0.1500000000000000 0.3750000000000000 9378 + 0.1500000000000000 0.3875000000000001 9379 + 0.1500000000000000 0.4000000000000000 9380 + 0.1500000000000000 0.4125000000000000 9381 + 0.1500000000000000 0.4250000000000000 9382 + 0.1500000000000000 0.4375000000000000 9383 + 0.1500000000000000 0.4500000000000000 9384 + 0.1500000000000000 0.4625000000000000 9385 + 0.1500000000000000 0.4750000000000001 9386 + 0.1500000000000000 0.4875000000000000 9387 + 0.1500000000000000 0.5000000000000000 9388 + 0.1375000000000000 0.000000000000000 9389 + 0.1375000000000000 0.01250000000000000 9390 + 0.1375000000000000 0.02500000000000000 9391 + 0.1375000000000000 0.03750000000000001 9392 + 0.1375000000000000 0.05000000000000000 9393 + 0.1375000000000000 0.06250000000000000 9394 + 0.1375000000000000 0.07500000000000001 9395 + 0.1375000000000000 0.08750000000000001 9396 + 0.1375000000000000 0.1000000000000000 9397 + 0.1375000000000000 0.1125000000000000 9398 + 0.1375000000000000 0.1250000000000000 9399 + 0.1374999999999998 0.1375000000000000 9400 + 0.1374999999999998 0.1500000000000000 9401 + 0.1375000000000000 0.1625000000000000 9402 + 0.1374999999999998 0.1750000000000000 9403 + 0.1374999999999998 0.1875000000000000 9404 + 0.1374999999999998 0.2000000000000000 9405 + 0.1374999999999998 0.2125000000000000 9406 + 0.1374999999999998 0.2250000000000000 9407 + 0.1374999999999998 0.2375000000000000 9408 + 0.1374999999999998 0.2500000000000000 9409 + 0.1374999999999998 0.2625000000000000 9410 + 0.1374999999999998 0.2750000000000000 9411 + 0.1374999999999998 0.2875000000000000 9412 + 0.1374999999999998 0.3000000000000000 9413 + 0.1374999999999998 0.3125000000000000 9414 + 0.1374999999999997 0.3250000000000000 9415 + 0.1374999999999997 0.3375000000000000 9416 + 0.1374999999999997 0.3500000000000000 9417 + 0.1374999999999997 0.3625000000000000 9418 + 0.1374999999999997 0.3750000000000000 9419 + 0.1374999999999997 0.3875000000000000 9420 + 0.1374999999999997 0.4000000000000000 9421 + 0.1374999999999997 0.4125000000000000 9422 + 0.1374999999999997 0.4250000000000000 9423 + 0.1374999999999997 0.4375000000000000 9424 + 0.1374999999999997 0.4500000000000001 9425 + 0.1374999999999997 0.4625000000000000 9426 + 0.1374999999999997 0.4750000000000000 9427 + 0.1374999999999997 0.4875000000000000 9428 + 0.1374999999999997 0.5000000000000000 9429 + 0.1250000000000000 0.000000000000000 9430 + 0.1250000000000000 0.01250000000000000 9431 + 0.1250000000000000 0.02500000000000000 9432 + 0.1250000000000000 0.03750000000000001 9433 + 0.1250000000000000 0.05000000000000000 9434 + 0.1250000000000000 0.06250000000000000 9435 + 0.1250000000000000 0.07500000000000001 9436 + 0.1250000000000000 0.08750000000000001 9437 + 0.1250000000000000 0.1000000000000000 9438 + 0.1250000000000000 0.1125000000000000 9439 + 0.1250000000000000 0.1250000000000000 9440 + 0.1250000000000000 0.1375000000000000 9441 + 0.1250000000000000 0.1500000000000000 9442 + 0.1250000000000000 0.1625000000000000 9443 + 0.1250000000000000 0.1750000000000000 9444 + 0.1250000000000000 0.1875000000000000 9445 + 0.1250000000000000 0.2000000000000000 9446 + 0.1250000000000000 0.2125000000000000 9447 + 0.1250000000000000 0.2250000000000000 9448 + 0.1250000000000000 0.2375000000000000 9449 + 0.1250000000000000 0.2500000000000000 9450 + 0.1250000000000001 0.2625000000000000 9451 + 0.1250000000000001 0.2750000000000000 9452 + 0.1250000000000001 0.2875000000000000 9453 + 0.1250000000000001 0.3000000000000000 9454 + 0.1250000000000001 0.3125000000000000 9455 + 0.1250000000000000 0.3250000000000000 9456 + 0.1250000000000000 0.3375000000000000 9457 + 0.1250000000000001 0.3500000000000000 9458 + 0.1250000000000001 0.3625000000000000 9459 + 0.1250000000000001 0.3750000000000000 9460 + 0.1250000000000001 0.3875000000000000 9461 + 0.1250000000000001 0.4000000000000000 9462 + 0.1250000000000001 0.4125000000000000 9463 + 0.1250000000000001 0.4250000000000000 9464 + 0.1250000000000001 0.4375000000000000 9465 + 0.1250000000000001 0.4499999999999999 9466 + 0.1250000000000001 0.4625000000000000 9467 + 0.1250000000000001 0.4750000000000000 9468 + 0.1250000000000001 0.4875000000000000 9469 + 0.1250000000000001 0.5000000000000000 9470 + 0.1125000000000000 0.000000000000000 9471 + 0.1125000000000000 0.01250000000000000 9472 + 0.1124999999999999 0.02500000000000000 9473 + 0.1124999999999999 0.03750000000000001 9474 + 0.1124999999999999 0.05000000000000000 9475 + 0.1124999999999999 0.06250000000000000 9476 + 0.1124999999999999 0.07500000000000001 9477 + 0.1124999999999999 0.08750000000000001 9478 + 0.1124999999999999 0.1000000000000000 9479 + 0.1124999999999999 0.1125000000000000 9480 + 0.1124999999999999 0.1250000000000000 9481 + 0.1124999999999999 0.1375000000000000 9482 + 0.1124999999999999 0.1500000000000000 9483 + 0.1124999999999999 0.1625000000000000 9484 + 0.1124999999999999 0.1750000000000000 9485 + 0.1124999999999999 0.1875000000000000 9486 + 0.1124999999999999 0.2000000000000000 9487 + 0.1124999999999999 0.2125000000000000 9488 + 0.1124999999999999 0.2250000000000000 9489 + 0.1124999999999999 0.2375000000000000 9490 + 0.1124999999999999 0.2500000000000000 9491 + 0.1124999999999999 0.2625000000000000 9492 + 0.1124999999999999 0.2750000000000000 9493 + 0.1124999999999998 0.2875000000000000 9494 + 0.1124999999999998 0.3000000000000000 9495 + 0.1124999999999998 0.3125000000000000 9496 + 0.1124999999999998 0.3250000000000000 9497 + 0.1124999999999998 0.3375000000000000 9498 + 0.1124999999999998 0.3500000000000000 9499 + 0.1124999999999998 0.3625000000000000 9500 + 0.1124999999999998 0.3750000000000000 9501 + 0.1124999999999998 0.3875000000000000 9502 + 0.1124999999999998 0.4000000000000000 9503 + 0.1124999999999998 0.4125000000000000 9504 + 0.1124999999999998 0.4250000000000000 9505 + 0.1124999999999998 0.4375000000000000 9506 + 0.1124999999999998 0.4500000000000000 9507 + 0.1124999999999998 0.4625000000000000 9508 + 0.1124999999999998 0.4750000000000001 9509 + 0.1124999999999998 0.4875000000000000 9510 + 0.1124999999999998 0.5000000000000000 9511 + 0.1000000000000000 0.000000000000000 9512 + 0.09999999999999998 0.01250000000000000 9513 + 0.09999999999999998 0.02500000000000000 9514 + 0.09999999999999998 0.03750000000000001 9515 + 0.09999999999999998 0.05000000000000000 9516 + 0.09999999999999998 0.06250000000000000 9517 + 0.09999999999999998 0.07500000000000001 9518 + 0.09999999999999998 0.08750000000000001 9519 + 0.09999999999999998 0.1000000000000000 9520 + 0.09999999999999998 0.1125000000000000 9521 + 0.09999999999999998 0.1250000000000000 9522 + 0.09999999999999998 0.1375000000000000 9523 + 0.09999999999999998 0.1500000000000000 9524 + 0.09999999999999998 0.1625000000000000 9525 + 0.09999999999999987 0.1750000000000000 9526 + 0.09999999999999998 0.1875000000000000 9527 + 0.09999999999999998 0.2000000000000000 9528 + 0.09999999999999998 0.2125000000000000 9529 + 0.09999999999999998 0.2250000000000000 9530 + 0.09999999999999987 0.2375000000000000 9531 + 0.09999999999999987 0.2500000000000000 9532 + 0.09999999999999987 0.2625000000000000 9533 + 0.09999999999999987 0.2750000000000000 9534 + 0.09999999999999987 0.2875000000000000 9535 + 0.09999999999999987 0.3000000000000000 9536 + 0.09999999999999987 0.3125000000000000 9537 + 0.09999999999999987 0.3250000000000000 9538 + 0.09999999999999987 0.3375000000000000 9539 + 0.09999999999999987 0.3500000000000000 9540 + 0.09999999999999987 0.3625000000000000 9541 + 0.09999999999999987 0.3750000000000000 9542 + 0.09999999999999987 0.3875000000000001 9543 + 0.09999999999999987 0.4000000000000000 9544 + 0.09999999999999987 0.4125000000000000 9545 + 0.09999999999999987 0.4250000000000000 9546 + 0.09999999999999987 0.4375000000000000 9547 + 0.09999999999999987 0.4500000000000000 9548 + 0.09999999999999987 0.4625000000000000 9549 + 0.09999999999999976 0.4749999999999999 9550 + 0.09999999999999976 0.4875000000000000 9551 + 0.09999999999999981 0.5000000000000000 9552 + 0.08750000000000001 0.000000000000000 9553 + 0.08750000000000002 0.01250000000000000 9554 + 0.08750000000000002 0.02500000000000000 9555 + 0.08750000000000002 0.03750000000000001 9556 + 0.08750000000000002 0.05000000000000000 9557 + 0.08750000000000002 0.06250000000000000 9558 + 0.08750000000000002 0.07500000000000001 9559 + 0.08750000000000002 0.08750000000000001 9560 + 0.08750000000000002 0.1000000000000000 9561 + 0.08750000000000002 0.1125000000000000 9562 + 0.08749999999999991 0.1250000000000000 9563 + 0.08749999999999991 0.1375000000000000 9564 + 0.08749999999999991 0.1500000000000000 9565 + 0.08750000000000002 0.1625000000000000 9566 + 0.08749999999999991 0.1750000000000000 9567 + 0.08749999999999991 0.1875000000000000 9568 + 0.08749999999999991 0.2000000000000000 9569 + 0.08749999999999991 0.2125000000000000 9570 + 0.08749999999999991 0.2250000000000000 9571 + 0.08749999999999991 0.2375000000000001 9572 + 0.08749999999999991 0.2500000000000000 9573 + 0.08749999999999991 0.2625000000000000 9574 + 0.08749999999999991 0.2750000000000000 9575 + 0.08749999999999991 0.2875000000000000 9576 + 0.08749999999999991 0.3000000000000000 9577 + 0.08749999999999991 0.3125000000000000 9578 + 0.08749999999999991 0.3250000000000000 9579 + 0.08749999999999991 0.3375000000000000 9580 + 0.08749999999999991 0.3500000000000000 9581 + 0.08749999999999991 0.3625000000000000 9582 + 0.08749999999999991 0.3750000000000000 9583 + 0.08749999999999991 0.3875000000000000 9584 + 0.08749999999999991 0.4000000000000000 9585 + 0.08749999999999991 0.4125000000000000 9586 + 0.08749999999999991 0.4250000000000000 9587 + 0.08749999999999991 0.4375000000000000 9588 + 0.08749999999999991 0.4500000000000001 9589 + 0.08749999999999991 0.4625000000000000 9590 + 0.08749999999999980 0.4750000000000001 9591 + 0.08749999999999980 0.4875000000000000 9592 + 0.08749999999999986 0.5000000000000000 9593 + 0.07500000000000001 0.000000000000000 9594 + 0.07500000000000007 0.01250000000000000 9595 + 0.07500000000000001 0.02500000000000000 9596 + 0.07500000000000001 0.03750000000000001 9597 + 0.07499999999999996 0.05000000000000000 9598 + 0.07499999999999996 0.06250000000000000 9599 + 0.07499999999999996 0.07500000000000001 9600 + 0.07500000000000001 0.08750000000000001 9601 + 0.07500000000000001 0.1000000000000000 9602 + 0.07499999999999996 0.1125000000000000 9603 + 0.07499999999999996 0.1250000000000000 9604 + 0.07499999999999996 0.1375000000000000 9605 + 0.07499999999999996 0.1500000000000000 9606 + 0.07500000000000001 0.1625000000000000 9607 + 0.07499999999999996 0.1750000000000000 9608 + 0.07499999999999996 0.1875000000000000 9609 + 0.07499999999999996 0.2000000000000000 9610 + 0.07499999999999996 0.2125000000000000 9611 + 0.07499999999999996 0.2250000000000000 9612 + 0.07499999999999996 0.2375000000000000 9613 + 0.07499999999999996 0.2500000000000000 9614 + 0.07499999999999996 0.2625000000000000 9615 + 0.07499999999999996 0.2750000000000000 9616 + 0.07499999999999996 0.2875000000000000 9617 + 0.07499999999999996 0.3000000000000000 9618 + 0.07499999999999996 0.3125000000000000 9619 + 0.07499999999999996 0.3250000000000000 9620 + 0.07499999999999996 0.3375000000000000 9621 + 0.07499999999999996 0.3500000000000000 9622 + 0.07499999999999996 0.3625000000000000 9623 + 0.07499999999999996 0.3750000000000000 9624 + 0.07499999999999996 0.3875000000000000 9625 + 0.07499999999999996 0.4000000000000000 9626 + 0.07499999999999996 0.4125000000000001 9627 + 0.07499999999999996 0.4250000000000000 9628 + 0.07499999999999984 0.4375000000000000 9629 + 0.07499999999999984 0.4500000000000000 9630 + 0.07499999999999984 0.4625000000000000 9631 + 0.07499999999999996 0.4749999999999999 9632 + 0.07499999999999996 0.4875000000000000 9633 + 0.07499999999999990 0.5000000000000000 9634 + 0.06250000000000000 0.000000000000000 9635 + 0.06250000000000000 0.01250000000000000 9636 + 0.06249999999999994 0.02500000000000000 9637 + 0.06249999999999994 0.03750000000000001 9638 + 0.06250000000000000 0.05000000000000000 9639 + 0.06250000000000000 0.06250000000000000 9640 + 0.06250000000000000 0.07500000000000001 9641 + 0.06249999999999994 0.08750000000000001 9642 + 0.06249999999999994 0.1000000000000000 9643 + 0.06250000000000000 0.1125000000000000 9644 + 0.06250000000000000 0.1250000000000000 9645 + 0.06250000000000000 0.1375000000000000 9646 + 0.06250000000000000 0.1500000000000000 9647 + 0.06249999999999994 0.1625000000000000 9648 + 0.06250000000000000 0.1750000000000000 9649 + 0.06250000000000000 0.1875000000000000 9650 + 0.06250000000000000 0.2000000000000000 9651 + 0.06250000000000000 0.2125000000000000 9652 + 0.06250000000000000 0.2250000000000000 9653 + 0.06250000000000000 0.2375000000000000 9654 + 0.06250000000000000 0.2500000000000000 9655 + 0.06250000000000000 0.2625000000000000 9656 + 0.06250000000000000 0.2750000000000000 9657 + 0.06250000000000000 0.2875000000000000 9658 + 0.06250000000000000 0.3000000000000000 9659 + 0.06250000000000000 0.3125000000000000 9660 + 0.06250000000000000 0.3250000000000000 9661 + 0.06250000000000000 0.3375000000000000 9662 + 0.06250000000000000 0.3500000000000001 9663 + 0.06250000000000000 0.3625000000000000 9664 + 0.06250000000000000 0.3750000000000000 9665 + 0.06250000000000000 0.3875000000000000 9666 + 0.06250000000000000 0.4000000000000000 9667 + 0.06250000000000000 0.4125000000000000 9668 + 0.06250000000000000 0.4250000000000000 9669 + 0.06250000000000000 0.4375000000000000 9670 + 0.06250000000000000 0.4499999999999999 9671 + 0.06250000000000000 0.4625000000000000 9672 + 0.06250000000000000 0.4750000000000001 9673 + 0.06250000000000000 0.4875000000000000 9674 + 0.06249999999999994 0.5000000000000000 9675 + 0.05000000000000000 0.000000000000000 9676 + 0.05000000000000004 0.01250000000000000 9677 + 0.04999999999999999 0.02500000000000000 9678 + 0.04999999999999999 0.03750000000000001 9679 + 0.05000000000000004 0.05000000000000000 9680 + 0.05000000000000004 0.06250000000000000 9681 + 0.05000000000000004 0.07500000000000001 9682 + 0.04999999999999999 0.08750000000000001 9683 + 0.04999999999999999 0.1000000000000000 9684 + 0.05000000000000004 0.1125000000000000 9685 + 0.05000000000000004 0.1250000000000000 9686 + 0.05000000000000004 0.1375000000000000 9687 + 0.05000000000000004 0.1500000000000000 9688 + 0.04999999999999999 0.1625000000000000 9689 + 0.05000000000000004 0.1750000000000000 9690 + 0.05000000000000004 0.1875000000000000 9691 + 0.05000000000000004 0.2000000000000000 9692 + 0.05000000000000004 0.2125000000000000 9693 + 0.05000000000000004 0.2250000000000000 9694 + 0.04999999999999993 0.2375000000000000 9695 + 0.05000000000000004 0.2500000000000000 9696 + 0.05000000000000004 0.2625000000000000 9697 + 0.05000000000000004 0.2750000000000000 9698 + 0.05000000000000004 0.2875000000000000 9699 + 0.05000000000000004 0.3000000000000000 9700 + 0.05000000000000004 0.3125000000000000 9701 + 0.04999999999999993 0.3250000000000000 9702 + 0.04999999999999993 0.3375000000000000 9703 + 0.05000000000000004 0.3500000000000000 9704 + 0.05000000000000004 0.3625000000000000 9705 + 0.04999999999999993 0.3750000000000000 9706 + 0.04999999999999993 0.3875000000000000 9707 + 0.05000000000000004 0.4000000000000000 9708 + 0.05000000000000004 0.4125000000000000 9709 + 0.05000000000000004 0.4250000000000000 9710 + 0.05000000000000004 0.4375000000000000 9711 + 0.05000000000000004 0.4500000000000001 9712 + 0.05000000000000004 0.4625000000000000 9713 + 0.04999999999999993 0.4750000000000001 9714 + 0.04999999999999993 0.4875000000000000 9715 + 0.04999999999999999 0.5000000000000000 9716 + 0.03750000000000001 0.000000000000000 9717 + 0.03749999999999998 0.01250000000000000 9718 + 0.03749999999999998 0.02500000000000000 9719 + 0.03749999999999998 0.03750000000000001 9720 + 0.03749999999999998 0.05000000000000000 9721 + 0.03749999999999998 0.06250000000000000 9722 + 0.03749999999999998 0.07500000000000001 9723 + 0.03749999999999992 0.08750000000000001 9724 + 0.03749999999999992 0.1000000000000000 9725 + 0.03749999999999992 0.1125000000000000 9726 + 0.03749999999999992 0.1250000000000000 9727 + 0.03749999999999992 0.1375000000000000 9728 + 0.03749999999999987 0.1500000000000000 9729 + 0.03749999999999987 0.1625000000000000 9730 + 0.03749999999999987 0.1750000000000000 9731 + 0.03749999999999987 0.1875000000000000 9732 + 0.03749999999999987 0.2000000000000000 9733 + 0.03749999999999987 0.2125000000000000 9734 + 0.03749999999999987 0.2250000000000001 9735 + 0.03749999999999981 0.2375000000000000 9736 + 0.03749999999999981 0.2500000000000000 9737 + 0.03749999999999981 0.2625000000000000 9738 + 0.03749999999999981 0.2750000000000000 9739 + 0.03749999999999981 0.2875000000000000 9740 + 0.03749999999999981 0.3000000000000000 9741 + 0.03749999999999976 0.3125000000000000 9742 + 0.03749999999999976 0.3250000000000000 9743 + 0.03749999999999976 0.3375000000000000 9744 + 0.03749999999999976 0.3500000000000000 9745 + 0.03749999999999976 0.3625000000000000 9746 + 0.03749999999999976 0.3750000000000000 9747 + 0.03749999999999976 0.3875000000000000 9748 + 0.03749999999999970 0.4000000000000000 9749 + 0.03749999999999970 0.4125000000000000 9750 + 0.03749999999999970 0.4250000000000000 9751 + 0.03749999999999970 0.4375000000000000 9752 + 0.03749999999999970 0.4500000000000000 9753 + 0.03749999999999964 0.4625000000000000 9754 + 0.03749999999999964 0.4750000000000000 9755 + 0.03749999999999964 0.4875000000000000 9756 + 0.03749999999999964 0.5000000000000000 9757 + 0.02500000000000000 0.000000000000000 9758 + 0.02500000000000002 0.01250000000000000 9759 + 0.02500000000000002 0.02500000000000000 9760 + 0.02500000000000002 0.03750000000000001 9761 + 0.02500000000000002 0.05000000000000000 9762 + 0.02500000000000002 0.06250000000000000 9763 + 0.02500000000000002 0.07500000000000001 9764 + 0.02500000000000002 0.08750000000000001 9765 + 0.02500000000000002 0.1000000000000000 9766 + 0.02500000000000002 0.1125000000000000 9767 + 0.02500000000000002 0.1250000000000000 9768 + 0.02500000000000002 0.1375000000000000 9769 + 0.02500000000000002 0.1500000000000000 9770 + 0.02500000000000002 0.1625000000000000 9771 + 0.02500000000000002 0.1750000000000000 9772 + 0.02500000000000002 0.1875000000000000 9773 + 0.02500000000000002 0.2000000000000000 9774 + 0.02500000000000002 0.2125000000000000 9775 + 0.02500000000000002 0.2250000000000000 9776 + 0.02500000000000002 0.2375000000000000 9777 + 0.02500000000000002 0.2500000000000000 9778 + 0.02500000000000002 0.2625000000000000 9779 + 0.02500000000000002 0.2750000000000000 9780 + 0.02500000000000002 0.2875000000000000 9781 + 0.02500000000000002 0.3000000000000000 9782 + 0.02500000000000002 0.3125000000000000 9783 + 0.02500000000000002 0.3250000000000000 9784 + 0.02500000000000002 0.3375000000000000 9785 + 0.02500000000000008 0.3500000000000000 9786 + 0.02500000000000008 0.3625000000000000 9787 + 0.02500000000000008 0.3750000000000000 9788 + 0.02500000000000008 0.3875000000000000 9789 + 0.02500000000000008 0.4000000000000000 9790 + 0.02500000000000008 0.4125000000000000 9791 + 0.02500000000000008 0.4250000000000000 9792 + 0.02500000000000008 0.4375000000000000 9793 + 0.02500000000000008 0.4500000000000000 9794 + 0.02500000000000008 0.4625000000000000 9795 + 0.02500000000000008 0.4750000000000000 9796 + 0.02500000000000008 0.4875000000000000 9797 + 0.02500000000000008 0.5000000000000000 9798 + 0.01250000000000000 0.000000000000000 9799 + 0.01250000000000001 0.01250000000000000 9800 + 0.01250000000000001 0.02500000000000000 9801 + 0.01249999999999996 0.03750000000000001 9802 + 0.01249999999999996 0.05000000000000000 9803 + 0.01249999999999996 0.06250000000000000 9804 + 0.01249999999999996 0.07500000000000001 9805 + 0.01249999999999996 0.08750000000000001 9806 + 0.01249999999999996 0.1000000000000000 9807 + 0.01249999999999996 0.1125000000000000 9808 + 0.01249999999999996 0.1250000000000000 9809 + 0.01249999999999990 0.1375000000000000 9810 + 0.01249999999999990 0.1500000000000000 9811 + 0.01249999999999990 0.1625000000000000 9812 + 0.01249999999999990 0.1750000000000000 9813 + 0.01249999999999990 0.1875000000000000 9814 + 0.01249999999999990 0.2000000000000000 9815 + 0.01249999999999990 0.2125000000000000 9816 + 0.01249999999999990 0.2250000000000000 9817 + 0.01249999999999984 0.2375000000000000 9818 + 0.01249999999999984 0.2500000000000000 9819 + 0.01249999999999984 0.2625000000000000 9820 + 0.01249999999999984 0.2750000000000000 9821 + 0.01249999999999984 0.2875000000000000 9822 + 0.01249999999999984 0.3000000000000000 9823 + 0.01249999999999984 0.3125000000000000 9824 + 0.01249999999999984 0.3250000000000000 9825 + 0.01249999999999984 0.3375000000000000 9826 + 0.01249999999999979 0.3500000000000000 9827 + 0.01249999999999979 0.3625000000000000 9828 + 0.01249999999999979 0.3750000000000000 9829 + 0.01249999999999979 0.3875000000000000 9830 + 0.01249999999999979 0.4000000000000000 9831 + 0.01249999999999979 0.4125000000000000 9832 + 0.01249999999999979 0.4250000000000000 9833 + 0.01249999999999979 0.4375000000000000 9834 + 0.01249999999999973 0.4499999999999999 9835 + 0.01249999999999973 0.4625000000000000 9836 + 0.01249999999999973 0.4749999999999999 9837 + 0.01249999999999973 0.4875000000000000 9838 + 0.01249999999999973 0.5000000000000000 9839 + 0.000000000000000 0.000000000000000 9840 + 0.000000000000000 0.01250000000000000 9841 + 0.000000000000000 0.02500000000000000 9842 + 0.000000000000000 0.03750000000000001 9843 + 0.000000000000000 0.05000000000000000 9844 + 0.000000000000000 0.06250000000000000 9845 + 0.000000000000000 0.07500000000000001 9846 + 5.551115123125783e-17 0.08750000000000001 9847 + 5.551115123125783e-17 0.1000000000000000 9848 + 5.551115123125783e-17 0.1125000000000000 9849 + 5.551115123125783e-17 0.1250000000000000 9850 + 5.551115123125783e-17 0.1375000000000000 9851 + 5.551115123125783e-17 0.1500000000000000 9852 + 5.551115123125783e-17 0.1625000000000000 9853 + 5.551115123125783e-17 0.1750000000000000 9854 + 5.551115123125783e-17 0.1875000000000000 9855 + 5.551115123125783e-17 0.2000000000000000 9856 + 5.551115123125783e-17 0.2125000000000000 9857 + 5.551115123125783e-17 0.2250000000000000 9858 + 5.551115123125783e-17 0.2375000000000000 9859 + 1.110223024625157e-16 0.2500000000000000 9860 + 1.110223024625157e-16 0.2625000000000000 9861 + 1.110223024625157e-16 0.2750000000000000 9862 + 1.110223024625157e-16 0.2875000000000000 9863 + 1.110223024625157e-16 0.3000000000000000 9864 + 1.110223024625157e-16 0.3125000000000000 9865 + 1.110223024625157e-16 0.3250000000000000 9866 + 1.110223024625157e-16 0.3375000000000000 9867 + 1.110223024625157e-16 0.3500000000000000 9868 + 1.110223024625157e-16 0.3625000000000000 9869 + 1.110223024625157e-16 0.3750000000000000 9870 + 1.110223024625157e-16 0.3875000000000000 9871 + 1.110223024625157e-16 0.4000000000000000 9872 + 1.110223024625157e-16 0.4125000000000000 9873 + 1.665334536937735e-16 0.4250000000000000 9874 + 1.665334536937735e-16 0.4375000000000000 9875 + 1.665334536937735e-16 0.4500000000000000 9876 + 1.665334536937735e-16 0.4625000000000000 9877 + 1.665334536937735e-16 0.4750000000000000 9878 + 1.665334536937735e-16 0.4875000000000000 9879 + 1.665334536937735e-16 0.5000000000000000 9880 + -0.01249999999999996 0.000000000000000 9881 + -0.01249999999999996 0.01250000000000000 9882 + -0.01249999999999996 0.02500000000000000 9883 + -0.01249999999999996 0.03750000000000001 9884 + -0.01249999999999996 0.05000000000000000 9885 + -0.01249999999999996 0.06250000000000000 9886 + -0.01250000000000001 0.07500000000000001 9887 + -0.01250000000000001 0.08749999999999999 9888 + -0.01250000000000001 0.1000000000000000 9889 + -0.01250000000000001 0.1125000000000000 9890 + -0.01250000000000001 0.1250000000000000 9891 + -0.01250000000000001 0.1375000000000000 9892 + -0.01250000000000001 0.1500000000000000 9893 + -0.01250000000000001 0.1625000000000000 9894 + -0.01250000000000001 0.1750000000000000 9895 + -0.01250000000000007 0.1875000000000000 9896 + -0.01250000000000007 0.2000000000000000 9897 + -0.01250000000000007 0.2125000000000000 9898 + -0.01250000000000007 0.2250000000000000 9899 + -0.01250000000000007 0.2375000000000000 9900 + -0.01250000000000007 0.2500000000000000 9901 + -0.01250000000000007 0.2625000000000000 9902 + -0.01250000000000007 0.2750000000000000 9903 + -0.01250000000000007 0.2875000000000000 9904 + -0.01250000000000007 0.3000000000000000 9905 + -0.01250000000000007 0.3125000000000000 9906 + -0.01250000000000012 0.3250000000000000 9907 + -0.01250000000000012 0.3375000000000000 9908 + -0.01250000000000012 0.3500000000000000 9909 + -0.01250000000000012 0.3625000000000000 9910 + -0.01250000000000012 0.3750000000000000 9911 + -0.01250000000000012 0.3875000000000000 9912 + -0.01250000000000012 0.4000000000000000 9913 + -0.01250000000000012 0.4125000000000000 9914 + -0.01250000000000012 0.4250000000000000 9915 + -0.01250000000000018 0.4375000000000000 9916 + -0.01250000000000018 0.4500000000000001 9917 + -0.01250000000000018 0.4625000000000000 9918 + -0.01250000000000018 0.4750000000000000 9919 + -0.01250000000000018 0.4875000000000000 9920 + -0.01250000000000018 0.5000000000000000 9921 + -0.02499999999999997 0.000000000000000 9922 + -0.02499999999999997 0.01250000000000000 9923 + -0.02499999999999997 0.02500000000000000 9924 + -0.02500000000000002 0.03750000000000001 9925 + -0.02500000000000002 0.05000000000000000 9926 + -0.02500000000000002 0.06250000000000000 9927 + -0.02500000000000002 0.07500000000000001 9928 + -0.02500000000000008 0.08750000000000001 9929 + -0.02500000000000008 0.1000000000000000 9930 + -0.02500000000000008 0.1125000000000000 9931 + -0.02500000000000013 0.1250000000000000 9932 + -0.02500000000000013 0.1375000000000000 9933 + -0.02500000000000013 0.1500000000000000 9934 + -0.02500000000000013 0.1625000000000000 9935 + -0.02500000000000013 0.1750000000000000 9936 + -0.02500000000000019 0.1875000000000000 9937 + -0.02500000000000019 0.2000000000000000 9938 + -0.02500000000000019 0.2125000000000000 9939 + -0.02500000000000024 0.2250000000000001 9940 + -0.02500000000000024 0.2375000000000000 9941 + -0.02500000000000024 0.2500000000000000 9942 + -0.02500000000000024 0.2625000000000000 9943 + -0.02500000000000024 0.2750000000000000 9944 + -0.02500000000000030 0.2875000000000000 9945 + -0.02500000000000030 0.3000000000000000 9946 + -0.02500000000000030 0.3125000000000000 9947 + -0.02500000000000036 0.3250000000000000 9948 + -0.02500000000000036 0.3375000000000000 9949 + -0.02500000000000036 0.3500000000000000 9950 + -0.02500000000000036 0.3625000000000000 9951 + -0.02500000000000036 0.3750000000000000 9952 + -0.02500000000000041 0.3875000000000000 9953 + -0.02500000000000041 0.4000000000000000 9954 + -0.02500000000000041 0.4125000000000000 9955 + -0.02500000000000047 0.4250000000000000 9956 + -0.02500000000000047 0.4375000000000000 9957 + -0.02500000000000047 0.4500000000000001 9958 + -0.02500000000000047 0.4625000000000000 9959 + -0.02500000000000047 0.4750000000000000 9960 + -0.02500000000000052 0.4875000000000000 9961 + -0.02500000000000052 0.5000000000000000 9962 + -0.03749999999999998 0.000000000000000 9963 + -0.03749999999999998 0.01250000000000000 9964 + -0.03749999999999998 0.02500000000000000 9965 + -0.03749999999999998 0.03750000000000001 9966 + -0.03749999999999998 0.05000000000000000 9967 + -0.03749999999999998 0.06250000000000000 9968 + -0.03749999999999998 0.07500000000000001 9969 + -0.03749999999999998 0.08750000000000001 9970 + -0.03750000000000003 0.1000000000000000 9971 + -0.03749999999999998 0.1125000000000000 9972 + -0.03749999999999998 0.1250000000000000 9973 + -0.03749999999999998 0.1375000000000000 9974 + -0.03750000000000003 0.1500000000000000 9975 + -0.03750000000000003 0.1625000000000000 9976 + -0.03750000000000003 0.1750000000000000 9977 + -0.03750000000000003 0.1875000000000000 9978 + -0.03750000000000003 0.2000000000000000 9979 + -0.03750000000000003 0.2125000000000000 9980 + -0.03750000000000003 0.2250000000000001 9981 + -0.03750000000000003 0.2375000000000000 9982 + -0.03750000000000003 0.2500000000000000 9983 + -0.03750000000000003 0.2625000000000000 9984 + -0.03750000000000003 0.2750000000000000 9985 + -0.03750000000000003 0.2875000000000000 9986 + -0.03750000000000003 0.3000000000000000 9987 + -0.03750000000000003 0.3125000000000000 9988 + -0.03750000000000003 0.3250000000000000 9989 + -0.03750000000000003 0.3375000000000000 9990 + -0.03750000000000003 0.3500000000000000 9991 + -0.03750000000000009 0.3625000000000000 9992 + -0.03750000000000009 0.3750000000000000 9993 + -0.03750000000000009 0.3875000000000000 9994 + -0.03750000000000009 0.4000000000000000 9995 + -0.03750000000000009 0.4125000000000000 9996 + -0.03750000000000009 0.4250000000000000 9997 + -0.03750000000000009 0.4375000000000000 9998 + -0.03750000000000009 0.4500000000000000 9999 + -0.03750000000000009 0.4625000000000000 10000 + -0.03750000000000009 0.4750000000000001 10001 + -0.03750000000000009 0.4875000000000000 10002 + -0.03750000000000009 0.5000000000000000 10003 + -0.04999999999999999 0.000000000000000 10004 + -0.04999999999999999 0.01250000000000000 10005 + -0.04999999999999999 0.02500000000000000 10006 + -0.05000000000000004 0.03750000000000001 10007 + -0.05000000000000004 0.05000000000000000 10008 + -0.05000000000000004 0.06250000000000000 10009 + -0.05000000000000004 0.07500000000000001 10010 + -0.05000000000000004 0.08750000000000001 10011 + -0.05000000000000010 0.1000000000000000 10012 + -0.05000000000000010 0.1125000000000000 10013 + -0.05000000000000010 0.1250000000000000 10014 + -0.05000000000000010 0.1375000000000000 10015 + -0.05000000000000010 0.1500000000000000 10016 + -0.05000000000000016 0.1625000000000000 10017 + -0.05000000000000016 0.1750000000000000 10018 + -0.05000000000000016 0.1875000000000000 10019 + -0.05000000000000016 0.2000000000000000 10020 + -0.05000000000000016 0.2125000000000000 10021 + -0.05000000000000021 0.2250000000000000 10022 + -0.05000000000000021 0.2375000000000000 10023 + -0.05000000000000021 0.2500000000000000 10024 + -0.05000000000000021 0.2625000000000000 10025 + -0.05000000000000021 0.2750000000000000 10026 + -0.05000000000000027 0.2875000000000000 10027 + -0.05000000000000027 0.3000000000000000 10028 + -0.05000000000000027 0.3125000000000000 10029 + -0.05000000000000027 0.3250000000000000 10030 + -0.05000000000000027 0.3375000000000000 10031 + -0.05000000000000032 0.3500000000000000 10032 + -0.05000000000000032 0.3625000000000000 10033 + -0.05000000000000032 0.3750000000000000 10034 + -0.05000000000000032 0.3875000000000000 10035 + -0.05000000000000032 0.4000000000000000 10036 + -0.05000000000000038 0.4125000000000000 10037 + -0.05000000000000038 0.4250000000000000 10038 + -0.05000000000000038 0.4375000000000000 10039 + -0.05000000000000038 0.4499999999999999 10040 + -0.05000000000000038 0.4625000000000000 10041 + -0.05000000000000043 0.4750000000000001 10042 + -0.05000000000000043 0.4875000000000000 10043 + -0.05000000000000043 0.5000000000000000 10044 + -0.06250000000000000 0.000000000000000 10045 + -0.06250000000000000 0.01250000000000000 10046 + -0.06250000000000000 0.02500000000000000 10047 + -0.06250000000000000 0.03750000000000001 10048 + -0.06250000000000000 0.05000000000000000 10049 + -0.06250000000000000 0.06250000000000000 10050 + -0.06250000000000000 0.07500000000000001 10051 + -0.06250000000000000 0.08750000000000002 10052 + -0.06250000000000000 0.1000000000000000 10053 + -0.06250000000000000 0.1125000000000000 10054 + -0.06250000000000000 0.1250000000000000 10055 + -0.06250000000000000 0.1375000000000000 10056 + -0.06250000000000000 0.1500000000000000 10057 + -0.06250000000000000 0.1625000000000000 10058 + -0.06250000000000000 0.1750000000000000 10059 + -0.06250000000000000 0.1875000000000000 10060 + -0.06250000000000000 0.2000000000000000 10061 + -0.06250000000000000 0.2125000000000000 10062 + -0.06250000000000000 0.2250000000000000 10063 + -0.06250000000000000 0.2375000000000000 10064 + -0.06250000000000000 0.2500000000000000 10065 + -0.06250000000000000 0.2625000000000000 10066 + -0.06250000000000000 0.2750000000000000 10067 + -0.06250000000000000 0.2875000000000000 10068 + -0.06250000000000000 0.3000000000000000 10069 + -0.06250000000000000 0.3125000000000000 10070 + -0.06250000000000000 0.3250000000000000 10071 + -0.06250000000000000 0.3375000000000000 10072 + -0.06250000000000000 0.3500000000000000 10073 + -0.06250000000000000 0.3625000000000000 10074 + -0.06250000000000000 0.3750000000000000 10075 + -0.06250000000000000 0.3875000000000000 10076 + -0.06250000000000000 0.4000000000000000 10077 + -0.06250000000000000 0.4125000000000000 10078 + -0.06250000000000000 0.4250000000000000 10079 + -0.06250000000000000 0.4375000000000000 10080 + -0.06250000000000000 0.4500000000000001 10081 + -0.06250000000000000 0.4625000000000000 10082 + -0.06250000000000000 0.4749999999999999 10083 + -0.06250000000000000 0.4875000000000000 10084 + -0.06250000000000000 0.5000000000000000 10085 + -0.07499999999999996 0.000000000000000 10086 + -0.07499999999999996 0.01250000000000000 10087 + -0.07499999999999996 0.02500000000000000 10088 + -0.07500000000000001 0.03750000000000001 10089 + -0.07500000000000001 0.05000000000000000 10090 + -0.07500000000000001 0.06250000000000000 10091 + -0.07500000000000001 0.07500000000000001 10092 + -0.07500000000000001 0.08750000000000001 10093 + -0.07500000000000001 0.1000000000000000 10094 + -0.07500000000000007 0.1125000000000000 10095 + -0.07500000000000007 0.1250000000000000 10096 + -0.07500000000000007 0.1375000000000000 10097 + -0.07500000000000007 0.1500000000000000 10098 + -0.07500000000000012 0.1625000000000000 10099 + -0.07500000000000007 0.1750000000000000 10100 + -0.07500000000000007 0.1875000000000000 10101 + -0.07500000000000012 0.2000000000000000 10102 + -0.07500000000000012 0.2125000000000000 10103 + -0.07500000000000012 0.2250000000000000 10104 + -0.07500000000000012 0.2375000000000001 10105 + -0.07500000000000018 0.2500000000000000 10106 + -0.07500000000000018 0.2625000000000000 10107 + -0.07500000000000018 0.2750000000000000 10108 + -0.07500000000000018 0.2875000000000000 10109 + -0.07500000000000018 0.3000000000000000 10110 + -0.07500000000000018 0.3125000000000000 10111 + -0.07500000000000018 0.3250000000000000 10112 + -0.07500000000000023 0.3375000000000000 10113 + -0.07500000000000023 0.3500000000000000 10114 + -0.07500000000000023 0.3625000000000000 10115 + -0.07500000000000023 0.3750000000000000 10116 + -0.07500000000000029 0.3875000000000000 10117 + -0.07500000000000029 0.4000000000000000 10118 + -0.07500000000000029 0.4125000000000000 10119 + -0.07500000000000029 0.4250000000000000 10120 + -0.07500000000000029 0.4375000000000000 10121 + -0.07500000000000029 0.4500000000000000 10122 + -0.07500000000000029 0.4625000000000000 10123 + -0.07500000000000029 0.4750000000000001 10124 + -0.07500000000000034 0.4875000000000000 10125 + -0.07500000000000034 0.5000000000000000 10126 + -0.08749999999999997 0.000000000000000 10127 + -0.08749999999999997 0.01250000000000000 10128 + -0.08749999999999997 0.02500000000000000 10129 + -0.08749999999999997 0.03750000000000001 10130 + -0.08750000000000002 0.05000000000000000 10131 + -0.08750000000000002 0.06250000000000000 10132 + -0.08750000000000002 0.07500000000000001 10133 + -0.08750000000000002 0.08750000000000001 10134 + -0.08750000000000002 0.1000000000000000 10135 + -0.08750000000000002 0.1125000000000000 10136 + -0.08750000000000002 0.1250000000000000 10137 + -0.08750000000000008 0.1375000000000000 10138 + -0.08750000000000008 0.1500000000000000 10139 + -0.08750000000000008 0.1625000000000000 10140 + -0.08750000000000008 0.1750000000000000 10141 + -0.08750000000000008 0.1875000000000000 10142 + -0.08750000000000013 0.2000000000000000 10143 + -0.08750000000000013 0.2125000000000000 10144 + -0.08750000000000013 0.2250000000000000 10145 + -0.08750000000000013 0.2375000000000000 10146 + -0.08750000000000013 0.2500000000000000 10147 + -0.08750000000000013 0.2625000000000000 10148 + -0.08750000000000013 0.2750000000000000 10149 + -0.08750000000000013 0.2875000000000001 10150 + -0.08750000000000013 0.3000000000000000 10151 + -0.08750000000000019 0.3125000000000000 10152 + -0.08750000000000019 0.3250000000000000 10153 + -0.08750000000000019 0.3375000000000000 10154 + -0.08750000000000019 0.3500000000000000 10155 + -0.08750000000000024 0.3625000000000000 10156 + -0.08750000000000024 0.3750000000000000 10157 + -0.08750000000000024 0.3875000000000000 10158 + -0.08750000000000024 0.4000000000000000 10159 + -0.08750000000000024 0.4125000000000000 10160 + -0.08750000000000024 0.4250000000000000 10161 + -0.08750000000000024 0.4375000000000000 10162 + -0.08750000000000024 0.4499999999999999 10163 + -0.08750000000000030 0.4625000000000000 10164 + -0.08750000000000030 0.4749999999999999 10165 + -0.08750000000000030 0.4875000000000000 10166 + -0.08750000000000030 0.5000000000000000 10167 + -0.09999999999999998 0.000000000000000 10168 + -0.09999999999999998 0.01250000000000000 10169 + -0.09999999999999998 0.02500000000000000 10170 + -0.1000000000000000 0.03750000000000001 10171 + -0.1000000000000000 0.05000000000000000 10172 + -0.1000000000000000 0.06250000000000000 10173 + -0.1000000000000000 0.07500000000000001 10174 + -0.1000000000000000 0.08750000000000001 10175 + -0.1000000000000000 0.1000000000000000 10176 + -0.1000000000000000 0.1125000000000000 10177 + -0.1000000000000000 0.1250000000000000 10178 + -0.1000000000000001 0.1375000000000000 10179 + -0.1000000000000001 0.1500000000000000 10180 + -0.1000000000000001 0.1625000000000000 10181 + -0.1000000000000001 0.1750000000000000 10182 + -0.1000000000000001 0.1875000000000000 10183 + -0.1000000000000001 0.2000000000000000 10184 + -0.1000000000000001 0.2125000000000000 10185 + -0.1000000000000001 0.2250000000000000 10186 + -0.1000000000000001 0.2375000000000001 10187 + -0.1000000000000001 0.2500000000000000 10188 + -0.1000000000000001 0.2625000000000000 10189 + -0.1000000000000001 0.2750000000000000 10190 + -0.1000000000000001 0.2875000000000000 10191 + -0.1000000000000001 0.3000000000000000 10192 + -0.1000000000000001 0.3125000000000000 10193 + -0.1000000000000001 0.3250000000000000 10194 + -0.1000000000000001 0.3375000000000000 10195 + -0.1000000000000002 0.3500000000000000 10196 + -0.1000000000000002 0.3625000000000000 10197 + -0.1000000000000002 0.3750000000000000 10198 + -0.1000000000000002 0.3875000000000000 10199 + -0.1000000000000002 0.4000000000000000 10200 + -0.1000000000000002 0.4125000000000000 10201 + -0.1000000000000002 0.4250000000000000 10202 + -0.1000000000000002 0.4375000000000000 10203 + -0.1000000000000002 0.4500000000000000 10204 + -0.1000000000000002 0.4625000000000000 10205 + -0.1000000000000003 0.4750000000000001 10206 + -0.1000000000000003 0.4875000000000000 10207 + -0.1000000000000003 0.5000000000000000 10208 + -0.1125000000000000 0.000000000000000 10209 + -0.1125000000000000 0.01250000000000000 10210 + -0.1125000000000000 0.02500000000000000 10211 + -0.1125000000000000 0.03750000000000001 10212 + -0.1125000000000000 0.05000000000000000 10213 + -0.1125000000000000 0.06250000000000000 10214 + -0.1125000000000000 0.07500000000000001 10215 + -0.1125000000000000 0.08750000000000001 10216 + -0.1125000000000000 0.1000000000000000 10217 + -0.1125000000000000 0.1125000000000000 10218 + -0.1125000000000000 0.1250000000000000 10219 + -0.1125000000000000 0.1375000000000000 10220 + -0.1125000000000000 0.1500000000000000 10221 + -0.1125000000000000 0.1625000000000000 10222 + -0.1125000000000000 0.1750000000000000 10223 + -0.1125000000000001 0.1875000000000000 10224 + -0.1125000000000001 0.2000000000000000 10225 + -0.1125000000000001 0.2125000000000000 10226 + -0.1125000000000001 0.2250000000000000 10227 + -0.1125000000000001 0.2375000000000000 10228 + -0.1125000000000001 0.2500000000000000 10229 + -0.1125000000000001 0.2625000000000000 10230 + -0.1125000000000001 0.2750000000000000 10231 + -0.1125000000000001 0.2875000000000000 10232 + -0.1125000000000001 0.3000000000000000 10233 + -0.1125000000000001 0.3125000000000000 10234 + -0.1125000000000001 0.3250000000000000 10235 + -0.1125000000000001 0.3375000000000000 10236 + -0.1125000000000002 0.3500000000000000 10237 + -0.1125000000000002 0.3625000000000000 10238 + -0.1125000000000002 0.3750000000000000 10239 + -0.1125000000000002 0.3875000000000000 10240 + -0.1125000000000002 0.4000000000000000 10241 + -0.1125000000000002 0.4125000000000000 10242 + -0.1125000000000002 0.4250000000000000 10243 + -0.1125000000000002 0.4375000000000000 10244 + -0.1125000000000002 0.4500000000000000 10245 + -0.1125000000000002 0.4625000000000000 10246 + -0.1125000000000002 0.4750000000000001 10247 + -0.1125000000000002 0.4875000000000000 10248 + -0.1125000000000002 0.5000000000000000 10249 + -0.1250000000000000 0.000000000000000 10250 + -0.1250000000000000 0.01250000000000000 10251 + -0.1250000000000000 0.02500000000000000 10252 + -0.1250000000000000 0.03750000000000001 10253 + -0.1250000000000000 0.05000000000000000 10254 + -0.1250000000000000 0.06250000000000000 10255 + -0.1250000000000000 0.07500000000000001 10256 + -0.1250000000000000 0.08750000000000001 10257 + -0.1250000000000001 0.1000000000000000 10258 + -0.1250000000000001 0.1125000000000000 10259 + -0.1250000000000001 0.1250000000000000 10260 + -0.1250000000000001 0.1375000000000000 10261 + -0.1250000000000001 0.1500000000000000 10262 + -0.1250000000000001 0.1625000000000000 10263 + -0.1250000000000001 0.1750000000000000 10264 + -0.1250000000000001 0.1875000000000000 10265 + -0.1250000000000001 0.2000000000000000 10266 + -0.1250000000000001 0.2125000000000000 10267 + -0.1250000000000001 0.2250000000000000 10268 + -0.1250000000000001 0.2375000000000000 10269 + -0.1250000000000001 0.2500000000000000 10270 + -0.1250000000000001 0.2625000000000000 10271 + -0.1250000000000001 0.2750000000000000 10272 + -0.1250000000000001 0.2875000000000000 10273 + -0.1250000000000001 0.3000000000000000 10274 + -0.1250000000000001 0.3125000000000000 10275 + -0.1250000000000001 0.3250000000000000 10276 + -0.1250000000000001 0.3375000000000000 10277 + -0.1250000000000001 0.3500000000000000 10278 + -0.1250000000000001 0.3625000000000000 10279 + -0.1250000000000001 0.3750000000000000 10280 + -0.1250000000000001 0.3875000000000000 10281 + -0.1250000000000001 0.4000000000000000 10282 + -0.1250000000000001 0.4125000000000000 10283 + -0.1250000000000001 0.4250000000000000 10284 + -0.1250000000000001 0.4375000000000000 10285 + -0.1250000000000002 0.4500000000000000 10286 + -0.1250000000000002 0.4625000000000000 10287 + -0.1250000000000002 0.4750000000000000 10288 + -0.1250000000000002 0.4875000000000000 10289 + -0.1250000000000002 0.5000000000000000 10290 + -0.1375000000000000 0.000000000000000 10291 + -0.1375000000000000 0.01250000000000000 10292 + -0.1375000000000000 0.02500000000000000 10293 + -0.1375000000000000 0.03750000000000001 10294 + -0.1375000000000000 0.05000000000000000 10295 + -0.1375000000000000 0.06250000000000000 10296 + -0.1375000000000000 0.07500000000000001 10297 + -0.1375000000000000 0.08750000000000001 10298 + -0.1375000000000000 0.1000000000000000 10299 + -0.1375000000000000 0.1125000000000000 10300 + -0.1375000000000000 0.1250000000000000 10301 + -0.1375000000000000 0.1375000000000000 10302 + -0.1375000000000000 0.1500000000000000 10303 + -0.1375000000000000 0.1625000000000000 10304 + -0.1375000000000000 0.1750000000000000 10305 + -0.1375000000000000 0.1875000000000000 10306 + -0.1375000000000000 0.2000000000000000 10307 + -0.1375000000000000 0.2125000000000000 10308 + -0.1375000000000000 0.2250000000000000 10309 + -0.1375000000000000 0.2375000000000000 10310 + -0.1375000000000001 0.2500000000000000 10311 + -0.1375000000000001 0.2625000000000000 10312 + -0.1375000000000001 0.2750000000000000 10313 + -0.1375000000000001 0.2875000000000000 10314 + -0.1375000000000001 0.3000000000000000 10315 + -0.1375000000000001 0.3125000000000000 10316 + -0.1375000000000001 0.3250000000000000 10317 + -0.1375000000000001 0.3375000000000000 10318 + -0.1375000000000001 0.3500000000000001 10319 + -0.1375000000000001 0.3625000000000000 10320 + -0.1375000000000001 0.3750000000000000 10321 + -0.1375000000000001 0.3875000000000000 10322 + -0.1375000000000001 0.4000000000000000 10323 + -0.1375000000000001 0.4125000000000000 10324 + -0.1375000000000001 0.4250000000000000 10325 + -0.1375000000000001 0.4375000000000000 10326 + -0.1375000000000001 0.4500000000000000 10327 + -0.1375000000000001 0.4625000000000000 10328 + -0.1375000000000001 0.4750000000000001 10329 + -0.1375000000000001 0.4875000000000000 10330 + -0.1375000000000001 0.5000000000000000 10331 + -0.1500000000000000 0.000000000000000 10332 + -0.1500000000000000 0.01250000000000000 10333 + -0.1500000000000000 0.02500000000000000 10334 + -0.1500000000000000 0.03750000000000001 10335 + -0.1500000000000000 0.05000000000000000 10336 + -0.1500000000000000 0.06250000000000000 10337 + -0.1500000000000001 0.07500000000000001 10338 + -0.1500000000000000 0.08749999999999999 10339 + -0.1500000000000001 0.1000000000000000 10340 + -0.1500000000000001 0.1125000000000000 10341 + -0.1500000000000001 0.1250000000000000 10342 + -0.1500000000000001 0.1375000000000000 10343 + -0.1500000000000001 0.1500000000000000 10344 + -0.1500000000000001 0.1625000000000000 10345 + -0.1500000000000001 0.1750000000000000 10346 + -0.1500000000000001 0.1875000000000000 10347 + -0.1500000000000002 0.2000000000000000 10348 + -0.1500000000000002 0.2125000000000000 10349 + -0.1500000000000002 0.2250000000000000 10350 + -0.1500000000000002 0.2375000000000000 10351 + -0.1500000000000002 0.2500000000000000 10352 + -0.1500000000000002 0.2625000000000000 10353 + -0.1500000000000002 0.2750000000000000 10354 + -0.1500000000000002 0.2875000000000000 10355 + -0.1500000000000002 0.3000000000000000 10356 + -0.1500000000000003 0.3125000000000000 10357 + -0.1500000000000003 0.3250000000000000 10358 + -0.1500000000000003 0.3375000000000000 10359 + -0.1500000000000004 0.3500000000000000 10360 + -0.1500000000000004 0.3625000000000000 10361 + -0.1500000000000004 0.3750000000000000 10362 + -0.1500000000000004 0.3875000000000000 10363 + -0.1500000000000004 0.4000000000000000 10364 + -0.1500000000000004 0.4125000000000000 10365 + -0.1500000000000004 0.4250000000000000 10366 + -0.1500000000000004 0.4375000000000000 10367 + -0.1500000000000004 0.4500000000000000 10368 + -0.1500000000000004 0.4625000000000000 10369 + -0.1500000000000004 0.4750000000000001 10370 + -0.1500000000000004 0.4875000000000000 10371 + -0.1500000000000005 0.5000000000000000 10372 + -0.1625000000000000 0.000000000000000 10373 + -0.1625000000000000 0.01250000000000000 10374 + -0.1625000000000000 0.02500000000000000 10375 + -0.1625000000000000 0.03750000000000001 10376 + -0.1625000000000000 0.05000000000000000 10377 + -0.1625000000000000 0.06250000000000000 10378 + -0.1625000000000000 0.07500000000000001 10379 + -0.1625000000000000 0.08750000000000001 10380 + -0.1625000000000000 0.1000000000000000 10381 + -0.1625000000000000 0.1125000000000000 10382 + -0.1625000000000000 0.1250000000000000 10383 + -0.1625000000000000 0.1375000000000000 10384 + -0.1625000000000000 0.1500000000000000 10385 + -0.1625000000000000 0.1625000000000000 10386 + -0.1625000000000000 0.1750000000000000 10387 + -0.1625000000000000 0.1875000000000000 10388 + -0.1625000000000000 0.2000000000000000 10389 + -0.1625000000000000 0.2125000000000000 10390 + -0.1625000000000000 0.2250000000000000 10391 + -0.1625000000000000 0.2375000000000000 10392 + -0.1625000000000000 0.2500000000000000 10393 + -0.1625000000000000 0.2625000000000000 10394 + -0.1625000000000000 0.2750000000000000 10395 + -0.1625000000000000 0.2875000000000000 10396 + -0.1625000000000000 0.3000000000000000 10397 + -0.1625000000000000 0.3125000000000000 10398 + -0.1625000000000000 0.3250000000000000 10399 + -0.1625000000000000 0.3375000000000000 10400 + -0.1625000000000000 0.3500000000000000 10401 + -0.1625000000000000 0.3625000000000000 10402 + -0.1625000000000000 0.3750000000000000 10403 + -0.1625000000000000 0.3875000000000000 10404 + -0.1625000000000000 0.4000000000000000 10405 + -0.1625000000000000 0.4125000000000000 10406 + -0.1625000000000000 0.4250000000000000 10407 + -0.1625000000000000 0.4375000000000000 10408 + -0.1625000000000000 0.4500000000000000 10409 + -0.1625000000000000 0.4625000000000000 10410 + -0.1625000000000000 0.4750000000000000 10411 + -0.1625000000000000 0.4875000000000000 10412 + -0.1625000000000000 0.5000000000000000 10413 + -0.1750000000000000 0.000000000000000 10414 + -0.1750000000000000 0.01250000000000000 10415 + -0.1750000000000000 0.02500000000000000 10416 + -0.1750000000000000 0.03750000000000001 10417 + -0.1750000000000000 0.05000000000000000 10418 + -0.1750000000000000 0.06250000000000000 10419 + -0.1750000000000000 0.07500000000000001 10420 + -0.1750000000000000 0.08750000000000001 10421 + -0.1750000000000000 0.1000000000000000 10422 + -0.1750000000000001 0.1125000000000000 10423 + -0.1750000000000001 0.1250000000000000 10424 + -0.1750000000000001 0.1375000000000000 10425 + -0.1750000000000001 0.1500000000000000 10426 + -0.1750000000000002 0.1625000000000000 10427 + -0.1750000000000001 0.1750000000000000 10428 + -0.1750000000000002 0.1875000000000000 10429 + -0.1750000000000002 0.2000000000000000 10430 + -0.1750000000000002 0.2125000000000000 10431 + -0.1750000000000002 0.2250000000000000 10432 + -0.1750000000000002 0.2375000000000001 10433 + -0.1750000000000002 0.2500000000000000 10434 + -0.1750000000000002 0.2625000000000000 10435 + -0.1750000000000002 0.2750000000000000 10436 + -0.1750000000000002 0.2875000000000000 10437 + -0.1750000000000002 0.3000000000000000 10438 + -0.1750000000000002 0.3125000000000000 10439 + -0.1750000000000002 0.3250000000000000 10440 + -0.1750000000000002 0.3375000000000000 10441 + -0.1750000000000003 0.3500000000000000 10442 + -0.1750000000000003 0.3625000000000000 10443 + -0.1750000000000003 0.3750000000000000 10444 + -0.1750000000000003 0.3875000000000000 10445 + -0.1750000000000003 0.4000000000000000 10446 + -0.1750000000000003 0.4125000000000000 10447 + -0.1750000000000003 0.4250000000000000 10448 + -0.1750000000000004 0.4375000000000000 10449 + -0.1750000000000003 0.4500000000000000 10450 + -0.1750000000000004 0.4625000000000000 10451 + -0.1750000000000004 0.4750000000000001 10452 + -0.1750000000000004 0.4875000000000000 10453 + -0.1750000000000004 0.5000000000000000 10454 + -0.1875000000000000 0.000000000000000 10455 + -0.1875000000000000 0.01250000000000000 10456 + -0.1875000000000000 0.02500000000000000 10457 + -0.1875000000000000 0.03750000000000001 10458 + -0.1875000000000000 0.05000000000000000 10459 + -0.1875000000000000 0.06250000000000000 10460 + -0.1875000000000000 0.07500000000000001 10461 + -0.1874999999999999 0.08750000000000001 10462 + -0.1875000000000000 0.1000000000000000 10463 + -0.1875000000000000 0.1125000000000000 10464 + -0.1875000000000000 0.1250000000000000 10465 + -0.1875000000000000 0.1375000000000000 10466 + -0.1875000000000000 0.1500000000000000 10467 + -0.1875000000000000 0.1625000000000000 10468 + -0.1875000000000000 0.1750000000000000 10469 + -0.1875000000000000 0.1875000000000000 10470 + -0.1875000000000000 0.2000000000000000 10471 + -0.1875000000000000 0.2125000000000000 10472 + -0.1875000000000000 0.2250000000000000 10473 + -0.1874999999999999 0.2375000000000000 10474 + -0.1875000000000000 0.2500000000000000 10475 + -0.1874999999999999 0.2625000000000000 10476 + -0.1874999999999999 0.2750000000000000 10477 + -0.1874999999999999 0.2875000000000000 10478 + -0.1874999999999999 0.3000000000000000 10479 + -0.1874999999999999 0.3125000000000000 10480 + -0.1874999999999999 0.3250000000000000 10481 + -0.1874999999999999 0.3375000000000000 10482 + -0.1874999999999999 0.3500000000000000 10483 + -0.1874999999999999 0.3625000000000000 10484 + -0.1874999999999999 0.3750000000000000 10485 + -0.1874999999999999 0.3875000000000000 10486 + -0.1874999999999999 0.4000000000000000 10487 + -0.1874999999999999 0.4125000000000000 10488 + -0.1874999999999999 0.4250000000000000 10489 + -0.1874999999999999 0.4375000000000000 10490 + -0.1874999999999999 0.4500000000000000 10491 + -0.1874999999999999 0.4625000000000000 10492 + -0.1874999999999999 0.4750000000000000 10493 + -0.1874999999999999 0.4875000000000000 10494 + -0.1874999999999999 0.5000000000000000 10495 + -0.2000000000000000 0.000000000000000 10496 + -0.2000000000000000 0.01250000000000000 10497 + -0.2000000000000000 0.02500000000000000 10498 + -0.2000000000000000 0.03750000000000001 10499 + -0.2000000000000000 0.05000000000000000 10500 + -0.2000000000000000 0.06250000000000000 10501 + -0.2000000000000000 0.07500000000000001 10502 + -0.2000000000000000 0.08750000000000001 10503 + -0.2000000000000000 0.1000000000000000 10504 + -0.2000000000000001 0.1125000000000000 10505 + -0.2000000000000001 0.1250000000000000 10506 + -0.2000000000000001 0.1375000000000000 10507 + -0.2000000000000001 0.1500000000000000 10508 + -0.2000000000000001 0.1625000000000000 10509 + -0.2000000000000001 0.1750000000000000 10510 + -0.2000000000000001 0.1875000000000000 10511 + -0.2000000000000001 0.2000000000000000 10512 + -0.2000000000000001 0.2125000000000000 10513 + -0.2000000000000001 0.2250000000000000 10514 + -0.2000000000000001 0.2375000000000000 10515 + -0.2000000000000001 0.2500000000000000 10516 + -0.2000000000000001 0.2625000000000000 10517 + -0.2000000000000001 0.2750000000000000 10518 + -0.2000000000000001 0.2875000000000000 10519 + -0.2000000000000001 0.3000000000000000 10520 + -0.2000000000000001 0.3125000000000000 10521 + -0.2000000000000002 0.3250000000000000 10522 + -0.2000000000000002 0.3375000000000000 10523 + -0.2000000000000002 0.3500000000000000 10524 + -0.2000000000000002 0.3625000000000000 10525 + -0.2000000000000002 0.3750000000000000 10526 + -0.2000000000000002 0.3875000000000000 10527 + -0.2000000000000002 0.4000000000000000 10528 + -0.2000000000000002 0.4125000000000000 10529 + -0.2000000000000002 0.4250000000000000 10530 + -0.2000000000000003 0.4375000000000000 10531 + -0.2000000000000003 0.4500000000000000 10532 + -0.2000000000000003 0.4625000000000000 10533 + -0.2000000000000003 0.4750000000000000 10534 + -0.2000000000000003 0.4875000000000000 10535 + -0.2000000000000003 0.5000000000000000 10536 + -0.2125000000000000 0.000000000000000 10537 + -0.2125000000000000 0.01250000000000000 10538 + -0.2125000000000000 0.02500000000000000 10539 + -0.2125000000000000 0.03750000000000001 10540 + -0.2125000000000000 0.05000000000000000 10541 + -0.2125000000000000 0.06250000000000000 10542 + -0.2125000000000000 0.07500000000000001 10543 + -0.2125000000000000 0.08750000000000001 10544 + -0.2125000000000000 0.1000000000000000 10545 + -0.2125000000000000 0.1125000000000000 10546 + -0.2125000000000000 0.1250000000000000 10547 + -0.2125000000000000 0.1375000000000000 10548 + -0.2125000000000000 0.1500000000000000 10549 + -0.2125000000000000 0.1625000000000000 10550 + -0.2125000000000001 0.1750000000000000 10551 + -0.2125000000000001 0.1875000000000000 10552 + -0.2125000000000001 0.2000000000000000 10553 + -0.2125000000000001 0.2125000000000000 10554 + -0.2125000000000001 0.2250000000000000 10555 + -0.2125000000000001 0.2375000000000000 10556 + -0.2125000000000001 0.2500000000000000 10557 + -0.2125000000000001 0.2625000000000000 10558 + -0.2125000000000001 0.2750000000000000 10559 + -0.2125000000000001 0.2875000000000000 10560 + -0.2125000000000001 0.3000000000000000 10561 + -0.2125000000000001 0.3125000000000000 10562 + -0.2125000000000001 0.3250000000000000 10563 + -0.2125000000000001 0.3375000000000000 10564 + -0.2125000000000001 0.3500000000000000 10565 + -0.2125000000000001 0.3625000000000000 10566 + -0.2125000000000002 0.3750000000000000 10567 + -0.2125000000000001 0.3875000000000000 10568 + -0.2125000000000002 0.4000000000000000 10569 + -0.2125000000000002 0.4125000000000000 10570 + -0.2125000000000002 0.4250000000000000 10571 + -0.2125000000000002 0.4375000000000000 10572 + -0.2125000000000002 0.4500000000000000 10573 + -0.2125000000000002 0.4625000000000000 10574 + -0.2125000000000002 0.4750000000000000 10575 + -0.2125000000000002 0.4875000000000000 10576 + -0.2125000000000002 0.5000000000000000 10577 + -0.2250000000000000 0.000000000000000 10578 + -0.2250000000000000 0.01250000000000000 10579 + -0.2250000000000000 0.02500000000000000 10580 + -0.2250000000000000 0.03750000000000001 10581 + -0.2250000000000000 0.05000000000000000 10582 + -0.2250000000000000 0.06250000000000000 10583 + -0.2250000000000000 0.07500000000000001 10584 + -0.2250000000000000 0.08750000000000001 10585 + -0.2250000000000001 0.1000000000000000 10586 + -0.2250000000000000 0.1125000000000000 10587 + -0.2250000000000000 0.1250000000000000 10588 + -0.2250000000000000 0.1375000000000000 10589 + -0.2250000000000000 0.1500000000000000 10590 + -0.2250000000000001 0.1625000000000000 10591 + -0.2250000000000000 0.1750000000000000 10592 + -0.2250000000000001 0.1875000000000000 10593 + -0.2250000000000000 0.2000000000000000 10594 + -0.2250000000000001 0.2125000000000000 10595 + -0.2250000000000001 0.2250000000000000 10596 + -0.2250000000000001 0.2375000000000000 10597 + -0.2250000000000001 0.2500000000000000 10598 + -0.2250000000000001 0.2625000000000000 10599 + -0.2250000000000001 0.2750000000000000 10600 + -0.2250000000000001 0.2875000000000000 10601 + -0.2250000000000001 0.3000000000000000 10602 + -0.2250000000000001 0.3125000000000000 10603 + -0.2250000000000001 0.3250000000000000 10604 + -0.2250000000000001 0.3375000000000000 10605 + -0.2250000000000001 0.3500000000000000 10606 + -0.2250000000000001 0.3625000000000000 10607 + -0.2250000000000001 0.3750000000000000 10608 + -0.2250000000000001 0.3875000000000000 10609 + -0.2250000000000001 0.4000000000000000 10610 + -0.2250000000000001 0.4125000000000000 10611 + -0.2250000000000001 0.4250000000000000 10612 + -0.2250000000000002 0.4375000000000000 10613 + -0.2250000000000001 0.4500000000000000 10614 + -0.2250000000000002 0.4625000000000000 10615 + -0.2250000000000002 0.4749999999999999 10616 + -0.2250000000000002 0.4875000000000000 10617 + -0.2250000000000002 0.5000000000000000 10618 + -0.2375000000000000 0.000000000000000 10619 + -0.2375000000000000 0.01250000000000000 10620 + -0.2375000000000000 0.02500000000000000 10621 + -0.2375000000000000 0.03750000000000001 10622 + -0.2375000000000000 0.05000000000000000 10623 + -0.2375000000000000 0.06250000000000000 10624 + -0.2375000000000000 0.07500000000000001 10625 + -0.2375000000000000 0.08750000000000001 10626 + -0.2375000000000000 0.1000000000000000 10627 + -0.2375000000000000 0.1125000000000000 10628 + -0.2375000000000000 0.1250000000000000 10629 + -0.2375000000000000 0.1375000000000000 10630 + -0.2375000000000000 0.1500000000000000 10631 + -0.2375000000000000 0.1625000000000000 10632 + -0.2375000000000000 0.1750000000000000 10633 + -0.2375000000000000 0.1875000000000000 10634 + -0.2375000000000000 0.2000000000000000 10635 + -0.2375000000000000 0.2125000000000000 10636 + -0.2375000000000000 0.2250000000000000 10637 + -0.2375000000000000 0.2375000000000000 10638 + -0.2375000000000000 0.2500000000000000 10639 + -0.2375000000000001 0.2625000000000000 10640 + -0.2375000000000001 0.2750000000000000 10641 + -0.2375000000000001 0.2875000000000000 10642 + -0.2375000000000001 0.3000000000000000 10643 + -0.2375000000000001 0.3125000000000000 10644 + -0.2375000000000001 0.3250000000000000 10645 + -0.2375000000000001 0.3375000000000000 10646 + -0.2375000000000001 0.3500000000000000 10647 + -0.2375000000000001 0.3625000000000000 10648 + -0.2375000000000001 0.3750000000000000 10649 + -0.2375000000000001 0.3875000000000000 10650 + -0.2375000000000001 0.4000000000000000 10651 + -0.2375000000000001 0.4125000000000000 10652 + -0.2375000000000002 0.4250000000000000 10653 + -0.2375000000000002 0.4375000000000000 10654 + -0.2375000000000002 0.4500000000000000 10655 + -0.2375000000000002 0.4625000000000000 10656 + -0.2375000000000002 0.4750000000000000 10657 + -0.2375000000000002 0.4875000000000000 10658 + -0.2375000000000002 0.5000000000000000 10659 + -0.2500000000000000 0.000000000000000 10660 + -0.2500000000000000 0.01250000000000000 10661 + -0.2500000000000000 0.02500000000000000 10662 + -0.2500000000000000 0.03750000000000001 10663 + -0.2500000000000000 0.05000000000000000 10664 + -0.2500000000000000 0.06250000000000000 10665 + -0.2500000000000000 0.07500000000000001 10666 + -0.2500000000000000 0.08750000000000001 10667 + -0.2500000000000000 0.1000000000000000 10668 + -0.2500000000000001 0.1125000000000000 10669 + -0.2500000000000000 0.1250000000000000 10670 + -0.2500000000000000 0.1375000000000000 10671 + -0.2500000000000000 0.1500000000000000 10672 + -0.2500000000000000 0.1625000000000000 10673 + -0.2500000000000000 0.1750000000000000 10674 + -0.2500000000000001 0.1875000000000000 10675 + -0.2500000000000001 0.2000000000000000 10676 + -0.2500000000000001 0.2125000000000000 10677 + -0.2500000000000001 0.2250000000000000 10678 + -0.2500000000000001 0.2375000000000000 10679 + -0.2500000000000001 0.2500000000000000 10680 + -0.2500000000000001 0.2625000000000000 10681 + -0.2500000000000001 0.2750000000000000 10682 + -0.2500000000000001 0.2875000000000000 10683 + -0.2500000000000001 0.3000000000000000 10684 + -0.2500000000000001 0.3125000000000000 10685 + -0.2500000000000001 0.3250000000000000 10686 + -0.2500000000000001 0.3375000000000000 10687 + -0.2500000000000001 0.3500000000000000 10688 + -0.2500000000000001 0.3625000000000000 10689 + -0.2500000000000001 0.3750000000000000 10690 + -0.2500000000000001 0.3875000000000000 10691 + -0.2500000000000001 0.4000000000000000 10692 + -0.2500000000000001 0.4125000000000000 10693 + -0.2500000000000001 0.4250000000000000 10694 + -0.2500000000000001 0.4375000000000000 10695 + -0.2500000000000001 0.4500000000000000 10696 + -0.2500000000000001 0.4625000000000000 10697 + -0.2500000000000001 0.4749999999999999 10698 + -0.2500000000000001 0.4875000000000000 10699 + -0.2500000000000001 0.5000000000000000 10700 + -0.2625000000000000 0.000000000000000 10701 + -0.2625000000000000 0.01250000000000000 10702 + -0.2625000000000000 0.02500000000000000 10703 + -0.2625000000000000 0.03750000000000001 10704 + -0.2625000000000000 0.05000000000000000 10705 + -0.2625000000000000 0.06250000000000000 10706 + -0.2625000000000000 0.07500000000000001 10707 + -0.2625000000000000 0.08750000000000001 10708 + -0.2625000000000000 0.1000000000000000 10709 + -0.2625000000000000 0.1125000000000000 10710 + -0.2625000000000000 0.1250000000000000 10711 + -0.2625000000000001 0.1375000000000000 10712 + -0.2625000000000001 0.1500000000000000 10713 + -0.2625000000000000 0.1625000000000000 10714 + -0.2625000000000000 0.1750000000000000 10715 + -0.2625000000000001 0.1875000000000000 10716 + -0.2625000000000000 0.2000000000000000 10717 + -0.2625000000000000 0.2125000000000000 10718 + -0.2625000000000000 0.2250000000000000 10719 + -0.2624999999999999 0.2375000000000000 10720 + -0.2625000000000000 0.2500000000000000 10721 + -0.2625000000000000 0.2625000000000000 10722 + -0.2625000000000000 0.2750000000000000 10723 + -0.2625000000000000 0.2875000000000000 10724 + -0.2625000000000000 0.3000000000000000 10725 + -0.2625000000000001 0.3125000000000000 10726 + -0.2625000000000001 0.3250000000000000 10727 + -0.2625000000000000 0.3375000000000000 10728 + -0.2625000000000000 0.3500000000000000 10729 + -0.2625000000000001 0.3625000000000000 10730 + -0.2625000000000001 0.3750000000000000 10731 + -0.2625000000000000 0.3875000000000000 10732 + -0.2625000000000001 0.4000000000000000 10733 + -0.2625000000000001 0.4125000000000000 10734 + -0.2625000000000001 0.4250000000000000 10735 + -0.2625000000000001 0.4375000000000000 10736 + -0.2625000000000000 0.4500000000000000 10737 + -0.2625000000000000 0.4625000000000000 10738 + -0.2625000000000000 0.4750000000000000 10739 + -0.2625000000000000 0.4875000000000000 10740 + -0.2625000000000001 0.5000000000000000 10741 + -0.2750000000000000 0.000000000000000 10742 + -0.2750000000000000 0.01250000000000000 10743 + -0.2750000000000000 0.02500000000000000 10744 + -0.2750000000000000 0.03750000000000001 10745 + -0.2750000000000001 0.05000000000000000 10746 + -0.2750000000000000 0.06250000000000000 10747 + -0.2750000000000000 0.07500000000000001 10748 + -0.2750000000000001 0.08750000000000001 10749 + -0.2750000000000001 0.1000000000000000 10750 + -0.2750000000000001 0.1125000000000000 10751 + -0.2750000000000001 0.1250000000000000 10752 + -0.2750000000000001 0.1375000000000000 10753 + -0.2750000000000001 0.1500000000000000 10754 + -0.2750000000000001 0.1625000000000000 10755 + -0.2750000000000001 0.1750000000000000 10756 + -0.2750000000000001 0.1875000000000000 10757 + -0.2750000000000002 0.2000000000000000 10758 + -0.2750000000000002 0.2125000000000000 10759 + -0.2750000000000003 0.2250000000000000 10760 + -0.2750000000000002 0.2375000000000000 10761 + -0.2750000000000003 0.2500000000000000 10762 + -0.2750000000000003 0.2625000000000000 10763 + -0.2750000000000003 0.2750000000000000 10764 + -0.2750000000000003 0.2875000000000000 10765 + -0.2750000000000003 0.3000000000000000 10766 + -0.2750000000000002 0.3125000000000000 10767 + -0.2750000000000002 0.3250000000000000 10768 + -0.2750000000000004 0.3375000000000000 10769 + -0.2750000000000004 0.3500000000000000 10770 + -0.2750000000000004 0.3625000000000000 10771 + -0.2750000000000004 0.3750000000000000 10772 + -0.2750000000000004 0.3875000000000001 10773 + -0.2750000000000004 0.4000000000000000 10774 + -0.2750000000000004 0.4125000000000000 10775 + -0.2750000000000004 0.4250000000000000 10776 + -0.2750000000000004 0.4375000000000000 10777 + -0.2750000000000004 0.4500000000000000 10778 + -0.2750000000000004 0.4625000000000000 10779 + -0.2750000000000004 0.4750000000000001 10780 + -0.2750000000000004 0.4875000000000000 10781 + -0.2750000000000004 0.5000000000000000 10782 + -0.2875000000000000 0.000000000000000 10783 + -0.2875000000000000 0.01250000000000000 10784 + -0.2875000000000000 0.02500000000000000 10785 + -0.2875000000000000 0.03750000000000001 10786 + -0.2875000000000000 0.05000000000000000 10787 + -0.2875000000000000 0.06250000000000000 10788 + -0.2875000000000000 0.07500000000000001 10789 + -0.2875000000000000 0.08750000000000001 10790 + -0.2875000000000000 0.1000000000000000 10791 + -0.2875000000000000 0.1125000000000000 10792 + -0.2875000000000000 0.1250000000000000 10793 + -0.2875000000000000 0.1375000000000000 10794 + -0.2875000000000000 0.1500000000000000 10795 + -0.2875000000000000 0.1625000000000000 10796 + -0.2875000000000000 0.1750000000000000 10797 + -0.2875000000000000 0.1875000000000000 10798 + -0.2875000000000000 0.2000000000000000 10799 + -0.2875000000000000 0.2125000000000000 10800 + -0.2875000000000000 0.2250000000000000 10801 + -0.2875000000000000 0.2375000000000000 10802 + -0.2875000000000000 0.2500000000000000 10803 + -0.2875000000000000 0.2625000000000000 10804 + -0.2875000000000000 0.2750000000000000 10805 + -0.2875000000000000 0.2875000000000000 10806 + -0.2875000000000000 0.3000000000000000 10807 + -0.2875000000000000 0.3125000000000000 10808 + -0.2875000000000000 0.3250000000000000 10809 + -0.2875000000000000 0.3375000000000000 10810 + -0.2875000000000000 0.3500000000000000 10811 + -0.2875000000000000 0.3625000000000000 10812 + -0.2875000000000000 0.3750000000000000 10813 + -0.2875000000000000 0.3875000000000000 10814 + -0.2875000000000000 0.4000000000000000 10815 + -0.2875000000000000 0.4125000000000000 10816 + -0.2874999999999999 0.4250000000000000 10817 + -0.2874999999999999 0.4375000000000000 10818 + -0.2874999999999999 0.4500000000000000 10819 + -0.2874999999999999 0.4625000000000000 10820 + -0.2874999999999999 0.4750000000000000 10821 + -0.2874999999999999 0.4875000000000000 10822 + -0.2875000000000000 0.5000000000000000 10823 + -0.3000000000000000 0.000000000000000 10824 + -0.2999999999999999 0.01250000000000000 10825 + -0.3000000000000000 0.02500000000000000 10826 + -0.3000000000000000 0.03750000000000001 10827 + -0.3000000000000000 0.05000000000000000 10828 + -0.3000000000000000 0.06250000000000000 10829 + -0.3000000000000000 0.07500000000000001 10830 + -0.3000000000000000 0.08750000000000001 10831 + -0.3000000000000000 0.1000000000000000 10832 + -0.3000000000000000 0.1125000000000000 10833 + -0.3000000000000000 0.1250000000000000 10834 + -0.3000000000000001 0.1375000000000000 10835 + -0.3000000000000001 0.1500000000000000 10836 + -0.3000000000000002 0.1625000000000000 10837 + -0.3000000000000001 0.1750000000000000 10838 + -0.3000000000000002 0.1875000000000000 10839 + -0.3000000000000002 0.2000000000000000 10840 + -0.3000000000000002 0.2125000000000000 10841 + -0.3000000000000002 0.2250000000000000 10842 + -0.3000000000000002 0.2375000000000000 10843 + -0.3000000000000002 0.2500000000000000 10844 + -0.3000000000000002 0.2625000000000000 10845 + -0.3000000000000002 0.2750000000000000 10846 + -0.3000000000000002 0.2875000000000000 10847 + -0.3000000000000002 0.3000000000000000 10848 + -0.3000000000000002 0.3125000000000000 10849 + -0.3000000000000003 0.3250000000000000 10850 + -0.3000000000000003 0.3375000000000000 10851 + -0.3000000000000003 0.3500000000000000 10852 + -0.3000000000000003 0.3625000000000000 10853 + -0.3000000000000003 0.3750000000000000 10854 + -0.3000000000000003 0.3875000000000000 10855 + -0.3000000000000003 0.4000000000000000 10856 + -0.3000000000000003 0.4125000000000000 10857 + -0.3000000000000003 0.4250000000000000 10858 + -0.3000000000000003 0.4375000000000000 10859 + -0.3000000000000003 0.4500000000000000 10860 + -0.3000000000000003 0.4625000000000000 10861 + -0.3000000000000003 0.4750000000000000 10862 + -0.3000000000000003 0.4875000000000000 10863 + -0.3000000000000003 0.5000000000000000 10864 + -0.3125000000000000 0.000000000000000 10865 + -0.3125000000000000 0.01250000000000000 10866 + -0.3125000000000000 0.02500000000000000 10867 + -0.3125000000000000 0.03750000000000001 10868 + -0.3125000000000000 0.05000000000000000 10869 + -0.3125000000000000 0.06250000000000000 10870 + -0.3125000000000000 0.07500000000000001 10871 + -0.3125000000000000 0.08750000000000001 10872 + -0.3125000000000000 0.1000000000000000 10873 + -0.3124999999999999 0.1125000000000000 10874 + -0.3124999999999999 0.1250000000000000 10875 + -0.3124999999999999 0.1375000000000000 10876 + -0.3124999999999999 0.1500000000000000 10877 + -0.3125000000000000 0.1625000000000000 10878 + -0.3124999999999999 0.1750000000000000 10879 + -0.3124999999999999 0.1875000000000000 10880 + -0.3124999999999999 0.2000000000000000 10881 + -0.3124999999999999 0.2125000000000000 10882 + -0.3124999999999999 0.2250000000000000 10883 + -0.3124999999999999 0.2375000000000000 10884 + -0.3125000000000000 0.2500000000000000 10885 + -0.3125000000000000 0.2625000000000000 10886 + -0.3125000000000000 0.2750000000000000 10887 + -0.3124999999999999 0.2875000000000000 10888 + -0.3125000000000000 0.3000000000000000 10889 + -0.3125000000000000 0.3125000000000000 10890 + -0.3125000000000000 0.3250000000000000 10891 + -0.3125000000000000 0.3375000000000000 10892 + -0.3124999999999999 0.3500000000000000 10893 + -0.3124999999999999 0.3625000000000000 10894 + -0.3124999999999999 0.3750000000000000 10895 + -0.3124999999999999 0.3875000000000000 10896 + -0.3124999999999999 0.4000000000000000 10897 + -0.3125000000000000 0.4125000000000000 10898 + -0.3124999999999998 0.4250000000000000 10899 + -0.3124999999999998 0.4375000000000000 10900 + -0.3124999999999998 0.4500000000000000 10901 + -0.3124999999999998 0.4625000000000000 10902 + -0.3124999999999998 0.4749999999999999 10903 + -0.3124999999999998 0.4875000000000000 10904 + -0.3124999999999999 0.5000000000000000 10905 + -0.3250000000000000 0.000000000000000 10906 + -0.3249999999999999 0.01250000000000000 10907 + -0.3250000000000000 0.02500000000000000 10908 + -0.3250000000000001 0.03750000000000001 10909 + -0.3250000000000000 0.05000000000000000 10910 + -0.3249999999999999 0.06250000000000000 10911 + -0.3249999999999999 0.07500000000000001 10912 + -0.3250000000000000 0.08750000000000001 10913 + -0.3250000000000001 0.1000000000000000 10914 + -0.3250000000000000 0.1125000000000000 10915 + -0.3250000000000000 0.1250000000000000 10916 + -0.3250000000000001 0.1375000000000000 10917 + -0.3250000000000001 0.1500000000000000 10918 + -0.3250000000000001 0.1625000000000000 10919 + -0.3250000000000000 0.1750000000000000 10920 + -0.3250000000000001 0.1875000000000000 10921 + -0.3250000000000001 0.2000000000000000 10922 + -0.3250000000000001 0.2125000000000000 10923 + -0.3250000000000001 0.2250000000000000 10924 + -0.3250000000000001 0.2375000000000000 10925 + -0.3250000000000001 0.2500000000000000 10926 + -0.3250000000000002 0.2625000000000000 10927 + -0.3250000000000001 0.2750000000000000 10928 + -0.3250000000000002 0.2875000000000000 10929 + -0.3250000000000002 0.3000000000000000 10930 + -0.3250000000000002 0.3125000000000000 10931 + -0.3250000000000002 0.3250000000000000 10932 + -0.3250000000000002 0.3375000000000000 10933 + -0.3250000000000002 0.3500000000000000 10934 + -0.3250000000000002 0.3625000000000000 10935 + -0.3250000000000002 0.3750000000000000 10936 + -0.3250000000000002 0.3875000000000000 10937 + -0.3250000000000002 0.4000000000000000 10938 + -0.3250000000000002 0.4125000000000000 10939 + -0.3250000000000002 0.4250000000000000 10940 + -0.3250000000000002 0.4375000000000000 10941 + -0.3250000000000002 0.4500000000000000 10942 + -0.3250000000000002 0.4625000000000000 10943 + -0.3250000000000002 0.4750000000000001 10944 + -0.3250000000000002 0.4875000000000000 10945 + -0.3250000000000002 0.5000000000000000 10946 + -0.3375000000000000 0.000000000000000 10947 + -0.3375000000000001 0.01250000000000000 10948 + -0.3375000000000000 0.02500000000000000 10949 + -0.3375000000000001 0.03750000000000001 10950 + -0.3375000000000001 0.05000000000000000 10951 + -0.3375000000000001 0.06250000000000000 10952 + -0.3375000000000001 0.07500000000000001 10953 + -0.3375000000000000 0.08750000000000001 10954 + -0.3375000000000000 0.1000000000000000 10955 + -0.3375000000000001 0.1125000000000000 10956 + -0.3375000000000001 0.1250000000000000 10957 + -0.3375000000000001 0.1375000000000000 10958 + -0.3375000000000001 0.1500000000000000 10959 + -0.3375000000000000 0.1625000000000000 10960 + -0.3375000000000001 0.1750000000000000 10961 + -0.3375000000000001 0.1875000000000000 10962 + -0.3375000000000001 0.2000000000000000 10963 + -0.3375000000000001 0.2125000000000000 10964 + -0.3375000000000001 0.2250000000000000 10965 + -0.3375000000000001 0.2375000000000000 10966 + -0.3375000000000001 0.2500000000000000 10967 + -0.3375000000000002 0.2625000000000000 10968 + -0.3375000000000002 0.2750000000000000 10969 + -0.3375000000000002 0.2875000000000000 10970 + -0.3375000000000002 0.3000000000000000 10971 + -0.3375000000000002 0.3125000000000000 10972 + -0.3375000000000002 0.3250000000000000 10973 + -0.3375000000000002 0.3375000000000000 10974 + -0.3375000000000002 0.3500000000000000 10975 + -0.3375000000000002 0.3625000000000000 10976 + -0.3375000000000002 0.3750000000000000 10977 + -0.3375000000000002 0.3875000000000000 10978 + -0.3375000000000002 0.4000000000000000 10979 + -0.3375000000000002 0.4125000000000000 10980 + -0.3375000000000002 0.4250000000000000 10981 + -0.3375000000000001 0.4375000000000000 10982 + -0.3375000000000002 0.4500000000000000 10983 + -0.3375000000000001 0.4625000000000000 10984 + -0.3375000000000002 0.4750000000000000 10985 + -0.3375000000000002 0.4875000000000000 10986 + -0.3375000000000002 0.5000000000000000 10987 + -0.3500000000000000 0.000000000000000 10988 + -0.3500000000000000 0.01250000000000000 10989 + -0.3500000000000000 0.02500000000000000 10990 + -0.3500000000000000 0.03750000000000001 10991 + -0.3500000000000001 0.05000000000000000 10992 + -0.3500000000000000 0.06250000000000000 10993 + -0.3500000000000001 0.07500000000000001 10994 + -0.3500000000000000 0.08750000000000001 10995 + -0.3500000000000000 0.1000000000000000 10996 + -0.3500000000000001 0.1125000000000000 10997 + -0.3500000000000000 0.1250000000000000 10998 + -0.3500000000000000 0.1375000000000000 10999 + -0.3500000000000000 0.1500000000000000 11000 + -0.3500000000000001 0.1625000000000000 11001 + -0.3500000000000000 0.1750000000000000 11002 + -0.3500000000000001 0.1875000000000000 11003 + -0.3500000000000001 0.2000000000000000 11004 + -0.3500000000000001 0.2125000000000000 11005 + -0.3500000000000001 0.2250000000000000 11006 + -0.3500000000000001 0.2375000000000000 11007 + -0.3500000000000001 0.2500000000000000 11008 + -0.3500000000000001 0.2625000000000000 11009 + -0.3500000000000001 0.2750000000000000 11010 + -0.3500000000000001 0.2875000000000000 11011 + -0.3500000000000001 0.3000000000000000 11012 + -0.3500000000000001 0.3125000000000000 11013 + -0.3500000000000001 0.3250000000000000 11014 + -0.3500000000000001 0.3375000000000000 11015 + -0.3500000000000001 0.3500000000000000 11016 + -0.3500000000000001 0.3625000000000000 11017 + -0.3500000000000001 0.3750000000000000 11018 + -0.3500000000000001 0.3875000000000000 11019 + -0.3500000000000001 0.4000000000000000 11020 + -0.3500000000000001 0.4125000000000001 11021 + -0.3500000000000001 0.4250000000000000 11022 + -0.3500000000000002 0.4375000000000000 11023 + -0.3500000000000001 0.4500000000000000 11024 + -0.3500000000000002 0.4625000000000000 11025 + -0.3500000000000002 0.4750000000000000 11026 + -0.3500000000000002 0.4875000000000000 11027 + -0.3500000000000001 0.5000000000000000 11028 + -0.3625000000000000 0.000000000000000 11029 + -0.3625000000000000 0.01250000000000000 11030 + -0.3625000000000000 0.02500000000000000 11031 + -0.3625000000000000 0.03750000000000001 11032 + -0.3625000000000000 0.05000000000000000 11033 + -0.3625000000000000 0.06250000000000000 11034 + -0.3625000000000000 0.07500000000000001 11035 + -0.3625000000000000 0.08750000000000001 11036 + -0.3625000000000000 0.1000000000000000 11037 + -0.3625000000000001 0.1125000000000000 11038 + -0.3625000000000000 0.1250000000000000 11039 + -0.3625000000000001 0.1375000000000000 11040 + -0.3625000000000001 0.1500000000000000 11041 + -0.3625000000000001 0.1625000000000000 11042 + -0.3625000000000001 0.1750000000000000 11043 + -0.3625000000000001 0.1875000000000000 11044 + -0.3625000000000001 0.2000000000000000 11045 + -0.3625000000000001 0.2125000000000000 11046 + -0.3625000000000001 0.2250000000000000 11047 + -0.3625000000000001 0.2375000000000000 11048 + -0.3625000000000000 0.2500000000000000 11049 + -0.3625000000000000 0.2625000000000000 11050 + -0.3625000000000000 0.2750000000000000 11051 + -0.3625000000000000 0.2875000000000000 11052 + -0.3625000000000000 0.3000000000000000 11053 + -0.3625000000000000 0.3125000000000000 11054 + -0.3625000000000000 0.3250000000000000 11055 + -0.3625000000000000 0.3375000000000000 11056 + -0.3625000000000000 0.3500000000000000 11057 + -0.3625000000000002 0.3625000000000000 11058 + -0.3625000000000002 0.3750000000000000 11059 + -0.3625000000000000 0.3875000000000000 11060 + -0.3625000000000000 0.4000000000000000 11061 + -0.3625000000000002 0.4125000000000000 11062 + -0.3625000000000000 0.4250000000000000 11063 + -0.3625000000000000 0.4375000000000000 11064 + -0.3625000000000001 0.4500000000000000 11065 + -0.3625000000000001 0.4625000000000000 11066 + -0.3625000000000000 0.4750000000000000 11067 + -0.3625000000000001 0.4875000000000000 11068 + -0.3625000000000001 0.5000000000000000 11069 + -0.3750000000000000 0.000000000000000 11070 + -0.3750000000000000 0.01250000000000000 11071 + -0.3750000000000000 0.02500000000000000 11072 + -0.3750000000000000 0.03750000000000001 11073 + -0.3750000000000000 0.05000000000000000 11074 + -0.3750000000000000 0.06250000000000000 11075 + -0.3750000000000000 0.07500000000000001 11076 + -0.3750000000000001 0.08750000000000001 11077 + -0.3750000000000001 0.1000000000000000 11078 + -0.3750000000000001 0.1125000000000000 11079 + -0.3750000000000001 0.1250000000000000 11080 + -0.3750000000000001 0.1375000000000000 11081 + -0.3750000000000001 0.1500000000000000 11082 + -0.3750000000000001 0.1625000000000000 11083 + -0.3750000000000001 0.1750000000000000 11084 + -0.3750000000000001 0.1875000000000000 11085 + -0.3750000000000001 0.2000000000000000 11086 + -0.3750000000000001 0.2125000000000000 11087 + -0.3750000000000001 0.2250000000000000 11088 + -0.3750000000000001 0.2375000000000000 11089 + -0.3750000000000000 0.2500000000000000 11090 + -0.3750000000000000 0.2625000000000000 11091 + -0.3750000000000000 0.2750000000000000 11092 + -0.3750000000000001 0.2875000000000000 11093 + -0.3750000000000000 0.3000000000000000 11094 + -0.3750000000000000 0.3125000000000000 11095 + -0.3750000000000000 0.3250000000000000 11096 + -0.3750000000000000 0.3375000000000000 11097 + -0.3750000000000001 0.3500000000000000 11098 + -0.3750000000000001 0.3625000000000000 11099 + -0.3750000000000001 0.3750000000000000 11100 + -0.3750000000000001 0.3875000000000000 11101 + -0.3750000000000000 0.4000000000000000 11102 + -0.3750000000000001 0.4125000000000000 11103 + -0.3750000000000001 0.4250000000000000 11104 + -0.3750000000000001 0.4375000000000000 11105 + -0.3750000000000001 0.4500000000000000 11106 + -0.3749999999999999 0.4625000000000000 11107 + -0.3750000000000001 0.4750000000000000 11108 + -0.3750000000000001 0.4875000000000000 11109 + -0.3750000000000001 0.5000000000000000 11110 + -0.3875000000000000 0.000000000000000 11111 + -0.3875000000000000 0.01250000000000000 11112 + -0.3875000000000000 0.02500000000000000 11113 + -0.3875000000000000 0.03750000000000001 11114 + -0.3875000000000000 0.05000000000000000 11115 + -0.3875000000000000 0.06250000000000000 11116 + -0.3875000000000000 0.07500000000000001 11117 + -0.3875000000000001 0.08750000000000001 11118 + -0.3875000000000001 0.1000000000000000 11119 + -0.3875000000000001 0.1125000000000000 11120 + -0.3875000000000001 0.1250000000000000 11121 + -0.3875000000000001 0.1375000000000000 11122 + -0.3875000000000001 0.1500000000000000 11123 + -0.3875000000000001 0.1625000000000000 11124 + -0.3875000000000000 0.1750000000000000 11125 + -0.3875000000000001 0.1875000000000000 11126 + -0.3875000000000001 0.2000000000000000 11127 + -0.3875000000000001 0.2125000000000000 11128 + -0.3875000000000001 0.2250000000000000 11129 + -0.3875000000000000 0.2375000000000000 11130 + -0.3875000000000001 0.2500000000000000 11131 + -0.3875000000000000 0.2625000000000000 11132 + -0.3875000000000000 0.2750000000000000 11133 + -0.3875000000000000 0.2875000000000000 11134 + -0.3875000000000000 0.3000000000000000 11135 + -0.3875000000000000 0.3125000000000000 11136 + -0.3875000000000000 0.3250000000000000 11137 + -0.3875000000000000 0.3375000000000000 11138 + -0.3875000000000000 0.3500000000000000 11139 + -0.3875000000000000 0.3625000000000000 11140 + -0.3875000000000000 0.3750000000000000 11141 + -0.3875000000000000 0.3875000000000000 11142 + -0.3875000000000001 0.4000000000000000 11143 + -0.3874999999999999 0.4125000000000000 11144 + -0.3875000000000000 0.4250000000000000 11145 + -0.3875000000000000 0.4375000000000000 11146 + -0.3875000000000000 0.4500000000000000 11147 + -0.3875000000000000 0.4625000000000000 11148 + -0.3875000000000000 0.4750000000000000 11149 + -0.3875000000000000 0.4875000000000000 11150 + -0.3875000000000000 0.5000000000000000 11151 + -0.4000000000000000 0.000000000000000 11152 + -0.4000000000000000 0.01250000000000000 11153 + -0.4000000000000000 0.02500000000000000 11154 + -0.4000000000000001 0.03750000000000001 11155 + -0.4000000000000001 0.05000000000000000 11156 + -0.4000000000000001 0.06250000000000000 11157 + -0.4000000000000001 0.07500000000000001 11158 + -0.4000000000000000 0.08750000000000001 11159 + -0.4000000000000001 0.1000000000000000 11160 + -0.4000000000000001 0.1125000000000000 11161 + -0.4000000000000001 0.1250000000000000 11162 + -0.4000000000000000 0.1375000000000000 11163 + -0.4000000000000000 0.1500000000000000 11164 + -0.4000000000000001 0.1625000000000000 11165 + -0.4000000000000000 0.1750000000000000 11166 + -0.4000000000000001 0.1875000000000000 11167 + -0.4000000000000001 0.2000000000000000 11168 + -0.4000000000000001 0.2125000000000000 11169 + -0.4000000000000002 0.2250000000000000 11170 + -0.4000000000000001 0.2375000000000000 11171 + -0.4000000000000002 0.2500000000000000 11172 + -0.4000000000000002 0.2625000000000000 11173 + -0.4000000000000003 0.2750000000000000 11174 + -0.4000000000000003 0.2875000000000000 11175 + -0.4000000000000003 0.3000000000000000 11176 + -0.4000000000000003 0.3125000000000000 11177 + -0.4000000000000003 0.3250000000000000 11178 + -0.4000000000000003 0.3375000000000000 11179 + -0.4000000000000003 0.3500000000000000 11180 + -0.4000000000000003 0.3625000000000000 11181 + -0.4000000000000003 0.3750000000000000 11182 + -0.4000000000000003 0.3875000000000000 11183 + -0.4000000000000003 0.4000000000000000 11184 + -0.4000000000000003 0.4125000000000000 11185 + -0.4000000000000004 0.4250000000000000 11186 + -0.4000000000000004 0.4375000000000000 11187 + -0.4000000000000004 0.4500000000000000 11188 + -0.4000000000000004 0.4625000000000000 11189 + -0.4000000000000004 0.4750000000000000 11190 + -0.4000000000000004 0.4875000000000000 11191 + -0.4000000000000004 0.5000000000000000 11192 + -0.4125000000000000 0.000000000000000 11193 + -0.4124999999999999 0.01250000000000000 11194 + -0.4124999999999999 0.02500000000000000 11195 + -0.4124999999999999 0.03750000000000001 11196 + -0.4124999999999999 0.05000000000000000 11197 + -0.4124999999999999 0.06250000000000000 11198 + -0.4124999999999999 0.07500000000000001 11199 + -0.4125000000000000 0.08750000000000001 11200 + -0.4125000000000000 0.1000000000000000 11201 + -0.4125000000000000 0.1125000000000000 11202 + -0.4125000000000000 0.1250000000000000 11203 + -0.4125000000000000 0.1375000000000000 11204 + -0.4125000000000000 0.1500000000000000 11205 + -0.4125000000000000 0.1625000000000000 11206 + -0.4125000000000000 0.1750000000000000 11207 + -0.4125000000000000 0.1875000000000000 11208 + -0.4125000000000000 0.2000000000000000 11209 + -0.4125000000000000 0.2125000000000000 11210 + -0.4125000000000000 0.2250000000000000 11211 + -0.4125000000000000 0.2375000000000000 11212 + -0.4125000000000000 0.2500000000000000 11213 + -0.4125000000000000 0.2625000000000000 11214 + -0.4125000000000000 0.2750000000000000 11215 + -0.4125000000000000 0.2875000000000000 11216 + -0.4125000000000000 0.3000000000000000 11217 + -0.4124999999999999 0.3125000000000000 11218 + -0.4124999999999999 0.3250000000000000 11219 + -0.4124999999999999 0.3375000000000000 11220 + -0.4124999999999999 0.3500000000000000 11221 + -0.4124999999999999 0.3625000000000000 11222 + -0.4125000000000000 0.3750000000000000 11223 + -0.4125000000000000 0.3875000000000000 11224 + -0.4124999999999999 0.4000000000000000 11225 + -0.4124999999999999 0.4125000000000000 11226 + -0.4124999999999999 0.4250000000000000 11227 + -0.4124999999999999 0.4375000000000000 11228 + -0.4124999999999999 0.4500000000000000 11229 + -0.4125000000000000 0.4625000000000000 11230 + -0.4124999999999999 0.4750000000000000 11231 + -0.4124999999999999 0.4875000000000000 11232 + -0.4124999999999999 0.5000000000000000 11233 + -0.4250000000000000 0.000000000000000 11234 + -0.4249999999999999 0.01250000000000000 11235 + -0.4249999999999999 0.02500000000000000 11236 + -0.4250000000000000 0.03750000000000001 11237 + -0.4250000000000000 0.05000000000000000 11238 + -0.4250000000000000 0.06250000000000000 11239 + -0.4249999999999999 0.07500000000000001 11240 + -0.4250000000000000 0.08750000000000001 11241 + -0.4250000000000002 0.1000000000000000 11242 + -0.4250000000000000 0.1125000000000000 11243 + -0.4250000000000000 0.1250000000000000 11244 + -0.4250000000000000 0.1375000000000000 11245 + -0.4250000000000000 0.1500000000000000 11246 + -0.4250000000000000 0.1625000000000000 11247 + -0.4250000000000000 0.1750000000000000 11248 + -0.4250000000000001 0.1875000000000000 11249 + -0.4250000000000002 0.2000000000000000 11250 + -0.4250000000000001 0.2125000000000000 11251 + -0.4250000000000002 0.2250000000000000 11252 + -0.4250000000000001 0.2375000000000000 11253 + -0.4250000000000002 0.2500000000000000 11254 + -0.4250000000000002 0.2625000000000000 11255 + -0.4250000000000002 0.2750000000000000 11256 + -0.4250000000000002 0.2875000000000000 11257 + -0.4250000000000002 0.3000000000000000 11258 + -0.4250000000000002 0.3125000000000000 11259 + -0.4250000000000002 0.3250000000000000 11260 + -0.4250000000000002 0.3375000000000000 11261 + -0.4250000000000002 0.3500000000000000 11262 + -0.4250000000000002 0.3625000000000000 11263 + -0.4250000000000003 0.3750000000000000 11264 + -0.4250000000000002 0.3875000000000000 11265 + -0.4250000000000003 0.4000000000000000 11266 + -0.4250000000000003 0.4125000000000000 11267 + -0.4250000000000003 0.4250000000000000 11268 + -0.4250000000000003 0.4375000000000000 11269 + -0.4250000000000003 0.4500000000000000 11270 + -0.4250000000000003 0.4625000000000000 11271 + -0.4250000000000003 0.4750000000000000 11272 + -0.4250000000000003 0.4875000000000000 11273 + -0.4250000000000003 0.5000000000000000 11274 + -0.4375000000000000 0.000000000000000 11275 + -0.4375000000000000 0.01250000000000000 11276 + -0.4374999999999999 0.02500000000000000 11277 + -0.4375000000000000 0.03750000000000001 11278 + -0.4375000000000000 0.05000000000000000 11279 + -0.4375000000000000 0.06250000000000000 11280 + -0.4375000000000000 0.07500000000000001 11281 + -0.4374999999999999 0.08750000000000001 11282 + -0.4375000000000000 0.1000000000000000 11283 + -0.4374999999999999 0.1125000000000000 11284 + -0.4374999999999999 0.1250000000000000 11285 + -0.4375000000000000 0.1375000000000000 11286 + -0.4374999999999999 0.1500000000000000 11287 + -0.4375000000000000 0.1625000000000000 11288 + -0.4374999999999999 0.1750000000000000 11289 + -0.4374999999999999 0.1875000000000000 11290 + -0.4374999999999999 0.2000000000000000 11291 + -0.4374999999999999 0.2125000000000000 11292 + -0.4375000000000000 0.2250000000000000 11293 + -0.4374999999999999 0.2375000000000000 11294 + -0.4374999999999999 0.2500000000000000 11295 + -0.4374999999999999 0.2625000000000000 11296 + -0.4374999999999999 0.2750000000000000 11297 + -0.4374999999999999 0.2875000000000000 11298 + -0.4374999999999999 0.3000000000000000 11299 + -0.4374999999999999 0.3125000000000000 11300 + -0.4374999999999999 0.3250000000000000 11301 + -0.4374999999999999 0.3375000000000000 11302 + -0.4374999999999999 0.3500000000000000 11303 + -0.4374999999999999 0.3625000000000000 11304 + -0.4374999999999999 0.3750000000000000 11305 + -0.4374999999999999 0.3875000000000000 11306 + -0.4374999999999998 0.4000000000000000 11307 + -0.4374999999999999 0.4125000000000000 11308 + -0.4374999999999999 0.4250000000000000 11309 + -0.4374999999999998 0.4375000000000000 11310 + -0.4374999999999999 0.4500000000000000 11311 + -0.4374999999999998 0.4625000000000000 11312 + -0.4374999999999998 0.4750000000000000 11313 + -0.4374999999999999 0.4875000000000000 11314 + -0.4374999999999998 0.5000000000000000 11315 + -0.4500000000000000 0.000000000000000 11316 + -0.4499999999999999 0.01250000000000000 11317 + -0.4500000000000000 0.02500000000000000 11318 + -0.4500000000000000 0.03750000000000001 11319 + -0.4500000000000001 0.05000000000000000 11320 + -0.4500000000000000 0.06250000000000000 11321 + -0.4500000000000001 0.07500000000000001 11322 + -0.4500000000000000 0.08750000000000001 11323 + -0.4500000000000001 0.1000000000000000 11324 + -0.4500000000000001 0.1125000000000000 11325 + -0.4500000000000001 0.1250000000000000 11326 + -0.4500000000000001 0.1375000000000000 11327 + -0.4500000000000001 0.1500000000000000 11328 + -0.4500000000000001 0.1625000000000000 11329 + -0.4500000000000001 0.1750000000000000 11330 + -0.4500000000000001 0.1875000000000000 11331 + -0.4500000000000001 0.2000000000000000 11332 + -0.4500000000000001 0.2125000000000000 11333 + -0.4500000000000001 0.2250000000000000 11334 + -0.4500000000000001 0.2375000000000000 11335 + -0.4500000000000001 0.2500000000000000 11336 + -0.4500000000000001 0.2625000000000000 11337 + -0.4500000000000001 0.2750000000000000 11338 + -0.4500000000000002 0.2875000000000000 11339 + -0.4500000000000001 0.3000000000000000 11340 + -0.4500000000000002 0.3125000000000000 11341 + -0.4500000000000002 0.3250000000000000 11342 + -0.4500000000000002 0.3375000000000000 11343 + -0.4500000000000002 0.3500000000000000 11344 + -0.4500000000000002 0.3625000000000000 11345 + -0.4500000000000002 0.3750000000000000 11346 + -0.4500000000000002 0.3875000000000000 11347 + -0.4500000000000002 0.4000000000000000 11348 + -0.4500000000000002 0.4125000000000000 11349 + -0.4500000000000002 0.4250000000000000 11350 + -0.4500000000000002 0.4375000000000000 11351 + -0.4500000000000002 0.4500000000000000 11352 + -0.4500000000000002 0.4625000000000000 11353 + -0.4500000000000002 0.4750000000000000 11354 + -0.4500000000000002 0.4875000000000000 11355 + -0.4500000000000002 0.5000000000000000 11356 + -0.4625000000000000 0.000000000000000 11357 + -0.4625000000000001 0.01250000000000000 11358 + -0.4625000000000001 0.02500000000000000 11359 + -0.4625000000000001 0.03750000000000001 11360 + -0.4625000000000001 0.05000000000000000 11361 + -0.4625000000000001 0.06250000000000000 11362 + -0.4625000000000001 0.07500000000000001 11363 + -0.4625000000000001 0.08750000000000001 11364 + -0.4625000000000001 0.1000000000000000 11365 + -0.4625000000000001 0.1125000000000000 11366 + -0.4625000000000002 0.1250000000000000 11367 + -0.4625000000000001 0.1375000000000000 11368 + -0.4625000000000001 0.1500000000000000 11369 + -0.4625000000000003 0.1625000000000000 11370 + -0.4625000000000001 0.1750000000000000 11371 + -0.4625000000000002 0.1875000000000000 11372 + -0.4625000000000003 0.2000000000000000 11373 + -0.4625000000000003 0.2125000000000000 11374 + -0.4625000000000003 0.2250000000000000 11375 + -0.4625000000000003 0.2375000000000000 11376 + -0.4625000000000002 0.2500000000000000 11377 + -0.4625000000000004 0.2625000000000000 11378 + -0.4625000000000002 0.2750000000000000 11379 + -0.4625000000000004 0.2875000000000000 11380 + -0.4625000000000004 0.3000000000000000 11381 + -0.4625000000000004 0.3125000000000000 11382 + -0.4625000000000004 0.3250000000000000 11383 + -0.4625000000000004 0.3375000000000000 11384 + -0.4625000000000004 0.3500000000000000 11385 + -0.4625000000000004 0.3625000000000000 11386 + -0.4625000000000004 0.3750000000000000 11387 + -0.4625000000000004 0.3875000000000000 11388 + -0.4625000000000004 0.4000000000000000 11389 + -0.4625000000000005 0.4125000000000000 11390 + -0.4625000000000005 0.4250000000000000 11391 + -0.4625000000000005 0.4375000000000000 11392 + -0.4625000000000005 0.4500000000000000 11393 + -0.4625000000000005 0.4625000000000000 11394 + -0.4625000000000005 0.4750000000000000 11395 + -0.4625000000000006 0.4875000000000000 11396 + -0.4625000000000005 0.5000000000000000 11397 + -0.4750000000000000 0.000000000000000 11398 + -0.4750000000000000 0.01250000000000000 11399 + -0.4750000000000000 0.02500000000000000 11400 + -0.4750000000000000 0.03750000000000001 11401 + -0.4750000000000000 0.05000000000000000 11402 + -0.4750000000000000 0.06250000000000000 11403 + -0.4750000000000000 0.07500000000000001 11404 + -0.4750000000000000 0.08750000000000001 11405 + -0.4750000000000000 0.1000000000000000 11406 + -0.4750000000000000 0.1125000000000000 11407 + -0.4750000000000000 0.1250000000000000 11408 + -0.4750000000000000 0.1375000000000000 11409 + -0.4750000000000000 0.1500000000000000 11410 + -0.4750000000000000 0.1625000000000000 11411 + -0.4750000000000000 0.1750000000000000 11412 + -0.4750000000000000 0.1875000000000000 11413 + -0.4750000000000000 0.2000000000000000 11414 + -0.4750000000000000 0.2125000000000000 11415 + -0.4750000000000000 0.2250000000000000 11416 + -0.4750000000000000 0.2375000000000000 11417 + -0.4750000000000001 0.2500000000000000 11418 + -0.4750000000000001 0.2625000000000000 11419 + -0.4750000000000001 0.2750000000000000 11420 + -0.4750000000000001 0.2875000000000000 11421 + -0.4750000000000001 0.3000000000000000 11422 + -0.4750000000000001 0.3125000000000000 11423 + -0.4750000000000001 0.3250000000000000 11424 + -0.4750000000000001 0.3375000000000000 11425 + -0.4750000000000001 0.3500000000000000 11426 + -0.4750000000000001 0.3625000000000000 11427 + -0.4750000000000001 0.3750000000000000 11428 + -0.4750000000000001 0.3875000000000000 11429 + -0.4750000000000001 0.4000000000000000 11430 + -0.4750000000000001 0.4125000000000000 11431 + -0.4750000000000001 0.4250000000000000 11432 + -0.4750000000000001 0.4375000000000000 11433 + -0.4750000000000001 0.4500000000000000 11434 + -0.4750000000000001 0.4625000000000000 11435 + -0.4750000000000001 0.4750000000000000 11436 + -0.4750000000000001 0.4875000000000000 11437 + -0.4750000000000001 0.5000000000000000 11438 + -0.4875000000000000 0.000000000000000 11439 + -0.4875000000000000 0.01250000000000000 11440 + -0.4875000000000000 0.02500000000000000 11441 + -0.4875000000000000 0.03750000000000001 11442 + -0.4875000000000000 0.05000000000000000 11443 + -0.4875000000000000 0.06250000000000000 11444 + -0.4875000000000000 0.07500000000000001 11445 + -0.4875000000000000 0.08750000000000001 11446 + -0.4875000000000000 0.1000000000000000 11447 + -0.4875000000000000 0.1125000000000000 11448 + -0.4875000000000000 0.1250000000000000 11449 + -0.4875000000000000 0.1375000000000000 11450 + -0.4875000000000002 0.1500000000000000 11451 + -0.4875000000000002 0.1625000000000000 11452 + -0.4875000000000002 0.1750000000000000 11453 + -0.4875000000000002 0.1875000000000000 11454 + -0.4875000000000002 0.2000000000000000 11455 + -0.4875000000000002 0.2125000000000000 11456 + -0.4875000000000003 0.2250000000000000 11457 + -0.4875000000000002 0.2375000000000000 11458 + -0.4875000000000003 0.2500000000000000 11459 + -0.4875000000000003 0.2625000000000000 11460 + -0.4875000000000003 0.2750000000000000 11461 + -0.4875000000000003 0.2875000000000000 11462 + -0.4875000000000003 0.3000000000000000 11463 + -0.4875000000000003 0.3125000000000000 11464 + -0.4875000000000003 0.3250000000000000 11465 + -0.4875000000000003 0.3375000000000000 11466 + -0.4875000000000003 0.3500000000000000 11467 + -0.4875000000000003 0.3625000000000000 11468 + -0.4875000000000003 0.3750000000000000 11469 + -0.4875000000000003 0.3875000000000000 11470 + -0.4875000000000003 0.4000000000000000 11471 + -0.4875000000000003 0.4125000000000000 11472 + -0.4875000000000004 0.4250000000000000 11473 + -0.4875000000000004 0.4375000000000000 11474 + -0.4875000000000004 0.4500000000000000 11475 + -0.4875000000000005 0.4625000000000000 11476 + -0.4875000000000005 0.4750000000000000 11477 + -0.4875000000000005 0.4875000000000000 11478 + -0.4875000000000004 0.5000000000000000 11479 + -0.5000000000000000 0.000000000000000 11480 + -0.5000000000000000 0.01250000000000000 11481 + -0.5000000000000000 0.02500000000000000 11482 + -0.5000000000000000 0.03750000000000001 11483 + -0.5000000000000000 0.05000000000000000 11484 + -0.5000000000000000 0.06250000000000000 11485 + -0.5000000000000000 0.07500000000000001 11486 + -0.5000000000000000 0.08750000000000001 11487 + -0.5000000000000000 0.1000000000000000 11488 + -0.5000000000000000 0.1125000000000000 11489 + -0.5000000000000000 0.1250000000000000 11490 + -0.5000000000000000 0.1375000000000000 11491 + -0.5000000000000000 0.1500000000000000 11492 + -0.5000000000000000 0.1625000000000000 11493 + -0.5000000000000000 0.1750000000000000 11494 + -0.5000000000000000 0.1875000000000000 11495 + -0.5000000000000000 0.2000000000000000 11496 + -0.5000000000000000 0.2125000000000000 11497 + -0.5000000000000000 0.2250000000000000 11498 + -0.5000000000000000 0.2375000000000000 11499 + -0.5000000000000000 0.2500000000000000 11500 + -0.5000000000000000 0.2625000000000000 11501 + -0.5000000000000000 0.2750000000000000 11502 + -0.5000000000000000 0.2875000000000000 11503 + -0.5000000000000000 0.3000000000000000 11504 + -0.5000000000000000 0.3125000000000000 11505 + -0.5000000000000000 0.3250000000000000 11506 + -0.5000000000000000 0.3375000000000000 11507 + -0.5000000000000000 0.3500000000000000 11508 + -0.5000000000000000 0.3625000000000000 11509 + -0.5000000000000000 0.3750000000000000 11510 + -0.5000000000000000 0.3875000000000000 11511 + -0.5000000000000000 0.4000000000000000 11512 + -0.5000000000000000 0.4125000000000000 11513 + -0.5000000000000000 0.4250000000000000 11514 + -0.5000000000000000 0.4375000000000000 11515 + -0.5000000000000000 0.4500000000000000 11516 + -0.5000000000000000 0.4625000000000000 11517 + -0.5000000000000000 0.4750000000000000 11518 + -0.5000000000000000 0.4875000000000000 11519 + -0.5000000000000000 0.5000000000000000 11520 +% +% Boundary elements +% +NMARK= 6 +MARKER_TAG= bottom +MARKER_ELEMS= 160 + 3 6560 6519 + 3 6519 6478 + 3 6478 6437 + 3 6437 6396 + 3 6396 6355 + 3 6355 6314 + 3 6314 6273 + 3 6273 6232 + 3 6232 6191 + 3 6191 6150 + 3 6150 6109 + 3 6109 6068 + 3 6068 6027 + 3 6027 5986 + 3 5986 5945 + 3 5945 5904 + 3 5904 5863 + 3 5863 5822 + 3 5822 5781 + 3 5781 5740 + 3 5740 5699 + 3 5699 5658 + 3 5658 5617 + 3 5617 5576 + 3 5576 5535 + 3 5535 5494 + 3 5494 5453 + 3 5453 5412 + 3 5412 5371 + 3 5371 5330 + 3 5330 5289 + 3 5289 5248 + 3 5248 5207 + 3 5207 5166 + 3 5166 5125 + 3 5125 5084 + 3 5084 5043 + 3 5043 5002 + 3 5002 4961 + 3 4961 4920 + 3 4920 4879 + 3 4879 4838 + 3 4838 4797 + 3 4797 4756 + 3 4756 4715 + 3 4715 4674 + 3 4674 4633 + 3 4633 4592 + 3 4592 4551 + 3 4551 4510 + 3 4510 4469 + 3 4469 4428 + 3 4428 4387 + 3 4387 4346 + 3 4346 4305 + 3 4305 4264 + 3 4264 4223 + 3 4223 4182 + 3 4182 4141 + 3 4141 4100 + 3 4100 4059 + 3 4059 4018 + 3 4018 3977 + 3 3977 3936 + 3 3936 3895 + 3 3895 3854 + 3 3854 3813 + 3 3813 3772 + 3 3772 3731 + 3 3731 3690 + 3 3690 3649 + 3 3649 3608 + 3 3608 3567 + 3 3567 3526 + 3 3526 3485 + 3 3485 3444 + 3 3444 3403 + 3 3403 3362 + 3 3362 3321 + 3 3321 3280 + 3 3280 3239 + 3 3239 3198 + 3 3198 3157 + 3 3157 3116 + 3 3116 3075 + 3 3075 3034 + 3 3034 2993 + 3 2993 2952 + 3 2952 2911 + 3 2911 2870 + 3 2870 2829 + 3 2829 2788 + 3 2788 2747 + 3 2747 2706 + 3 2706 2665 + 3 2665 2624 + 3 2624 2583 + 3 2583 2542 + 3 2542 2501 + 3 2501 2460 + 3 2460 2419 + 3 2419 2378 + 3 2378 2337 + 3 2337 2296 + 3 2296 2255 + 3 2255 2214 + 3 2214 2173 + 3 2173 2132 + 3 2132 2091 + 3 2091 2050 + 3 2050 2009 + 3 2009 1968 + 3 1968 1927 + 3 1927 1886 + 3 1886 1845 + 3 1845 1804 + 3 1804 1763 + 3 1763 1722 + 3 1722 1681 + 3 1681 1640 + 3 1640 1599 + 3 1599 1558 + 3 1558 1517 + 3 1517 1476 + 3 1476 1435 + 3 1435 1394 + 3 1394 1353 + 3 1353 1312 + 3 1312 1271 + 3 1271 1230 + 3 1230 1189 + 3 1189 1148 + 3 1148 1107 + 3 1107 1066 + 3 1066 1025 + 3 1025 984 + 3 984 943 + 3 943 902 + 3 902 861 + 3 861 820 + 3 820 779 + 3 779 738 + 3 738 697 + 3 697 656 + 3 656 615 + 3 615 574 + 3 574 533 + 3 533 492 + 3 492 451 + 3 451 410 + 3 410 369 + 3 369 328 + 3 328 287 + 3 287 246 + 3 246 205 + 3 205 164 + 3 164 123 + 3 123 82 + 3 82 41 + 3 41 0 +MARKER_TAG= inlet +MARKER_ELEMS= 40 + 3 11481 11480 + 3 11482 11481 + 3 11483 11482 + 3 11484 11483 + 3 11485 11484 + 3 11486 11485 + 3 11487 11486 + 3 11488 11487 + 3 11489 11488 + 3 11490 11489 + 3 11491 11490 + 3 11492 11491 + 3 11493 11492 + 3 11494 11493 + 3 11495 11494 + 3 11496 11495 + 3 11497 11496 + 3 11498 11497 + 3 11499 11498 + 3 11500 11499 + 3 11501 11500 + 3 11502 11501 + 3 11503 11502 + 3 11504 11503 + 3 11505 11504 + 3 11506 11505 + 3 11507 11506 + 3 11508 11507 + 3 11509 11508 + 3 11510 11509 + 3 11511 11510 + 3 11512 11511 + 3 11513 11512 + 3 11514 11513 + 3 11515 11514 + 3 11516 11515 + 3 11517 11516 + 3 11518 11517 + 3 11519 11518 + 3 11520 11519 +MARKER_TAG= interface +MARKER_ELEMS= 80 + 3 9840 9799 + 3 9799 9758 + 3 9758 9717 + 3 9717 9676 + 3 9676 9635 + 3 9635 9594 + 3 9594 9553 + 3 9553 9512 + 3 9512 9471 + 3 9471 9430 + 3 9430 9389 + 3 9389 9348 + 3 9348 9307 + 3 9307 9266 + 3 9266 9225 + 3 9225 9184 + 3 9184 9143 + 3 9143 9102 + 3 9102 9061 + 3 9061 9020 + 3 9020 8979 + 3 8979 8938 + 3 8938 8897 + 3 8897 8856 + 3 8856 8815 + 3 8815 8774 + 3 8774 8733 + 3 8733 8692 + 3 8692 8651 + 3 8651 8610 + 3 8610 8569 + 3 8569 8528 + 3 8528 8487 + 3 8487 8446 + 3 8446 8405 + 3 8405 8364 + 3 8364 8323 + 3 8323 8282 + 3 8282 8241 + 3 8241 8200 + 3 8200 8159 + 3 8159 8118 + 3 8118 8077 + 3 8077 8036 + 3 8036 7995 + 3 7995 7954 + 3 7954 7913 + 3 7913 7872 + 3 7872 7831 + 3 7831 7790 + 3 7790 7749 + 3 7749 7708 + 3 7708 7667 + 3 7667 7626 + 3 7626 7585 + 3 7585 7544 + 3 7544 7503 + 3 7503 7462 + 3 7462 7421 + 3 7421 7380 + 3 7380 7339 + 3 7339 7298 + 3 7298 7257 + 3 7257 7216 + 3 7216 7175 + 3 7175 7134 + 3 7134 7093 + 3 7093 7052 + 3 7052 7011 + 3 7011 6970 + 3 6970 6929 + 3 6929 6888 + 3 6888 6847 + 3 6847 6806 + 3 6806 6765 + 3 6765 6724 + 3 6724 6683 + 3 6683 6642 + 3 6642 6601 + 3 6601 6560 +MARKER_TAG= outlet +MARKER_ELEMS= 40 + 3 0 1 + 3 1 2 + 3 2 3 + 3 3 4 + 3 4 5 + 3 5 6 + 3 6 7 + 3 7 8 + 3 8 9 + 3 9 10 + 3 10 11 + 3 11 12 + 3 12 13 + 3 13 14 + 3 14 15 + 3 15 16 + 3 16 17 + 3 17 18 + 3 18 19 + 3 19 20 + 3 20 21 + 3 21 22 + 3 22 23 + 3 23 24 + 3 24 25 + 3 25 26 + 3 26 27 + 3 27 28 + 3 28 29 + 3 29 30 + 3 30 31 + 3 31 32 + 3 32 33 + 3 33 34 + 3 34 35 + 3 35 36 + 3 36 37 + 3 37 38 + 3 38 39 + 3 39 40 +MARKER_TAG= slip_bottom +MARKER_ELEMS= 40 + 3 11480 11439 + 3 11439 11398 + 3 11398 11357 + 3 11357 11316 + 3 11316 11275 + 3 11275 11234 + 3 11234 11193 + 3 11193 11152 + 3 11152 11111 + 3 11111 11070 + 3 11070 11029 + 3 11029 10988 + 3 10988 10947 + 3 10947 10906 + 3 10906 10865 + 3 10865 10824 + 3 10824 10783 + 3 10783 10742 + 3 10742 10701 + 3 10701 10660 + 3 10660 10619 + 3 10619 10578 + 3 10578 10537 + 3 10537 10496 + 3 10496 10455 + 3 10455 10414 + 3 10414 10373 + 3 10373 10332 + 3 10332 10291 + 3 10291 10250 + 3 10250 10209 + 3 10209 10168 + 3 10168 10127 + 3 10127 10086 + 3 10086 10045 + 3 10045 10004 + 3 10004 9963 + 3 9963 9922 + 3 9922 9881 + 3 9881 9840 +MARKER_TAG= top +MARKER_ELEMS= 280 + 3 40 81 + 3 81 122 + 3 122 163 + 3 163 204 + 3 204 245 + 3 245 286 + 3 286 327 + 3 327 368 + 3 368 409 + 3 409 450 + 3 450 491 + 3 491 532 + 3 532 573 + 3 573 614 + 3 614 655 + 3 655 696 + 3 696 737 + 3 737 778 + 3 778 819 + 3 819 860 + 3 860 901 + 3 901 942 + 3 942 983 + 3 983 1024 + 3 1024 1065 + 3 1065 1106 + 3 1106 1147 + 3 1147 1188 + 3 1188 1229 + 3 1229 1270 + 3 1270 1311 + 3 1311 1352 + 3 1352 1393 + 3 1393 1434 + 3 1434 1475 + 3 1475 1516 + 3 1516 1557 + 3 1557 1598 + 3 1598 1639 + 3 1639 1680 + 3 1680 1721 + 3 1721 1762 + 3 1762 1803 + 3 1803 1844 + 3 1844 1885 + 3 1885 1926 + 3 1926 1967 + 3 1967 2008 + 3 2008 2049 + 3 2049 2090 + 3 2090 2131 + 3 2131 2172 + 3 2172 2213 + 3 2213 2254 + 3 2254 2295 + 3 2295 2336 + 3 2336 2377 + 3 2377 2418 + 3 2418 2459 + 3 2459 2500 + 3 2500 2541 + 3 2541 2582 + 3 2582 2623 + 3 2623 2664 + 3 2664 2705 + 3 2705 2746 + 3 2746 2787 + 3 2787 2828 + 3 2828 2869 + 3 2869 2910 + 3 2910 2951 + 3 2951 2992 + 3 2992 3033 + 3 3033 3074 + 3 3074 3115 + 3 3115 3156 + 3 3156 3197 + 3 3197 3238 + 3 3238 3279 + 3 3279 3320 + 3 3320 3361 + 3 3361 3402 + 3 3402 3443 + 3 3443 3484 + 3 3484 3525 + 3 3525 3566 + 3 3566 3607 + 3 3607 3648 + 3 3648 3689 + 3 3689 3730 + 3 3730 3771 + 3 3771 3812 + 3 3812 3853 + 3 3853 3894 + 3 3894 3935 + 3 3935 3976 + 3 3976 4017 + 3 4017 4058 + 3 4058 4099 + 3 4099 4140 + 3 4140 4181 + 3 4181 4222 + 3 4222 4263 + 3 4263 4304 + 3 4304 4345 + 3 4345 4386 + 3 4386 4427 + 3 4427 4468 + 3 4468 4509 + 3 4509 4550 + 3 4550 4591 + 3 4591 4632 + 3 4632 4673 + 3 4673 4714 + 3 4714 4755 + 3 4755 4796 + 3 4796 4837 + 3 4837 4878 + 3 4878 4919 + 3 4919 4960 + 3 4960 5001 + 3 5001 5042 + 3 5042 5083 + 3 5083 5124 + 3 5124 5165 + 3 5165 5206 + 3 5206 5247 + 3 5247 5288 + 3 5288 5329 + 3 5329 5370 + 3 5370 5411 + 3 5411 5452 + 3 5452 5493 + 3 5493 5534 + 3 5534 5575 + 3 5575 5616 + 3 5616 5657 + 3 5657 5698 + 3 5698 5739 + 3 5739 5780 + 3 5780 5821 + 3 5821 5862 + 3 5862 5903 + 3 5903 5944 + 3 5944 5985 + 3 5985 6026 + 3 6026 6067 + 3 6067 6108 + 3 6108 6149 + 3 6149 6190 + 3 6190 6231 + 3 6231 6272 + 3 6272 6313 + 3 6313 6354 + 3 6354 6395 + 3 6395 6436 + 3 6436 6477 + 3 6477 6518 + 3 6518 6559 + 3 6559 6600 + 3 6600 6641 + 3 6641 6682 + 3 6682 6723 + 3 6723 6764 + 3 6764 6805 + 3 6805 6846 + 3 6846 6887 + 3 6887 6928 + 3 6928 6969 + 3 6969 7010 + 3 7010 7051 + 3 7051 7092 + 3 7092 7133 + 3 7133 7174 + 3 7174 7215 + 3 7215 7256 + 3 7256 7297 + 3 7297 7338 + 3 7338 7379 + 3 7379 7420 + 3 7420 7461 + 3 7461 7502 + 3 7502 7543 + 3 7543 7584 + 3 7584 7625 + 3 7625 7666 + 3 7666 7707 + 3 7707 7748 + 3 7748 7789 + 3 7789 7830 + 3 7830 7871 + 3 7871 7912 + 3 7912 7953 + 3 7953 7994 + 3 7994 8035 + 3 8035 8076 + 3 8076 8117 + 3 8117 8158 + 3 8158 8199 + 3 8199 8240 + 3 8240 8281 + 3 8281 8322 + 3 8322 8363 + 3 8363 8404 + 3 8404 8445 + 3 8445 8486 + 3 8486 8527 + 3 8527 8568 + 3 8568 8609 + 3 8609 8650 + 3 8650 8691 + 3 8691 8732 + 3 8732 8773 + 3 8773 8814 + 3 8814 8855 + 3 8855 8896 + 3 8896 8937 + 3 8937 8978 + 3 8978 9019 + 3 9019 9060 + 3 9060 9101 + 3 9101 9142 + 3 9142 9183 + 3 9183 9224 + 3 9224 9265 + 3 9265 9306 + 3 9306 9347 + 3 9347 9388 + 3 9388 9429 + 3 9429 9470 + 3 9470 9511 + 3 9511 9552 + 3 9552 9593 + 3 9593 9634 + 3 9634 9675 + 3 9675 9716 + 3 9716 9757 + 3 9757 9798 + 3 9798 9839 + 3 9839 9880 + 3 9880 9921 + 3 9921 9962 + 3 9962 10003 + 3 10003 10044 + 3 10044 10085 + 3 10085 10126 + 3 10126 10167 + 3 10167 10208 + 3 10208 10249 + 3 10249 10290 + 3 10290 10331 + 3 10331 10372 + 3 10372 10413 + 3 10413 10454 + 3 10454 10495 + 3 10495 10536 + 3 10536 10577 + 3 10577 10618 + 3 10618 10659 + 3 10659 10700 + 3 10700 10741 + 3 10741 10782 + 3 10782 10823 + 3 10823 10864 + 3 10864 10905 + 3 10905 10946 + 3 10946 10987 + 3 10987 11028 + 3 11028 11069 + 3 11069 11110 + 3 11110 11151 + 3 11151 11192 + 3 11192 11233 + 3 11233 11274 + 3 11274 11315 + 3 11315 11356 + 3 11356 11397 + 3 11397 11438 + 3 11438 11479 + 3 11479 11520 diff --git a/flow-over-heated-plate/fluid-su2/laminar_config_unsteady.cfg b/flow-over-heated-plate/fluid-su2/laminar_config_unsteady.cfg new file mode 100644 index 000000000..9838574eb --- /dev/null +++ b/flow-over-heated-plate/fluid-su2/laminar_config_unsteady.cfg @@ -0,0 +1,210 @@ +% ------------- DIRECT, ADJOINT, AND LINEARIZED PROBLEM DEFINITION ------------% +% +% Physical governing equations (EULER, NAVIER_STOKES, +% WAVE_EQUATION, HEAT_EQUATION, FEM_ELASTICITY, +% POISSON_EQUATION) +SOLVER= NAVIER_STOKES +% +% Specify turbulence model (NONE, SA, SA_NEG, SST) +KIND_TURB_MODEL= NONE +% +% Mathematical problem (DIRECT, CONTINUOUS_ADJOINT) +MATH_PROBLEM= DIRECT +% +% Restart solution (NO, YES) +RESTART_SOL= NO + +% -------------------- COMPRESSIBLE FREE-STREAM DEFINITION --------------------% +% +% Mach number (non-dimensional, based on the free-stream values) +MACH_NUMBER= 0.0003 +% +% Angle of attack (degrees, only for compressible flows) +AOA= 0.0 +% +% Side-slip angle (degrees, only for compressible flows) +SIDESLIP_ANGLE= 0.0 +% +% Free-stream temperature (288.15 K by default) +FREESTREAM_TEMPERATURE= 300 +% +% Free-stream pressure (101325.0 N/m^2, 2116.216 psf by default) +FREESTREAM_PRESSURE= 103500 +% +% Init option to choose between Reynolds (default) or thermodynamics quantities +% for initializing the solution (REYNOLDS, TD_CONDITIONS) +INIT_OPTION= TD_CONDITIONS +% +% Free-stream option to choose between density and temperature (default) for +% initializing the solution (TEMPERATURE_FS, DENSITY_FS) +FREESTREAM_OPTION= TEMPERATURE_FS +% +% Compressible flow non-dimensionalization (DIMENSIONAL, FREESTREAM_PRESS_EQ_ONE, +% FREESTREAM_VEL_EQ_MACH, FREESTREAM_VEL_EQ_ONE) +REF_DIMENSIONALIZATION= DIMENSIONAL +% +% ---- NONEQUILIBRIUM GAS, IDEAL GAS, POLYTROPIC, VAN DER WAALS AND PENG ROBINSON CONSTANTS, CoolProp library -------% +% +% Fluid model (STANDARD_AIR, IDEAL_GAS, VW_GAS, PR_GAS, +% CONSTANT_DENSITY, INC_IDEAL_GAS, INC_IDEAL_GAS_POLY, MUTATIONPP, SU2_NONEQ, FLUID_MIXTURE, COOLPROP) +FLUID_MODEL= IDEAL_GAS +% Ratio of specific heats (1.4 default and the value is hardcoded +% for the model STANDARD_AIR, compressible only) +GAMMA_VALUE= 1.0741 +% +% Specific gas constant (287.058 J/kg*K default and this value is hardcoded +% for the model STANDARD_AIR, compressible only) +GAS_CONSTANT= 345 +% +% --------------------------- VISCOSITY MODEL ---------------------------------% +% +% Viscosity model (SUTHERLAND, CONSTANT_VISCOSITY, POLYNOMIAL_VISCOSITY). +VISCOSITY_MODEL= CONSTANT_VISCOSITY +% +% Molecular Viscosity that would be constant (1.716E-5 by default) +MU_CONSTANT= 0.0002 +% --------------------------- THERMAL CONDUCTIVITY MODEL ----------------------% +% +% Laminar Conductivity model (CONSTANT_CONDUCTIVITY, CONSTANT_PRANDTL, +% POLYNOMIAL_CONDUCTIVITY). +CONDUCTIVITY_MODEL= CONSTANT_PRANDTL +% +% Laminar Prandtl number (0.72 (air), only for CONSTANT_PRANDTL) +PRANDTL_LAM= 0.01 +% ------------------------- TIME-DEPENDENT SIMULATION -------------------------------% +% +% Time domain simulation +TIME_DOMAIN= YES +% +% Unsteady simulation (NO, TIME_STEPPING, DUAL_TIME_STEPPING-1ST_ORDER, +% DUAL_TIME_STEPPING-2ND_ORDER, HARMONIC_BALANCE) +TIME_MARCHING= DUAL_TIME_STEPPING-1ST_ORDER +% +% Time Step for dual time stepping simulations (s) -- Only used when UNST_CFL_NUMBER = 0.0 +% For the DG-FEM solver it is used as a synchronization time when UNST_CFL_NUMBER != 0.0 +TIME_STEP= 0.01 +% +MAX_TIME= 1.0 +% +% Number of internal iterations (dual time method) +INNER_ITER= 1000 +% +% Inner iter convergence +CONV_FIELD= REL_RMS_DENSITY +CONV_RESIDUAL_MINVAL= -3 +CONV_STARTITER= 0 +% +% Time discretization (RUNGE-KUTTA_EXPLICIT, EULER_IMPLICIT, EULER_EXPLICIT) +% This is used for the inner iterations of dual time-stepping +TIME_DISCRE_FLOW= EULER_IMPLICIT +% +% ----------------------- BODY FORCE DEFINITION -------------------------------% +% +% Apply a body force as a source term (NO, YES) +BODY_FORCE= YES +% +% Vector of body force values (BodyForce_X, BodyForce_Y, BodyForce_Z) +BODY_FORCE_VECTOR= ( 0.0, -9.81, 0.0 ) +% -------------------- BOUNDARY CONDITION DEFINITION --------------------------% +% +MARKER_FAR= (inlet, outlet) +% +MARKER_HEATFLUX= (bottom, 0, interface, 0) +% +MARKER_SYM= (slip_bottom, top) +% +% Marker(s) of the surface where custom thermal BCs are defined. +MARKER_PYTHON_CUSTOM = ( interface ) +% +% ------------- COMMON PARAMETERS DEFINING THE NUMERICAL METHOD ---------------% +% +% Numerical method for spatial gradients (GREEN_GAUSS, WEIGHTED_LEAST_SQUARES) +NUM_METHOD_GRAD= WEIGHTED_LEAST_SQUARES +% +% Courant-Friedrichs-Lewy condition of the finest grid +% Important for inner iterations +CFL_NUMBER= 1000.0 +% +% Adaptive CFL number (NO, YES) +CFL_ADAPT= YES +% +% Parameters of the adaptive CFL number (factor down, factor up, CFL min value, +% CFL max value ) +CFL_ADAPT_PARAM= ( 0.1, 10, 1.0, 10000.0 ) +% +% Number of total iterations +TIME_ITER= 99999 +% ------------------------ LINEAR SOLVER DEFINITION ---------------------------% +% +% Linear solver for implicit formulations (BCGSTAB, FGMRES) +LINEAR_SOLVER= FGMRES +% +% Preconditioner of the Krylov linear solver (JACOBI, LINELET, LU_SGS) +LINEAR_SOLVER_PREC= ILU +% +% Minimum error of the linear solver for implicit formulations +LINEAR_SOLVER_ERROR= 1E-6 +% +% Max number of iterations of the linear solver for the implicit formulation +LINEAR_SOLVER_ITER= 10 + +% -------------------- FLOW NUMERICAL METHOD DEFINITION -----------------------% +% +% Convective numerical method (JST, LAX-FRIEDRICH, CUSP, ROE, AUSM, HLLC, +% TURKEL_PREC, MSW) +CONV_NUM_METHOD_FLOW= ROE +% +% Monotonic Upwind Scheme for Conservation Laws (TVD) in the flow equations. +% Required for 2nd order upwind schemes (NO, YES) +MUSCL_FLOW= YES +% +% Slope limiter (NONE, VENKATAKRISHNAN, VENKATAKRISHNAN_WANG, +% BARTH_JESPERSEN, VAN_ALBADA_EDGE) +SLOPE_LIMITER_FLOW= NONE +% +% Coefficient for the limiter (smooth regions) +VENKAT_LIMITER_COEFF= 0.05 +% +% 2nd and 4th order artificial dissipation coefficients +JST_SENSOR_COEFF= ( 0.5, 0.02 ) +% +% +% ------------------------- SCREEN/HISTORY VOLUME OUTPUT --------------------------% +% Screen output fields (use 'SU2_CFD -d ' to view list of available fields) +SCREEN_OUTPUT= (CUR_TIME, INNER_ITER, REL_RMS_DENSITY, RMS_DENSITY, RMS_ENERGY) +% +% History output groups (use 'SU2_CFD -d ' to view list of available fields) +HISTORY_OUTPUT= (ITER, RMS_RES) +% +% Volume output fields/groups (use 'SU2_CFD -d ' to view list of available fields) +VOLUME_OUTPUT= (COORDINATES, SOLUTION, PRIMITIVE) +% +% +% ------------------------- INPUT/OUTPUT INFORMATION --------------------------% +% Mesh input file +MESH_FILENAME= fluid_mesh.su2 +% +% Mesh input file format (SU2, CGNS, NETCDF_ASCII) +MESH_FORMAT= SU2 +% +% Restart flow input file +% SOLUTION_FILENAME= restart_flow.dat +% +% Files to output +% Possible formats : (TECPLOT_ASCII, TECPLOT, SURFACE_TECPLOT_ASCII, +% SURFACE_TECPLOT, CSV, SURFACE_CSV, PARAVIEW_ASCII, PARAVIEW_LEGACY, SURFACE_PARAVIEW_ASCII, +% SURFACE_PARAVIEW_LEGACY, PARAVIEW, SURFACE_PARAVIEW, RESTART_ASCII, RESTART, CGNS, SURFACE_CGNS, STL_ASCII, STL_BINARY) +% default : (RESTART, PARAVIEW, SURFACE_PARAVIEW) +OUTPUT_FILES= (PARAVIEW) +% +OUTPUT_WRT_FREQ= (5) +% +% Output file restart flow +RESTART_FILENAME= restart_flow.dat +% +% Output file convergence history (w/o extension) +CONV_FILENAME= history +% +% Output file flow (w/o extension) variables +VOLUME_FILENAME= flow + diff --git a/flow-over-heated-plate/fluid-su2/run.sh b/flow-over-heated-plate/fluid-su2/run.sh new file mode 100755 index 000000000..0e85e879a --- /dev/null +++ b/flow-over-heated-plate/fluid-su2/run.sh @@ -0,0 +1,4 @@ +#!/bin/sh +set -e -u + +SU2_preCICE_CHT.py -f laminar_config_unsteady.cfg -r --parallel \ No newline at end of file diff --git a/flow-over-heated-plate/images/tutorials-flow-over-heated-plate-precice-config.png b/flow-over-heated-plate/images/tutorials-flow-over-heated-plate-precice-config.png new file mode 100644 index 000000000..7c5570750 Binary files /dev/null and b/flow-over-heated-plate/images/tutorials-flow-over-heated-plate-precice-config.png differ diff --git a/flow-over-heated-plate/images/tutorials-flow-over-heated-plate-results-comparison.png b/flow-over-heated-plate/images/tutorials-flow-over-heated-plate-results-comparison.png index 4d3c6f487..580a654aa 100644 Binary files a/flow-over-heated-plate/images/tutorials-flow-over-heated-plate-results-comparison.png and b/flow-over-heated-plate/images/tutorials-flow-over-heated-plate-results-comparison.png differ diff --git a/flow-over-heated-plate/metadata.yaml b/flow-over-heated-plate/metadata.yaml new file mode 100644 index 000000000..0fea0d842 --- /dev/null +++ b/flow-over-heated-plate/metadata.yaml @@ -0,0 +1,35 @@ +name: Flow over heated plate +path: flow-over-heated-plate # relative to git repo +url: https://precice.org/tutorials-flow-over-heated-plate.html + +participants: + - Fluid + - Solid + +cases: + fluid-openfoam: + participant: Fluid + directory: ./fluid-openfoam + run: ./run.sh + component: openfoam-adapter + + 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 + run: ./run.sh + component: openfoam-adapter + + + diff --git a/flow-over-heated-plate/plot-final-interface-temperature.py b/flow-over-heated-plate/plot-final-interface-temperature.py index ffe5e424e..9a767b020 100644 --- a/flow-over-heated-plate/plot-final-interface-temperature.py +++ b/flow-over-heated-plate/plot-final-interface-temperature.py @@ -4,7 +4,7 @@ def vtk_to_dict(case): - vtkFileName = "solid-{}/preCICE-output/Fluid-Mesh-Solid.final.vtk".format(case) + vtkFileName = "solid-{}/precice-exports/Fluid-Mesh-Solid.dt100.vtk".format(case) # read the vtk file as an unstructured grid reader = vtk.vtkUnstructuredGridReader() reader.SetFileName(vtkFileName) @@ -23,7 +23,7 @@ def vtk_to_dict(case): while i < max_i: this_data_name = data.GetPointData().GetArray(i).GetName() data_names.append(this_data_name) - if(this_data_name == name): + if (this_data_name == name): data_id = i break i += 1 @@ -44,8 +44,13 @@ def vtk_to_dict(case): cases.append('fenics') cases.append('openfoam') cases.append('nutils') +cases.append('dunefem') -case_labels = {'fenics': 'OpenFOAM-FEniCS', 'openfoam': 'OpenFOAM-OpenFOAM', 'nutils': 'OpenFOAM-Nutils', } +case_labels = { + 'fenics': 'OpenFOAM-FEniCS', + 'openfoam': 'OpenFOAM-OpenFOAM', + 'nutils': 'OpenFOAM-Nutils', + 'dunefem': 'OpenFOAM-DuneFem'} styles = [':', '-', '--'] colors = ['r', 'b', 'g', 'k'] i = 0 diff --git a/flow-over-heated-plate/precice-config.xml b/flow-over-heated-plate/precice-config.xml index 9c1337449..d33823c58 100644 --- a/flow-over-heated-plate/precice-config.xml +++ b/flow-over-heated-plate/precice-config.xml @@ -1,4 +1,4 @@ - + - - - + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + 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 new file mode 100644 index 000000000..bf6102a64 --- /dev/null +++ b/flow-over-heated-plate/reference-results/fluid-openfoam_solid-fenics.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:656007eaa973f35c421a3b9ec340a06145fd065041e33f10efe023ab127a4552 +size 775369 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 new file mode 100644 index 000000000..d0f560a2f --- /dev/null +++ b/flow-over-heated-plate/reference-results/fluid-openfoam_solid-nutils.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:13557384af972d30f6b6d7fcf07429b2d99a463d1e9358d19ea72665fd06279e +size 531446 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 new file mode 100644 index 000000000..ca97ab96c --- /dev/null +++ b/flow-over-heated-plate/reference-results/fluid-openfoam_solid-openfoam.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da907862142542501da920b8dde9d81cc53e947bd72dc59a8df59dc8e3b28348 +size 497746 diff --git a/flow-over-heated-plate/reference_results.metadata b/flow-over-heated-plate/reference_results.metadata new file mode 100644 index 000000000..462a5b878 --- /dev/null +++ b/flow-over-heated-plate/reference_results.metadata @@ -0,0 +1,65 @@ + + +# 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-nutils.tar.gz | 2024-04-13 12:00:34 | 13557384af972d30f6b6d7fcf07429b2d99a463d1e9358d19ea72665fd06279e | +| fluid-openfoam_solid-openfoam.tar.gz | 2024-04-13 12:00:34 | da907862142542501da920b8dde9d81cc53e947bd72dc59a8df59dc8e3b28348 | +| fluid-openfoam_solid-fenics.tar.gz | 2024-04-13 12:00:34 | 656007eaa973f35c421a3b9ec340a06145fd065041e33f10efe023ab127a4552 | + +## List of arguments used to generate the files + +| name | value | +|------|------| +| PRECICE_REF | v3.1.1 | +| OPENFOAM_EXECUTABLE | openfoam2312 | +| OPENFOAM_ADAPTER_REF | v1.3.0 | +| PYTHON_BINDINGS_REF | v3.1.0 | +| FENICS_ADAPTER_REF | v2.1.0 | +| TUTORIALS_REF | 340b447 | +| PLATFORM | ubuntu_2204 | +| CALULIX_VERSION | 2.20 | +| CALULIX_ADAPTER_REF | v2.20.1 | +| SU2_VERSION | 7.5.1 | +| SU2_ADAPTER_REF | 64d4aff | +## Information about the machine + +### uname -a + +Linux precice-tests 5.15.0-101-generic #111-Ubuntu SMP Tue Mar 5 20:16:58 UTC 2024 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/solid-dunefem/.gitignore b/flow-over-heated-plate/solid-dunefem/.gitignore new file mode 100644 index 000000000..1f72138b1 --- /dev/null +++ b/flow-over-heated-plate/solid-dunefem/.gitignore @@ -0,0 +1 @@ +dune-env/ diff --git a/flow-over-heated-plate/solid-dunefem/requirements.txt b/flow-over-heated-plate/solid-dunefem/requirements.txt new file mode 100644 index 000000000..b0b7bdf42 --- /dev/null +++ b/flow-over-heated-plate/solid-dunefem/requirements.txt @@ -0,0 +1,2 @@ +dune-fem>=2.8 +pyprecice==3 diff --git a/flow-over-heated-plate/solid-dunefem/run.sh b/flow-over-heated-plate/solid-dunefem/run.sh index 21bd5c3b1..125686c9e 100755 --- a/flow-over-heated-plate/solid-dunefem/run.sh +++ b/flow-over-heated-plate/solid-dunefem/run.sh @@ -1,5 +1,12 @@ #!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 -m venv .venv +. .venv/bin/activate +pip install -r requirements.txt python3 solid.py +close_log diff --git a/flow-over-heated-plate/solid-dunefem/solid.py b/flow-over-heated-plate/solid-dunefem/solid.py index 24ee12c16..fc56c4e5b 100644 --- a/flow-over-heated-plate/solid-dunefem/solid.py +++ b/flow-over-heated-plate/solid-dunefem/solid.py @@ -12,7 +12,7 @@ from dune.fem.operator import galerkin from dune.fem.utility import Sampler from dune.grid import cartesianDomain -from dune.alugrid import aluSimplexGrid +from dune.alugrid import aluGrid from dune.fem.function import uflFunction, gridFunction from dune.ufl import expression2GF @@ -32,19 +32,18 @@ x_right = x_left + 1 # preCICE setup - interface = precice.Interface("Solid", "../precice-config.xml", 0, 1) + participant = precice.Participant("Solid", "../precice-config.xml", 0, 1) # define coupling mesh mesh_name = "Solid-Mesh" - mesh_id = interface.get_mesh_id(mesh_name) - interface_x_coordinates = np.linspace(0, 1, nx + 1) # meshpoints for interface values + interface_x_coordinates = np.linspace( + 0, 1, nx + 1) # meshpoints for interface values vertices = [[x0, 0] for x0 in interface_x_coordinates] - vertex_ids = interface.set_mesh_vertices(mesh_id, vertices) - temperature_id = interface.get_data_id("Temperature", mesh_id) - flux_id = interface.get_data_id("Heat-Flux", mesh_id) + + vertex_ids = participant.set_mesh_vertices(mesh_name, vertices) domain = cartesianDomain([x_left, y_bottom], [x_right, y_top], [nx, ny]) - mesh = aluSimplexGrid(domain, serial=True) + mesh = aluGrid(domain, 2, 2, elementType="simplex") # create a simple mesh with dimGrid=2 and dimWorld=2 space = solutionSpace(mesh, order=1) u = ufl.TrialFunction(space) v = ufl.TestFunction(space) @@ -80,32 +79,36 @@ def u_gamma(xg): scheme = solutionScheme([A == b, *bcs], solver='cg') # Weak form of the flux - flux_expr = -(u - uold) * v / dt * ufl.dx - k * ufl.dot(ufl.grad(u), ufl.grad(v)) * ufl.dx + flux_expr = -(u - uold) * v / dt * ufl.dx - k * \ + ufl.dot(ufl.grad(u), ufl.grad(v)) * ufl.dx flux_expr_operator = galerkin(flux_expr) flux_sol = space.interpolate(u0, name='flux_sol') # Sample the flux on the top edge - flux_sol_expr = expression2GF(flux_sol.space.grid, flux_sol, flux_sol.space.order) + flux_sol_expr = expression2GF( + flux_sol.space.grid, flux_sol, flux_sol.space.order) sampler_weak_flux = Sampler(flux_sol_expr) - def flux_f_weak(): return sampler_weak_flux.lineSample([0., 0.], [1., 0.], nx + 1)[1] * nx + + def flux_f_weak(): return sampler_weak_flux.lineSample( + [0., 0.], [1., 0.], nx + 1)[1] * nx if not os.path.exists("output"): os.makedirs("output") vtk = mesh.sequencedVTK("output/heat", pointdata=[unew]) - precice_dt = interface.initialize() + participant.initialize() + precice_dt = participant.get_max_time_step_size() dt.assign(min(float(dt), precice_dt)) t = float(dt) - while interface.is_coupling_ongoing(): + while participant.is_coupling_ongoing(): - if interface.is_action_required(precice.action_write_iteration_checkpoint()): # write checkpoint + # write checkpoint + if participant.requires_writing_checkpoint(): t_check = t ucheckpoint.assign(uold) - interface.mark_action_fulfilled(precice.action_write_iteration_checkpoint()) - - ug = interface.read_block_scalar_data(temperature_id, vertex_ids) + ug = participant.read_data(mesh_name, "Temperature", vertex_ids, dt) ug_interp.y = ug scheme.model.dt = dt @@ -115,25 +118,27 @@ def flux_f_weak(): return sampler_weak_flux.lineSample([0., 0.], [1., 0.], nx + flux_expr_operator(unew, flux_sol) flux_values = flux_f_weak() # sample the flux function - interface.write_block_scalar_data(flux_id, vertex_ids, flux_values) + participant.write_data(mesh_name, "Heat-Flux", vertex_ids, flux_values) - precice_dt = interface.advance(dt) + participant.advance(dt) + precice_dt = participant.get_max_time_step_size() dt.assign(min(float(dt), precice_dt)) - if interface.is_action_required(precice.action_read_iteration_checkpoint()): # roll back to checkpoint + # roll back to checkpoint + if participant.requires_reading_checkpoint(): t = t_check uold.assign(ucheckpoint) - interface.mark_action_fulfilled(precice.action_read_iteration_checkpoint()) else: # update solution uold.assign(unew) t += float(dt) - if interface.is_time_window_complete(): - tol = 10e-5 # we need some tolerance, since otherwise output might be skipped. + if participant.is_time_window_complete(): + # we need some tolerance, since otherwise output might be skipped. + tol = 10e-5 if abs((t + tol) % dt_out) < 2 * tol: # output if t is a multiple of dt_out print("output vtk for time = {}".format(float(t))) vtk() - interface.finalize() + participant.finalize() diff --git a/flow-over-heated-plate/solid-fenics/run.sh b/flow-over-heated-plate/solid-fenics/run.sh index 15315c67d..6d5da4496 100755 --- a/flow-over-heated-plate/solid-fenics/run.sh +++ b/flow-over-heated-plate/solid-fenics/run.sh @@ -1,4 +1,9 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + python3 solid.py + +close_log diff --git a/flow-over-heated-plate/solid-fenics/solid.py b/flow-over-heated-plate/solid-fenics/solid.py index 23ee3bbd4..f07cc29d5 100644 --- a/flow-over-heated-plate/solid-fenics/solid.py +++ b/flow-over-heated-plate/solid-fenics/solid.py @@ -115,13 +115,14 @@ def determine_heat_flux(V_g, u, k, flux): # Adapter definition and initialization precice = Adapter(adapter_config_filename="precice-adapter-config.json") -precice_dt = precice.initialize(coupling_boundary, read_function_space=V, write_object=V_flux_y) +precice.initialize(coupling_boundary, read_function_space=V, write_object=V_flux_y) # Create a FEniCS Expression to define and control the coupling boundary values coupling_expression = precice.create_coupling_expression() # Assigning appropriate dt dt = Constant(0) +precice_dt = precice.get_max_time_step_size() dt.assign(np.min([fenics_dt, precice_dt])) # Define variational problem @@ -149,7 +150,7 @@ def determine_heat_flux(V_g, u, k, flux): # Create output file file_out = File("output/%s.pvd" % precice.get_participant_name()) -file_out << u_n +file_out << (u_n, t) print("output vtk for time = {}".format(float(t))) n = 0 @@ -159,16 +160,16 @@ def determine_heat_flux(V_g, u, k, flux): while precice.is_coupling_ongoing(): - if precice.is_action_required(precice.action_write_iteration_checkpoint()): # write checkpoint + if precice.requires_writing_checkpoint(): # write checkpoint precice.store_checkpoint(u_n, t, n) - read_data = precice.read_data() + precice_dt = precice.get_max_time_step_size() + dt.assign(np.min([fenics_dt, precice_dt])) + read_data = precice.read_data(dt) # Update the coupling expression with the new read data precice.update_coupling_expression(coupling_expression, read_data) - dt.assign(np.min([fenics_dt, precice_dt])) - # Compute solution solve(a == L, u_np1, bcs) @@ -177,9 +178,9 @@ def determine_heat_flux(V_g, u, k, flux): fluxes_y = fluxes.sub(1) # only exchange y component of flux. precice.write_data(fluxes_y) - precice_dt = precice.advance(dt(0)) + precice.advance(dt(0)) - if precice.is_action_required(precice.action_read_iteration_checkpoint()): # roll back to checkpoint + if precice.requires_reading_checkpoint(): # roll back to checkpoint u_cp, t_cp, n_cp = precice.retrieve_checkpoint() u_n.assign(u_cp) t = t_cp @@ -193,7 +194,7 @@ def determine_heat_flux(V_g, u, k, flux): tol = 10e-5 # we need some tolerance, since otherwise output might be skipped. if abs((t + tol) % dt_out) < 2 * tol: # output if t is a multiple of dt_out print("output vtk for time = {}".format(float(t))) - file_out << u_n + file_out << (u_n, t) # Update dirichlet BC u_D.t = t + float(dt) diff --git a/flow-over-heated-plate/solid-nutils/requirements.txt b/flow-over-heated-plate/solid-nutils/requirements.txt new file mode 100644 index 000000000..cfd521c81 --- /dev/null +++ b/flow-over-heated-plate/solid-nutils/requirements.txt @@ -0,0 +1,2 @@ +nutils==7 +pyprecice==3 diff --git a/flow-over-heated-plate/solid-nutils/run.sh b/flow-over-heated-plate/solid-nutils/run.sh index 21bd5c3b1..125686c9e 100755 --- a/flow-over-heated-plate/solid-nutils/run.sh +++ b/flow-over-heated-plate/solid-nutils/run.sh @@ -1,5 +1,12 @@ #!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 -m venv .venv +. .venv/bin/activate +pip install -r requirements.txt python3 solid.py +close_log diff --git a/flow-over-heated-plate/solid-nutils/solid.py b/flow-over-heated-plate/solid-nutils/solid.py index 32f5d95e9..37bdb4b75 100644 --- a/flow-over-heated-plate/solid-nutils/solid.py +++ b/flow-over-heated-plate/solid-nutils/solid.py @@ -34,19 +34,14 @@ def main(): cons = solver.optimize('lhs', sqr, droptol=1e-15) # preCICE setup - interface = precice.Interface("Solid", "../precice-config.xml", 0, 1) + participant = precice.Participant("Solid", "../precice-config.xml", 0, 1) # define coupling mesh mesh_name = "Solid-Mesh" - mesh_id = interface.get_mesh_id(mesh_name) coupling_boundary = domain.boundary['top'] coupling_sample = coupling_boundary.sample('gauss', degree=2) # mesh vertices at Gauss points vertices = coupling_sample.eval(ns.x) - vertex_ids = interface.set_mesh_vertices(mesh_id, vertices) - - # coupling data - flux_id = interface.get_data_id("Heat-Flux", mesh_id) - temperature_id = interface.get_data_id("Temperature", mesh_id) + vertex_ids = participant.set_mesh_vertices(mesh_name, vertices) # helper functions to project heat flux to coupling boundary projection_matrix = coupling_boundary.integrate(ns.eval_nm('basis_n basis_m d:x'), degree=2) @@ -54,12 +49,15 @@ def main(): projection_cons[projection_matrix.rowsupp(1e-15)] = np.nan def fluxdofs(v): return projection_matrix.solve(v, constrain=projection_cons) - precice_dt = interface.initialize() - cons0 = cons # to not lose the Dirichlet BC at the bottom lhs0 = np.zeros(res.shape) # solution from previous timestep timestep = 0 - dt = 0.01 + solver_dt = 0.01 + + participant.initialize() + + precice_dt = participant.get_max_time_step_size() + dt = min(precice_dt, solver_dt) # set u = uwall as initial condition and visualize sqr = domain.integral('(u - uwall)^2' @ ns, degree=2) @@ -69,46 +67,43 @@ def fluxdofs(v): return projection_matrix.solve(v, constrain=projection_cons) with treelog.add(treelog.DataLog()): export.vtk('Solid_0', bezier.tri, x, T=u) - while interface.is_coupling_ongoing(): - - # read temperature from interface - if interface.is_read_data_available(): - temperature_values = interface.read_block_scalar_data(temperature_id, vertex_ids) - temperature_function = coupling_sample.asfunction(temperature_values) - - sqr = coupling_sample.integral((ns.u - temperature_function)**2) - cons = solver.optimize('lhs', sqr, droptol=1e-15, constrain=cons0) + while participant.is_coupling_ongoing(): # save checkpoint - if interface.is_action_required(precice.action_write_iteration_checkpoint()): + if participant.requires_writing_checkpoint(): lhs_checkpoint = lhs0 timestep_checkpoint = timestep - interface.mark_action_fulfilled(precice.action_write_iteration_checkpoint()) # potentially adjust non-matching timestep sizes - dt = min(dt, precice_dt) + precice_dt = participant.get_max_time_step_size() + dt = min(solver_dt, precice_dt) + + # read temperature from participant + temperature_values = participant.read_data(mesh_name, "Temperature", vertex_ids, dt) + temperature_function = coupling_sample.asfunction(temperature_values) + + sqr = coupling_sample.integral((ns.u - temperature_function)**2) + cons = solver.optimize('lhs', sqr, droptol=1e-15, constrain=cons0) # solve nutils timestep lhs = solver.solve_linear('lhs', res, constrain=cons, arguments=dict(lhs0=lhs0, dt=dt)) - # write heat fluxes to interface - if interface.is_write_data_required(dt): - flux_function = res.eval(lhs0=lhs0, lhs=lhs, dt=dt) - flux_values = coupling_sample.eval('-flux' @ ns, fluxdofs=fluxdofs(flux_function)) - interface.write_block_scalar_data(flux_id, vertex_ids, flux_values) + # write heat fluxes to participant + flux_function = res.eval(lhs0=lhs0, lhs=lhs, dt=dt) + flux_values = coupling_sample.eval('-flux' @ ns, fluxdofs=fluxdofs(flux_function)) + participant.write_data(mesh_name, "Heat-Flux", vertex_ids, flux_values) # do the coupling - precice_dt = interface.advance(dt) + participant.advance(dt) # advance variables timestep += 1 lhs0 = lhs # read checkpoint if required - if interface.is_action_required(precice.action_read_iteration_checkpoint()): + if participant.requires_reading_checkpoint(): lhs0 = lhs_checkpoint timestep = timestep_checkpoint - interface.mark_action_fulfilled(precice.action_read_iteration_checkpoint()) else: # go to next timestep if timestep % 20 == 0: # visualize bezier = domain.sample('bezier', 2) @@ -116,7 +111,7 @@ def fluxdofs(v): return projection_matrix.solve(v, constrain=projection_cons) with treelog.add(treelog.DataLog()): export.vtk('Solid_' + str(timestep), bezier.tri, x, T=u) - interface.finalize() + participant.finalize() if __name__ == '__main__': diff --git a/flow-over-heated-plate/solid-openfoam/run.sh b/flow-over-heated-plate/solid-openfoam/run.sh index 57e9395ee..da82a9ba2 100755 --- a/flow-over-heated-plate/solid-openfoam/run.sh +++ b/flow-over-heated-plate/solid-openfoam/run.sh @@ -1,8 +1,12 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + blockMesh -touch solid-openfoam.foam ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/heat-exchanger-simplified/README.md b/heat-exchanger-simplified/README.md new file mode 100644 index 000000000..c05905632 --- /dev/null +++ b/heat-exchanger-simplified/README.md @@ -0,0 +1,70 @@ +--- +title: Heat exchanger (simplified) +permalink: tutorials-heat-exchanger-simplified.html +keywords: tutorial, CHT, conjugate-heat transfer, OpenFOAM, CalculiX, multi-coupling +summary: This tutorial describes how to run a conjugate heat transfer simulation with three participants, with CalculiX as solid solver and Dirichlet-Neumann coupling. +--- + + +{% note %} +Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/heat-exchanger-simplified). Read how in the [tutorials introduction](https://www.precice.org/tutorials.html). +{% endnote %} + +## Setup + +This tutorial extends the [flow over heated plate: Two meshes](https://precice.org/tutorials-flow-over-heated-plate-two-meshes.html) tutorial, adding another channel flow below the plate. The plate is not heated in this scenario, but is acting as a conducting material for the two fluids, serving as a simplified heat exchanger example. + +Contrary to the [heat exchanger](https://precice.org/tutorials-heat-exchanger.html) tutorial, which defines Robin-Robin coupling, this case defines a Dirichlet-Neumann coupling, exchanging temperature (from the fluids to the solid) and heat flux (from the solid to the fluids). Additionally, instead of composing two explicit coupling schemes, this tutorial uses a fully-implicit multi-coupling scheme and is transient. + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-heat-exchanger-simplified-precice-config.png) + +## Available solvers + +Fluid participants: + +* OpenFOAM (buoyantPimpleFoam). For more information, have a look at the [OpenFOAM adapter documentation](https://www.precice.org/adapter-openfoam-overview.html). + +Solid participant: + +* CalculiX. For more information, have a look at the [CalculiX adapter documentation](https://precice.org/adapter-calculix-overview.html). Be sure to use at least version 2.19.1 of the adapter. + +## Running the Simulation + +Open two separate terminals and start the desired fluid and solid participant by calling the respective run script `run.sh` located in the participant directory. For example: + +```bash +cd fluid-top-openfoam +./run.sh +``` + +and + +```bash +cd fluid-bottom-openfoam +./run.sh +``` + +to run the fluid participants, as well as + +```bash +cd solid-calculix +./run.sh +``` + +to run the solid participant (which is also controlling the coupling). + +## Post-processing + +Similarly to the [flow over heated plate: Two meshes](https://precice.org/tutorials-flow-over-heated-plate-two-meshes.html) tutorial. + +![Results of the simplified heat exchanger tutorial](images/tutorials-heat-exchanger-simplified-overview.png) + +![Animation of the simplified heat exchanger tutorial](images/tutorials-heat-exchanger-simplified-animation.webp) + +{% disclaimer %} +This offering is not approved or endorsed by OpenCFD Limited, producer and distributor of the OpenFOAM software via www.openfoam.com, and owner of the OPENFOAM® and OpenCFD® trade marks. +{% enddisclaimer %} diff --git a/heat-exchanger-simplified/clean-tutorial.sh b/heat-exchanger-simplified/clean-tutorial.sh new file mode 120000 index 000000000..4713f5092 --- /dev/null +++ b/heat-exchanger-simplified/clean-tutorial.sh @@ -0,0 +1 @@ +../tools/clean-tutorial-base.sh \ No newline at end of file diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/0/T b/heat-exchanger-simplified/fluid-bottom-openfoam/0/T new file mode 100644 index 000000000..52e34ddd4 --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/0/T @@ -0,0 +1,49 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} + +dimensions [ 0 0 0 1 0 0 0 ]; + +internalField uniform 310; + +boundaryField +{ + interface + { + type fixedGradient; + gradient uniform 0; + } + inlet + { + type fixedValue; + value $internalField; + } + outlet + { + type zeroGradient; + } + top + { + type zeroGradient; + } + bottom + { + type zeroGradient; + } + slip-bottom + { + type zeroGradient; + } + outerWall + { + type zeroGradient; + } + defaultFaces + { + type empty; + } +} diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/0/U b/heat-exchanger-simplified/fluid-bottom-openfoam/0/U new file mode 100644 index 000000000..cfe775cf3 --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/0/U @@ -0,0 +1,44 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} + +dimensions [ 0 1 -1 0 0 0 0 ]; + +internalField uniform ( 0.1 0 0 ); + +boundaryField +{ + interface + { + type noSlip; + } + inlet + { + type fixedValue; + value $internalField; + } + outlet + { + type zeroGradient; + } + top + { + type slip; + } + bottom + { + type noSlip; + } + slip-bottom + { + type slip; + } + defaultFaces + { + type empty; + } +} diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/0/alphat b/heat-exchanger-simplified/fluid-bottom-openfoam/0/alphat new file mode 100644 index 000000000..1d3ac72d0 --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/0/alphat @@ -0,0 +1,49 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object alphat; +} + +dimensions [ 1 -1 -1 0 0 0 0 ]; + +internalField uniform 0; + +boundaryField +{ + interface + { + type compressible::alphatWallFunction; + value uniform 0; + } + inlet + { + type compressible::alphatWallFunction; + value uniform 0; + } + outlet + { + type compressible::alphatWallFunction; + value uniform 0; + } + top + { + type compressible::alphatWallFunction; + value uniform 0; + } + bottom + { + type compressible::alphatWallFunction; + value uniform 0; + } + slip-bottom + { + type compressible::alphatWallFunction; + value uniform 0; + } + defaultFaces + { + type empty; + } +} diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/0/epsilon b/heat-exchanger-simplified/fluid-bottom-openfoam/0/epsilon new file mode 100644 index 000000000..c419576fc --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/0/epsilon @@ -0,0 +1,49 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object epsilon; +} + +dimensions [ 0 2 -3 0 0 0 0 ]; + +internalField uniform 0.01; + +boundaryField +{ + interface + { + type epsilonWallFunction; + value uniform 0.01; + } + inlet + { + type epsilonWallFunction; + value uniform 0.01; + } + outlet + { + type epsilonWallFunction; + value uniform 0.01; + } + top + { + type epsilonWallFunction; + value uniform 0.01; + } + bottom + { + type epsilonWallFunction; + value uniform 0.01; + } + slip-bottom + { + type epsilonWallFunction; + value uniform 0.01; + } + defaultFaces + { + type empty; + } +} diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/0/k b/heat-exchanger-simplified/fluid-bottom-openfoam/0/k new file mode 100644 index 000000000..a09c9617c --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/0/k @@ -0,0 +1,49 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object k; +} + +dimensions [ 0 2 -2 0 0 0 0 ]; + +internalField uniform 0.1; + +boundaryField +{ + interface + { + type kqRWallFunction; + value uniform 0.1; + } + inlet + { + type kqRWallFunction; + value uniform 0.1; + } + outlet + { + type kqRWallFunction; + value uniform 0.1; + } + top + { + type kqRWallFunction; + value uniform 0.1; + } + slip-bottom + { + type kqRWallFunction; + value uniform 0.1; + } + bottom + { + type kqRWallFunction; + value uniform 0.1; + } + defaultFaces + { + type empty; + } +} diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/0/nut b/heat-exchanger-simplified/fluid-bottom-openfoam/0/nut new file mode 100644 index 000000000..580e908d7 --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/0/nut @@ -0,0 +1,49 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object nut; +} + +dimensions [ 0 2 -1 0 0 0 0 ]; + +internalField uniform 0; + +boundaryField +{ + interface + { + type nutkWallFunction; + value uniform 0; + } + inlet + { + type nutkWallFunction; + value uniform 0; + } + outlet + { + type nutkWallFunction; + value uniform 0; + } + top + { + type nutkWallFunction; + value uniform 0; + } + bottom + { + type nutkWallFunction; + value uniform 0; + } + slip-bottom + { + type nutkWallFunction; + value uniform 0; + } + defaultFaces + { + type empty; + } +} diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/0/p b/heat-exchanger-simplified/fluid-bottom-openfoam/0/p new file mode 100644 index 000000000..654bb4023 --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/0/p @@ -0,0 +1,54 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p; +} + +dimensions [ 1 -1 -2 0 0 0 0 ]; + +internalField uniform 103500; + +boundaryField +{ + interface + { + type calculated; + value $internalField; + } + inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + outerWall + { + type calculated; + value $internalField; + } + top + { + type calculated; + value $internalField; + } + bottom + { + type calculated; + value $internalField; + } + slip-bottom + { + type calculated; + value $internalField; + } + defaultFaces + { + type empty; + } +} diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/0/p_rgh b/heat-exchanger-simplified/fluid-bottom-openfoam/0/p_rgh new file mode 100644 index 000000000..c5eebe883 --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/0/p_rgh @@ -0,0 +1,44 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p_rgh; +} + +dimensions [ 1 -1 -2 0 0 0 0 ]; + +internalField uniform 103500; + +boundaryField +{ + interface + { + type zeroGradient; + } + inlet + { + type zeroGradient; + } + outlet + { + type fixedValue; + value $internalField; + } + top + { + type zeroGradient; + } + slip-bottom + { + type zeroGradient; + } + bottom + { + type zeroGradient; + } + defaultFaces + { + type empty; + } +} diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/clean.sh b/heat-exchanger-simplified/fluid-bottom-openfoam/clean.sh new file mode 100755 index 000000000..c31d9fc76 --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/constant/g b/heat-exchanger-simplified/fluid-bottom-openfoam/constant/g new file mode 100644 index 000000000..ca544e1f1 --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/constant/g @@ -0,0 +1,10 @@ +FoamFile +{ + version 2.0; + format ascii; + class uniformDimensionedVectorField; + object g; +} + +dimensions [0 1 -2 0 0 0 0]; +value (0 -9.81 0); diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/constant/thermophysicalProperties b/heat-exchanger-simplified/fluid-bottom-openfoam/constant/thermophysicalProperties new file mode 100644 index 000000000..7b93ee2ea --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/constant/thermophysicalProperties @@ -0,0 +1,37 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties; +} + +thermoType +{ + type heRhoThermo; + mixture pureMixture; + transport const; + thermo hConst; + equationOfState perfectGas; + specie specie; + energy sensibleEnthalpy; +} + +mixture +{ + specie + { + molWeight 24.0999; + } + thermodynamics + { + Cp 5000.0; + Hf 0; + } + transport + { + mu 0.0002; + Pr 0.01; + } +} diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/constant/turbulenceProperties b/heat-exchanger-simplified/fluid-bottom-openfoam/constant/turbulenceProperties new file mode 100644 index 000000000..b75c49530 --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/constant/turbulenceProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object turbulenceProperties; +} + +simulationType laminar; diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/run.sh b/heat-exchanger-simplified/fluid-bottom-openfoam/run.sh new file mode 100755 index 000000000..da82a9ba2 --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/run.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/system/blockMeshDict b/heat-exchanger-simplified/fluid-bottom-openfoam/system/blockMeshDict new file mode 100644 index 000000000..02a04e7bd --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/system/blockMeshDict @@ -0,0 +1,101 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +vertices +( + (0 -1.0 0) + (1 -1.0 0) + (1 -0.5 0) + (0 -0.5 0) + + (0 -1.0 .4) + (1 -1.0 .4) + (1 -0.5 .4) + (0 -0.5 .4) + + (3 -1.0 0) + (3 -0.5 0) + + (3 -1.0 .4) + (3 -0.5 .4) + + (-.5 -1.0 0) + (-.5 -0.5 0) + + (-.5 -0.5 .4) + (-.5 -1.0 .4) + +); + +blocks +( + hex (12 0 3 13 15 4 7 14) (81 41 1) simpleGrading (0.2 0.067 1) + hex (0 1 2 3 4 5 6 7) (161 41 1) simpleGrading (5 0.067 1) + hex (1 8 9 2 5 10 11 6) (51 41 1) simpleGrading (1 0.067 1) +); + +boundary +( + + inlet + { + type wall; + faces + ( + (13 12 15 14) + ); + } + + outlet + { + type wall; + faces + ( + (8 9 11 10) + ); + } + + top + { + type wall; + faces + ( + (9 2 6 11) + (13 3 7 14) + ); + } + + slip-bottom + { + type wall; + faces + ( + (15 12 0 4) + ); + } + + bottom + { + type wall; + faces + ( + (1 8 10 5) + (4 0 1 5) + ); + } + + interface + { + type wall; + faces + ( + (7 6 2 3) + ); + } + +); diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/system/controlDict b/heat-exchanger-simplified/fluid-bottom-openfoam/system/controlDict new file mode 100644 index 000000000..324ab13b7 --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/system/controlDict @@ -0,0 +1,46 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} + +application buoyantPimpleFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 5; + +deltaT 0.01; + +writeControl runTime; + +writeInterval 0.01; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable false; + +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + libs ("libpreciceAdapterFunctionObject.so"); + } +} diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/system/decomposeParDict b/heat-exchanger-simplified/fluid-bottom-openfoam/system/decomposeParDict new file mode 100644 index 000000000..0d1859e14 --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/system/decomposeParDict @@ -0,0 +1,16 @@ +FoamFile { + version 2.0; + class dictionary; + object decomposeParDict; + format ascii; +} + +numberOfSubdomains 2; + +method simple; + +simpleCoeffs +{ + n (2 1 1); + delta 0.001; +} diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/system/fvSchemes b/heat-exchanger-simplified/fluid-bottom-openfoam/system/fvSchemes new file mode 100644 index 000000000..fd48cb5b7 --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/system/fvSchemes @@ -0,0 +1,48 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ + default none; + div(phi,U) Gauss upwind; + div(phi,h) Gauss upwind; + div(phi,e) Gauss upwind; + div(phi,k) Gauss upwind; + div(phi,epsilon) Gauss upwind; + div(phi,R) Gauss upwind; + div(phi,K) Gauss linear; + div(phi,Ekp) Gauss linear; + div(R) Gauss linear; + div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/system/fvSolution b/heat-exchanger-simplified/fluid-bottom-openfoam/system/fvSolution new file mode 100644 index 000000000..e7047fa96 --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/system/fvSolution @@ -0,0 +1,55 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} + +solvers +{ + "rho.*" + { + solver PCG; + preconditioner DIC; + tolerance 0; + relTol 0; + } + + p_rgh + { + solver PCG; + preconditioner DIC; + tolerance 1e-8; + relTol 0.01; + } + + p_rghFinal + { + $p_rgh; + relTol 0; + } + + "(U|h|e|k|epsilon|R)" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-6; + relTol 0.1; + } + + "(U|h|e|k|epsilon|R)Final" + { + $U; + relTol 0; + } +} + +PIMPLE +{ + momentumPredictor yes; + nOuterCorrectors 1; + nCorrectors 2; + nNonOrthogonalCorrectors 0; +} diff --git a/heat-exchanger-simplified/fluid-bottom-openfoam/system/preciceDict b/heat-exchanger-simplified/fluid-bottom-openfoam/system/preciceDict new file mode 100644 index 000000000..eb39196d1 --- /dev/null +++ b/heat-exchanger-simplified/fluid-bottom-openfoam/system/preciceDict @@ -0,0 +1,33 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Fluid-Bottom; + +modules (CHT); + +interfaces +{ + Interface + { + mesh Fluid-Bottom-Mesh; + patches (interface); + + readData + ( + Heat-Flux-Bottom + ); + + writeData + ( + Temperature-Bottom + ); + }; +}; diff --git a/heat-exchanger-simplified/fluid-top-openfoam/0/T b/heat-exchanger-simplified/fluid-top-openfoam/0/T new file mode 100644 index 000000000..abf1bce54 --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/0/T @@ -0,0 +1,49 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} + +dimensions [ 0 0 0 1 0 0 0 ]; + +internalField uniform 300; + +boundaryField +{ + interface + { + type fixedGradient; + gradient uniform 0; + } + inlet + { + type fixedValue; + value $internalField; + } + outlet + { + type zeroGradient; + } + top + { + type zeroGradient; + } + bottom + { + type zeroGradient; + } + slip-bottom + { + type zeroGradient; + } + outerWall + { + type zeroGradient; + } + defaultFaces + { + type empty; + } +} diff --git a/heat-exchanger-simplified/fluid-top-openfoam/0/U b/heat-exchanger-simplified/fluid-top-openfoam/0/U new file mode 100644 index 000000000..cfe775cf3 --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/0/U @@ -0,0 +1,44 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} + +dimensions [ 0 1 -1 0 0 0 0 ]; + +internalField uniform ( 0.1 0 0 ); + +boundaryField +{ + interface + { + type noSlip; + } + inlet + { + type fixedValue; + value $internalField; + } + outlet + { + type zeroGradient; + } + top + { + type slip; + } + bottom + { + type noSlip; + } + slip-bottom + { + type slip; + } + defaultFaces + { + type empty; + } +} diff --git a/heat-exchanger-simplified/fluid-top-openfoam/0/alphat b/heat-exchanger-simplified/fluid-top-openfoam/0/alphat new file mode 100644 index 000000000..1d3ac72d0 --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/0/alphat @@ -0,0 +1,49 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object alphat; +} + +dimensions [ 1 -1 -1 0 0 0 0 ]; + +internalField uniform 0; + +boundaryField +{ + interface + { + type compressible::alphatWallFunction; + value uniform 0; + } + inlet + { + type compressible::alphatWallFunction; + value uniform 0; + } + outlet + { + type compressible::alphatWallFunction; + value uniform 0; + } + top + { + type compressible::alphatWallFunction; + value uniform 0; + } + bottom + { + type compressible::alphatWallFunction; + value uniform 0; + } + slip-bottom + { + type compressible::alphatWallFunction; + value uniform 0; + } + defaultFaces + { + type empty; + } +} diff --git a/heat-exchanger-simplified/fluid-top-openfoam/0/epsilon b/heat-exchanger-simplified/fluid-top-openfoam/0/epsilon new file mode 100644 index 000000000..c419576fc --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/0/epsilon @@ -0,0 +1,49 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object epsilon; +} + +dimensions [ 0 2 -3 0 0 0 0 ]; + +internalField uniform 0.01; + +boundaryField +{ + interface + { + type epsilonWallFunction; + value uniform 0.01; + } + inlet + { + type epsilonWallFunction; + value uniform 0.01; + } + outlet + { + type epsilonWallFunction; + value uniform 0.01; + } + top + { + type epsilonWallFunction; + value uniform 0.01; + } + bottom + { + type epsilonWallFunction; + value uniform 0.01; + } + slip-bottom + { + type epsilonWallFunction; + value uniform 0.01; + } + defaultFaces + { + type empty; + } +} diff --git a/heat-exchanger-simplified/fluid-top-openfoam/0/k b/heat-exchanger-simplified/fluid-top-openfoam/0/k new file mode 100644 index 000000000..a09c9617c --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/0/k @@ -0,0 +1,49 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object k; +} + +dimensions [ 0 2 -2 0 0 0 0 ]; + +internalField uniform 0.1; + +boundaryField +{ + interface + { + type kqRWallFunction; + value uniform 0.1; + } + inlet + { + type kqRWallFunction; + value uniform 0.1; + } + outlet + { + type kqRWallFunction; + value uniform 0.1; + } + top + { + type kqRWallFunction; + value uniform 0.1; + } + slip-bottom + { + type kqRWallFunction; + value uniform 0.1; + } + bottom + { + type kqRWallFunction; + value uniform 0.1; + } + defaultFaces + { + type empty; + } +} diff --git a/heat-exchanger-simplified/fluid-top-openfoam/0/nut b/heat-exchanger-simplified/fluid-top-openfoam/0/nut new file mode 100644 index 000000000..580e908d7 --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/0/nut @@ -0,0 +1,49 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object nut; +} + +dimensions [ 0 2 -1 0 0 0 0 ]; + +internalField uniform 0; + +boundaryField +{ + interface + { + type nutkWallFunction; + value uniform 0; + } + inlet + { + type nutkWallFunction; + value uniform 0; + } + outlet + { + type nutkWallFunction; + value uniform 0; + } + top + { + type nutkWallFunction; + value uniform 0; + } + bottom + { + type nutkWallFunction; + value uniform 0; + } + slip-bottom + { + type nutkWallFunction; + value uniform 0; + } + defaultFaces + { + type empty; + } +} diff --git a/heat-exchanger-simplified/fluid-top-openfoam/0/p b/heat-exchanger-simplified/fluid-top-openfoam/0/p new file mode 100644 index 000000000..654bb4023 --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/0/p @@ -0,0 +1,54 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p; +} + +dimensions [ 1 -1 -2 0 0 0 0 ]; + +internalField uniform 103500; + +boundaryField +{ + interface + { + type calculated; + value $internalField; + } + inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + outerWall + { + type calculated; + value $internalField; + } + top + { + type calculated; + value $internalField; + } + bottom + { + type calculated; + value $internalField; + } + slip-bottom + { + type calculated; + value $internalField; + } + defaultFaces + { + type empty; + } +} diff --git a/heat-exchanger-simplified/fluid-top-openfoam/0/p_rgh b/heat-exchanger-simplified/fluid-top-openfoam/0/p_rgh new file mode 100644 index 000000000..c5eebe883 --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/0/p_rgh @@ -0,0 +1,44 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p_rgh; +} + +dimensions [ 1 -1 -2 0 0 0 0 ]; + +internalField uniform 103500; + +boundaryField +{ + interface + { + type zeroGradient; + } + inlet + { + type zeroGradient; + } + outlet + { + type fixedValue; + value $internalField; + } + top + { + type zeroGradient; + } + slip-bottom + { + type zeroGradient; + } + bottom + { + type zeroGradient; + } + defaultFaces + { + type empty; + } +} diff --git a/heat-exchanger-simplified/fluid-top-openfoam/clean.sh b/heat-exchanger-simplified/fluid-top-openfoam/clean.sh new file mode 100755 index 000000000..c31d9fc76 --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . diff --git a/heat-exchanger-simplified/fluid-top-openfoam/constant/g b/heat-exchanger-simplified/fluid-top-openfoam/constant/g new file mode 100644 index 000000000..ca544e1f1 --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/constant/g @@ -0,0 +1,10 @@ +FoamFile +{ + version 2.0; + format ascii; + class uniformDimensionedVectorField; + object g; +} + +dimensions [0 1 -2 0 0 0 0]; +value (0 -9.81 0); diff --git a/heat-exchanger-simplified/fluid-top-openfoam/constant/thermophysicalProperties b/heat-exchanger-simplified/fluid-top-openfoam/constant/thermophysicalProperties new file mode 100644 index 000000000..7b93ee2ea --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/constant/thermophysicalProperties @@ -0,0 +1,37 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties; +} + +thermoType +{ + type heRhoThermo; + mixture pureMixture; + transport const; + thermo hConst; + equationOfState perfectGas; + specie specie; + energy sensibleEnthalpy; +} + +mixture +{ + specie + { + molWeight 24.0999; + } + thermodynamics + { + Cp 5000.0; + Hf 0; + } + transport + { + mu 0.0002; + Pr 0.01; + } +} diff --git a/heat-exchanger-simplified/fluid-top-openfoam/constant/turbulenceProperties b/heat-exchanger-simplified/fluid-top-openfoam/constant/turbulenceProperties new file mode 100644 index 000000000..b75c49530 --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/constant/turbulenceProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object turbulenceProperties; +} + +simulationType laminar; diff --git a/heat-exchanger-simplified/fluid-top-openfoam/run.sh b/heat-exchanger-simplified/fluid-top-openfoam/run.sh new file mode 100755 index 000000000..da82a9ba2 --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/run.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/heat-exchanger-simplified/fluid-top-openfoam/system/blockMeshDict b/heat-exchanger-simplified/fluid-top-openfoam/system/blockMeshDict new file mode 100644 index 000000000..de95b0ace --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/system/blockMeshDict @@ -0,0 +1,101 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +vertices +( + (0 0 0) + (1 0 0) + (1 .5 0) + (0 .5 0) + + (0 0 .4) + (1 0 .4) + (1 .5 .4) + (0 .5 .4) + + (3 0 0) + (3 .5 0) + + (3 0 .4) + (3 .5 .4) + + (-.5 0 0) + (-.5 .5 0) + + (-.5 .5 .4) + (-.5 0 .4) + +); + +blocks +( + hex (12 0 3 13 15 4 7 14) (81 41 1) simpleGrading (.2 15 1) + hex (0 1 2 3 4 5 6 7) (161 41 1) simpleGrading (5 15 1) + hex (1 8 9 2 5 10 11 6) (51 41 1) simpleGrading (1 15 1) +); + +boundary +( + + inlet + { + type wall; + faces + ( + (13 12 15 14) + ); + } + + outlet + { + type wall; + faces + ( + (8 9 11 10) + ); + } + + top + { + type wall; + faces + ( + (7 6 2 3) + (9 2 6 11) + (13 3 7 14) + ); + } + + slip-bottom + { + type wall; + faces + ( + (15 12 0 4) + ); + } + + bottom + { + type wall; + faces + ( + (1 8 10 5) + ); + } + + interface + { + type wall; + faces + ( + (4 0 1 5) + ); + } + +); diff --git a/heat-exchanger-simplified/fluid-top-openfoam/system/controlDict b/heat-exchanger-simplified/fluid-top-openfoam/system/controlDict new file mode 100644 index 000000000..324ab13b7 --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/system/controlDict @@ -0,0 +1,46 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} + +application buoyantPimpleFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 5; + +deltaT 0.01; + +writeControl runTime; + +writeInterval 0.01; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable false; + +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + libs ("libpreciceAdapterFunctionObject.so"); + } +} diff --git a/heat-exchanger-simplified/fluid-top-openfoam/system/decomposeParDict b/heat-exchanger-simplified/fluid-top-openfoam/system/decomposeParDict new file mode 100644 index 000000000..0d1859e14 --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/system/decomposeParDict @@ -0,0 +1,16 @@ +FoamFile { + version 2.0; + class dictionary; + object decomposeParDict; + format ascii; +} + +numberOfSubdomains 2; + +method simple; + +simpleCoeffs +{ + n (2 1 1); + delta 0.001; +} diff --git a/heat-exchanger-simplified/fluid-top-openfoam/system/fvSchemes b/heat-exchanger-simplified/fluid-top-openfoam/system/fvSchemes new file mode 100644 index 000000000..fd48cb5b7 --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/system/fvSchemes @@ -0,0 +1,48 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ + default none; + div(phi,U) Gauss upwind; + div(phi,h) Gauss upwind; + div(phi,e) Gauss upwind; + div(phi,k) Gauss upwind; + div(phi,epsilon) Gauss upwind; + div(phi,R) Gauss upwind; + div(phi,K) Gauss linear; + div(phi,Ekp) Gauss linear; + div(R) Gauss linear; + div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/heat-exchanger-simplified/fluid-top-openfoam/system/fvSolution b/heat-exchanger-simplified/fluid-top-openfoam/system/fvSolution new file mode 100644 index 000000000..e7047fa96 --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/system/fvSolution @@ -0,0 +1,55 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} + +solvers +{ + "rho.*" + { + solver PCG; + preconditioner DIC; + tolerance 0; + relTol 0; + } + + p_rgh + { + solver PCG; + preconditioner DIC; + tolerance 1e-8; + relTol 0.01; + } + + p_rghFinal + { + $p_rgh; + relTol 0; + } + + "(U|h|e|k|epsilon|R)" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-6; + relTol 0.1; + } + + "(U|h|e|k|epsilon|R)Final" + { + $U; + relTol 0; + } +} + +PIMPLE +{ + momentumPredictor yes; + nOuterCorrectors 1; + nCorrectors 2; + nNonOrthogonalCorrectors 0; +} diff --git a/heat-exchanger-simplified/fluid-top-openfoam/system/preciceDict b/heat-exchanger-simplified/fluid-top-openfoam/system/preciceDict new file mode 100644 index 000000000..bf97d50ac --- /dev/null +++ b/heat-exchanger-simplified/fluid-top-openfoam/system/preciceDict @@ -0,0 +1,33 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Fluid-Top; + +modules (CHT); + +interfaces +{ + Interface + { + mesh Fluid-Top-Mesh; + patches (interface); + + readData + ( + Heat-Flux-Top + ); + + writeData + ( + Temperature-Top + ); + }; +}; diff --git a/heat-exchanger-simplified/images/tutorials-heat-exchanger-simplified-animation.webp b/heat-exchanger-simplified/images/tutorials-heat-exchanger-simplified-animation.webp new file mode 100644 index 000000000..d4d94e143 Binary files /dev/null and b/heat-exchanger-simplified/images/tutorials-heat-exchanger-simplified-animation.webp differ diff --git a/heat-exchanger-simplified/images/tutorials-heat-exchanger-simplified-overview.png b/heat-exchanger-simplified/images/tutorials-heat-exchanger-simplified-overview.png new file mode 100644 index 000000000..49081e9ce Binary files /dev/null and b/heat-exchanger-simplified/images/tutorials-heat-exchanger-simplified-overview.png differ diff --git a/heat-exchanger-simplified/images/tutorials-heat-exchanger-simplified-precice-config.png b/heat-exchanger-simplified/images/tutorials-heat-exchanger-simplified-precice-config.png new file mode 100644 index 000000000..e6523caf6 Binary files /dev/null and b/heat-exchanger-simplified/images/tutorials-heat-exchanger-simplified-precice-config.png differ diff --git a/heat-exchanger-simplified/metadata.yaml b/heat-exchanger-simplified/metadata.yaml new file mode 100644 index 000000000..124e76f9d --- /dev/null +++ b/heat-exchanger-simplified/metadata.yaml @@ -0,0 +1,29 @@ +name: Heat Exchanger simplified +path: heat-exchanger-simplified # relative to git repo +url: https://precice.org/tutorials-heat-exchanger-simplified.html + +participants: + - Fluid-Top + - Fluid-Bottom + - Solid + +cases: + fluid-btm-openfoam: + participant: Fluid-Bottom + directory: ./fluid-bottom-openfoam + run: ./run.sh + component: openfoam-adapter + + fluid-top-openfoam: + participant: Fluid-Top + directory: ./fluid-top-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-simplified/precice-config.xml b/heat-exchanger-simplified/precice-config.xml new file mode 100644 index 000000000..5b0dc9237 --- /dev/null +++ b/heat-exchanger-simplified/precice-config.xml @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/heat-exchanger-simplified/solid-calculix/clean.sh b/heat-exchanger-simplified/solid-calculix/clean.sh new file mode 100755 index 000000000..e9fdde0e3 --- /dev/null +++ b/heat-exchanger-simplified/solid-calculix/clean.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_calculix . +rm -fv all.msh # The mesh is generated by generate_mesh.py in this case diff --git a/heat-exchanger-simplified/solid-calculix/config.yml b/heat-exchanger-simplified/solid-calculix/config.yml new file mode 100644 index 000000000..5fd8cff21 --- /dev/null +++ b/heat-exchanger-simplified/solid-calculix/config.yml @@ -0,0 +1,17 @@ +participants: + Solid: + interfaces: + - nodes-mesh: Solid-Top-Mesh-Nodes + patch: yend + read-data: [Temperature-Top] + - faces-mesh: Solid-Top-Mesh-Faces + patch: flux_interface_top + write-data: [Heat-Flux-Top] + - nodes-mesh: Solid-Bottom-Mesh-Nodes + patch: ybegin + read-data: [Temperature-Bottom] + - faces-mesh: Solid-Bottom-Mesh-Faces + patch: flux_interface_bottom + write-data: [Heat-Flux-Bottom] + +precice-config-file: ../precice-config.xml diff --git a/heat-exchanger-simplified/solid-calculix/generate_mesh.py b/heat-exchanger-simplified/solid-calculix/generate_mesh.py new file mode 100644 index 000000000..58c00e347 --- /dev/null +++ b/heat-exchanger-simplified/solid-calculix/generate_mesh.py @@ -0,0 +1,95 @@ +import numpy as np + +# Output, geometric parameters +output_file_name = "out.msh" + +x_begin, x_end = 0, 1.0 +y_begin, y_end = -0.5, 0 +z_begin, z_end = 0, 0.4 + +# Number of elements. Add one for number of nodes! +n_x, n_y, n_z = 400, 50, 1 + +# Coordinates in (i, j, k) space. i = 0, ..., n_x etc +xs = np.linspace(x_begin, x_end, n_x + 1) +ys = np.linspace(y_begin, y_end, n_y + 1) +zs = np.linspace(z_begin, z_end, n_z + 1) + +# List of 3D points +nodes = [] +# Map from (i,j,k) pos to index +indices = dict() + +# Build nodes +for i in range(0, n_x + 1): + for j in range(0, n_y + 1): + for k in range(0, n_z + 1): + nodes.append((xs[i], ys[j], zs[k])) + # CCX index starts at 1! + v = len(nodes) + indices[(i, j, k)] = v + 1 + +print("** Nodes") +print("*Node, NSET=Nall") +for v, (x, y, z) in enumerate(nodes): + print("{}, {:10.4f}, {:10.4f}, {:10.4f},".format(v + 2, x, y, z)) + +# Build elements +print("** Volume elements") +print("* Element, TYPE=C3D8, ELSET=Evolumes") + +elems_top_surface = [] +elems_bottom_surface = [] + +elem_id = 1 +for i in range(0, n_x): + for j in range(0, n_y): + for k in range(0, n_z): + print("{}, {}, {}, {}, {}, {}, {}, {}, {},".format(elem_id, + indices[( + i, j, k)], + indices[( + i + 1, j, k)], + indices[( + i + 1, j + 1, k)], + indices[( + i, j + 1, k)], + indices[( + i, j, k + 1)], + indices[( + i + 1, j, k + 1)], + indices[( + i + 1, j + 1, k + 1)], + indices[(i, j + 1, k + 1)],)) + if j == n_y - 1: + elems_top_surface.append(elem_id) + elif j == 0: + elems_bottom_surface.append(elem_id) + elem_id += 1 + +# Set of border. Adapt freely +print("** Nodes, border with y = y_end") +print("*NSET, NSET=Nyend") +str = "" +for i in range(0, n_x + 1): + for k in range(0, n_z + 1): + str = "{}, ".format(indices[i, n_y, k]) + print(str) +print("** Nodes, border with y = y_begin") +print("*NSET, NSET=Nybegin") +str = "" +for i in range(0, n_x + 1): + for k in range(0, n_z + 1): + str = "{}, ".format(indices[i, 0, k]) + print(str) + + +# Upper surface +print("*SURFACE, NAME=Sflux_interface_top") +for id in elems_top_surface: + print("{}, S5".format(id)) + +# Lower surface +print("*SURFACE, NAME=Sflux_interface_bottom") +for id in elems_bottom_surface: + print("{}, S3".format(id)) diff --git a/heat-exchanger-simplified/solid-calculix/run.sh b/heat-exchanger-simplified/solid-calculix/run.sh new file mode 100755 index 000000000..460b914bd --- /dev/null +++ b/heat-exchanger-simplified/solid-calculix/run.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 ./generate_mesh.py > all.msh +ccx_preCICE -i solid -precice-participant Solid + +close_log diff --git a/heat-exchanger-simplified/solid-calculix/solid.inp b/heat-exchanger-simplified/solid-calculix/solid.inp new file mode 100644 index 000000000..7e3cf4d8a --- /dev/null +++ b/heat-exchanger-simplified/solid-calculix/solid.inp @@ -0,0 +1,112 @@ +** Case file adapted from one generated by FreeCAD inp file writer for CalculiX,Abaqus meshes +** Mesh generated from https://gist.github.com/boris-martin/1cdcc53bac909449632076a614450949 + +*INCLUDE, INPUT=./all.msh + +** Define element set Eall +*ELSET, ELSET=Eall +Evolumes + + + +*********************************************************** +** Element sets for materials and FEM element type (solid, shell, beam, fluid) +** written by write_element_sets_material_and_femelement_type function +*ELSET,ELSET=MaterialSolidSolid +Evolumes + + +*********************************************************** +** Materials +** written by write_materials function +** Young's modulus unit is Pa = N/m2 +** Thermal conductivity unit is W/(m*K) +** Specific Heat unit is J/(kg*K) +** FreeCAD material name: CalculiX-Steel +** MaterialSolid +*MATERIAL, NAME=MaterialSolid +*ELASTIC +210000, 0.300 +*CONDUCTIVITY +100.000 +*EXPANSION +1.200e-05 +*SPECIFIC HEAT +100.0 + +** conductivity / (density * Specific Heat) = 1 +*DENSITY +1.0 + +*********************************************************** +** Initial temperature constraint +** written by write_constraints_initialtemperature function +*INITIAL CONDITIONS,TYPE=TEMPERATURE +Nall,305.0 + +*********************************************************** +** Sections +** written by write_femelementsets function +*SOLID SECTION, ELSET=MaterialSolidSolid, MATERIAL=MaterialSolid + +*********************************************************** +** At least one step is needed to run an CalculiX analysis of FreeCAD +** written by write_step_begin function +*STEP, INC=2000 +*HEAT TRANSFER, DIRECT +0.01,5.0 + +*********************************************************** +** Fixed temperature constraint applied +** written by write_constraints_temperature function +** HeatedPlate +*BOUNDARY +Nybegin,11,11,0.0 + +** ConstraintTemperature001 +*BOUNDARY +Nyend,11,11,0.0 + + +*********************************************************** +** Outputs --> frd file +** written by write_outputs_types function +*NODE FILE +NT + +*********************************************************** +** written by write_step_end function +*END STEP + +*********************************************************** +** CalculiX Input file +** written by write_footer function +** written by --> FreeCAD 0.19.24267 +99 (Git) +** written on --> Sat Feb 19 21:15:15 2022 +** file name --> heat_plate_ccx.FCStd +** analysis name --> Analysis +** +** +*********************************************************** +** About units: +** See ccx manual, ccx does not know about any unit. +** Golden rule: The user must make sure that the numbers he provides have consistent units. +** The user is the FreeCAD calculix writer module ;-) +** +** The unit system which is used at Guido Dhondt's company: mm, N, s, K +** Since Length and Mass are connected by Force, if Length is mm the Mass is in t to get N +** The following units are used to write to inp file: +** +** Length: mm (this includes the mesh geometry) +** Mass: t +** TimeSpan: s +** Temperature: K +** +** This leads to: +** Force: N +** Pressure: N/mm^2 +** Density: t/mm^3 +** Gravity: mm/s^2 +** Thermal conductivity: t*mm/K/s^3 (same as W/m/K) +** Specific Heat: mm^2/s^2/K (same as J/kg/K) +** diff --git a/heat-exchanger/.gitignore b/heat-exchanger/.gitignore new file mode 100644 index 000000000..41190654c --- /dev/null +++ b/heat-exchanger/.gitignore @@ -0,0 +1,12 @@ +# 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 ae7277c4a..5272d76b7 100644 --- a/heat-exchanger/README.md +++ b/heat-exchanger/README.md @@ -23,6 +23,12 @@ We define the participants `Inner-Fluid`, `Solid`, and `Outer-Fluid` and two int ![Heat exchanger: three participants](images/tutorials-heat-exchanger-participants.png) +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-heat-exchanger-precice-config.png) + ## Available solvers * OpenFOAM. `buoyantSimpleFoam` is used for fluid flow (both participants). This is a solver for steady-state, buoyant, turbulent flow of compressible fluids for ventilation and heat transfer. For more information, have a look at the [OpenFOAM adapter documentation](https://www.precice.org/adapter-openfoam-overview.html). diff --git a/heat-exchanger/fluid-inner-openfoam/constant/.gitignore b/heat-exchanger/fluid-inner-openfoam/constant/.gitignore deleted file mode 100644 index 825968042..000000000 --- a/heat-exchanger/fluid-inner-openfoam/constant/.gitignore +++ /dev/null @@ -1 +0,0 @@ -polyMesh/ diff --git a/heat-exchanger/fluid-inner-openfoam/run.sh b/heat-exchanger/fluid-inner-openfoam/run.sh index 6f176ba93..71a1313ae 100755 --- a/heat-exchanger/fluid-inner-openfoam/run.sh +++ b/heat-exchanger/fluid-inner-openfoam/run.sh @@ -1,7 +1,10 @@ -#!/bin/sh +#!/bin/bash set -e -u -touch fluid-inner-openfoam.foam +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/heat-exchanger/fluid-inner-openfoam/system/controlDict b/heat-exchanger/fluid-inner-openfoam/system/controlDict index 4382c859f..461bca5ce 100644 --- a/heat-exchanger/fluid-inner-openfoam/system/controlDict +++ b/heat-exchanger/fluid-inner-openfoam/system/controlDict @@ -31,7 +31,7 @@ writeInterval 50; adjustTimeStep no; -endTime 2000.0; +endTime 500; writeControl timeStep; diff --git a/heat-exchanger/fluid-outer-openfoam/constant/.gitignore b/heat-exchanger/fluid-outer-openfoam/constant/.gitignore deleted file mode 100644 index 825968042..000000000 --- a/heat-exchanger/fluid-outer-openfoam/constant/.gitignore +++ /dev/null @@ -1 +0,0 @@ -polyMesh/ diff --git a/heat-exchanger/fluid-outer-openfoam/run.sh b/heat-exchanger/fluid-outer-openfoam/run.sh index 8816441f2..71a1313ae 100755 --- a/heat-exchanger/fluid-outer-openfoam/run.sh +++ b/heat-exchanger/fluid-outer-openfoam/run.sh @@ -1,7 +1,10 @@ -#!/bin/sh +#!/bin/bash set -e -u -touch fluid-outer-openfoam.foam +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/heat-exchanger/fluid-outer-openfoam/system/controlDict b/heat-exchanger/fluid-outer-openfoam/system/controlDict index d32f869c6..d7b9ecec4 100644 --- a/heat-exchanger/fluid-outer-openfoam/system/controlDict +++ b/heat-exchanger/fluid-outer-openfoam/system/controlDict @@ -31,7 +31,7 @@ writeInterval 50; adjustTimeStep no; -endTime 2000.0; +endTime 500; writeControl timeStep; diff --git a/heat-exchanger/images/tutorials-heat-exchanger-precice-config.png b/heat-exchanger/images/tutorials-heat-exchanger-precice-config.png new file mode 100644 index 000000000..2a3fcf1d1 Binary files /dev/null and b/heat-exchanger/images/tutorials-heat-exchanger-precice-config.png differ diff --git a/heat-exchanger/precice-config.xml b/heat-exchanger/precice-config.xml index c1006a1ca..bc2f33dc7 100644 --- a/heat-exchanger/precice-config.xml +++ b/heat-exchanger/precice-config.xml @@ -1,4 +1,4 @@ - + - - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - + - - - - - - - - - + + + + + + + + + - + - - - - - - - - - - + + + + + + + + + diff --git a/heat-exchanger/solid-calculix/.gitignore b/heat-exchanger/solid-calculix/.gitignore deleted file mode 100644 index b138a63c9..000000000 --- a/heat-exchanger/solid-calculix/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Files distributed separately, downloaded via download-meshes.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 33d6d65c3..f1f5b3aef 100755 --- a/heat-exchanger/solid-calculix/run.sh +++ b/heat-exchanger/solid-calculix/run.sh @@ -1,6 +1,9 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +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 @@ -9,3 +12,5 @@ fi export OMP_NUM_THREADS=1 export CCX_NPROC_EQUATION_SOLVER=1 ccx_preCICE -i solid -precice-participant Solid + +close_log diff --git a/multiple-perpendicular-flaps/README.md b/multiple-perpendicular-flaps/README.md index 420eb7c6f..00ed7f83f 100644 --- a/multiple-perpendicular-flaps/README.md +++ b/multiple-perpendicular-flaps/README.md @@ -25,6 +25,12 @@ The top, bottom and flap are walls with a `noslip` condition. For a case showing fluid-structure interaction only (no multi-coupling), take a look at the [single perpendicular flap tutorial](https://www.precice.org/tutorials-perpendicular-flap.html). +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-multiple-perpendicular-flaps-precice-config.png) + ## Why multi-coupling? This is a case with three participants: the fluid and each flap. In preCICE, there are two options to [couple more than two participants](https://www.precice.org/configuration-coupling-multi.html). The first option a composition of bi-coupling schemes, in which we must specify the exchange of data in a participant to participant manner. However, such a composition is not suited for combining multiple strong fluid-structure interactions [1]. Thus, in this case, we use the second option, fully-implicit multi-coupling. @@ -34,8 +40,8 @@ We can set this in our `precice-config.xml`: ```xml - - + + ``` The participant that has the control is the one that it is connected to all other participants. This is why we have chosen the fluid participant for this task. @@ -44,21 +50,21 @@ The participant that has the control is the one that it is connected to all othe For the fluid participant we use OpenFOAM. In particular, we use the application `pimpleFoam`. The geometry of the Fluid participant is defined in the file `Fluid/system/blockMeshDict`. Besides, we must specify where are we exchanging data with the other participants. The interfaces are set in the file `Fluid/system/preciceDict`. In this file, we set to exchange stress and displacement on the surface of each flap. -Most of the coupling details are specified in the file `precide-config.xml`. Here we estipulate the order in which we read/write data from one participant to another or how we map from the fluid to the solid's mesh. In particular, we have chosen the nearest-neighbor mapping scheme. +Most of the coupling details are specified in the file `precice-config.xml`. Here we estipulate the order in which we read/write data from one participant to another or how we map from the fluid to the solid's mesh. In particular, we have chosen the nearest-neighbor mapping scheme. -For the simulation of the solid participants we use the deal.II adapter. In deal.II, the geometry of the domain is specified directly on the solver. The two flaps in our case are essentially the same but for the x-coordinate. The flap geometry is given to the solver when we select the scenario in the '.prm' file. +For the simulation of the solid participants we use the deal.II adapter. In deal.II, the geometry of the domain is specified directly on the solver. The two flaps in our case are essentially the same but for the x-coordinate. The flap geometry is given to the solver when we select the scenario in the `.prm` file. ```text set Scenario = PF ``` -But to specify the position of the flap along the x-axis, we must specify it in the `Solid1/linear_elasticity.prm` file as follows: +But to specify the position of the flap along the x-axis, we must specify it in the `solid-upstream-dealii/parameters.prm` file as follows: ```text set Flap location = -1.0 ``` -While in case of `Solid2/linear_elasticity.prm` we write: +While in case of `solid-downstream-dealii/parameters.prm` we write: ```text set Flap location = 1.0 @@ -69,7 +75,7 @@ The scenario settings are implemented similarly for the nonlinear case. ## Running the Simulation 1. Preparation: - To run the coupled simulation, copy the deal.II executable `linear_elasticity` or `nonlinear_elasticity` into the main folder. To learn how to obtain the deal.II executable take a look at the description on the [deal.II-adapter page](https://www.precice.org/adapter-dealii-overview.html). + To run the coupled simulation, copy the deal.II executable `elasticity` into the main folder. To learn how to obtain the deal.II executable take a look at the description on the [deal.II-adapter page](https://www.precice.org/adapter-dealii-overview.html). 2. Starting: We are going to run each solver in a different terminal. It is important that first we navigate to the simulation directory so that all solvers start in the same directory. @@ -89,26 +95,26 @@ The scenario settings are implemented similarly for the nonlinear case. for a parallel run. - The solid participants are only designed for serial runs. To run the `Solid1` participant, execute the corresponding deal.II binary file e.g. by: + The solid participants are only designed for serial runs. To run the `Solid-Upstream` participant, execute the corresponding deal.II binary file e.g. by: ```bash - cd solid-left-dealii - ./run.sh -linear + cd solid-upstream-dealii + ./run.sh ``` - Finally, in the third terminal we will run the solver for the `Solid2` participant by: + Finally, in the third terminal we will run the solver for the `Solid-Downstream` participant by: ```bash - cd solid-right-dealii - ./run.sh -linear + cd solid-downstream-dealii + ./run.sh ``` - In case we want to run the nonlinear case, simply replace the flag`-linear` by `-nonlinear`. - ## Postprocessing After the simulation has finished, you can visualize your results using e.g. ParaView. Fluid results are in the OpenFOAM format and you may load the `fluid-openfoam.foam` file. Looking at the fluid results is enough to obtain information about the behaviour of the flaps. You can also visualize the solid participants' vtks though. +Example visualization of the fluid velocity and the solid displacement at t=2.3s, after synchronizing the results with a `Temporal Shift Scale` filter (scale for the deal.II results: 0.1): + ![Example visualization](images/tutorials-multiple-perpendicular-flaps-results.png) ## References diff --git a/multiple-perpendicular-flaps/fluid-openfoam/run.sh b/multiple-perpendicular-flaps/fluid-openfoam/run.sh index c191b9e48..da82a9ba2 100755 --- a/multiple-perpendicular-flaps/fluid-openfoam/run.sh +++ b/multiple-perpendicular-flaps/fluid-openfoam/run.sh @@ -1,8 +1,12 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + blockMesh -touch fluid-openfoam.foam ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/multiple-perpendicular-flaps/fluid-openfoam/system/controlDict b/multiple-perpendicular-flaps/fluid-openfoam/system/controlDict index 2b316a90a..9d35646a2 100644 --- a/multiple-perpendicular-flaps/fluid-openfoam/system/controlDict +++ b/multiple-perpendicular-flaps/fluid-openfoam/system/controlDict @@ -15,7 +15,7 @@ startTime 0; stopAt endTime; -endTime 10; +endTime 5; deltaT 0.01; diff --git a/multiple-perpendicular-flaps/fluid-openfoam/system/preciceDict b/multiple-perpendicular-flaps/fluid-openfoam/system/preciceDict index d38366ad1..3575f7142 100644 --- a/multiple-perpendicular-flaps/fluid-openfoam/system/preciceDict +++ b/multiple-perpendicular-flaps/fluid-openfoam/system/preciceDict @@ -14,9 +14,9 @@ modules (FSI); interfaces { - Interface1 + Upstream-Centers { - mesh Fluid1-Mesh-Centers; + mesh Fluid-Upstream-Mesh-Centers; patches (flap1); locations faceCenters; @@ -26,19 +26,19 @@ interfaces writeData ( - Stress1 + Stress-Upstream ); }; - Interface2 + Upstream-Nodes { - mesh Fluid1-Mesh-Nodes; + mesh Fluid-Upstream-Mesh-Nodes; patches (flap1); locations faceNodes; readData ( - Displacement1 + Displacement-Upstream ); writeData @@ -46,9 +46,9 @@ interfaces ); }; - Interface3 + Downstream-Centers { - mesh Fluid2-Mesh-Centers; + mesh Fluid-Downstream-Mesh-Centers; patches (flap2); locations faceCenters; @@ -58,19 +58,19 @@ interfaces writeData ( - Stress2 + Stress-Downstream ); }; - Interface4 + Downstream-Nodes { - mesh Fluid2-Mesh-Nodes; + mesh Fluid-Downstream-Mesh-Nodes; patches (flap2); locations faceNodes; readData ( - Displacement2 + Displacement-Downstream ); writeData diff --git a/multiple-perpendicular-flaps/images/tutorials-multiple-perpendicular-flaps-precice-config.png b/multiple-perpendicular-flaps/images/tutorials-multiple-perpendicular-flaps-precice-config.png new file mode 100644 index 000000000..7d9dc634e Binary files /dev/null and b/multiple-perpendicular-flaps/images/tutorials-multiple-perpendicular-flaps-precice-config.png differ diff --git a/multiple-perpendicular-flaps/images/tutorials-multiple-perpendicular-flaps-results.png b/multiple-perpendicular-flaps/images/tutorials-multiple-perpendicular-flaps-results.png index aedc406db..911d374f5 100644 Binary files a/multiple-perpendicular-flaps/images/tutorials-multiple-perpendicular-flaps-results.png and b/multiple-perpendicular-flaps/images/tutorials-multiple-perpendicular-flaps-results.png differ diff --git a/multiple-perpendicular-flaps/precice-config.xml b/multiple-perpendicular-flaps/precice-config.xml index e21b46e4c..d90f70e06 100644 --- a/multiple-perpendicular-flaps/precice-config.xml +++ b/multiple-perpendicular-flaps/precice-config.xml @@ -7,117 +7,142 @@ enabled="true" /> - - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/multiple-perpendicular-flaps/solid-left-dealii/clean.sh b/multiple-perpendicular-flaps/solid-downstream-dealii/clean.sh similarity index 100% rename from multiple-perpendicular-flaps/solid-left-dealii/clean.sh rename to multiple-perpendicular-flaps/solid-downstream-dealii/clean.sh diff --git a/multiple-perpendicular-flaps/solid-right-dealii/parameters.prm b/multiple-perpendicular-flaps/solid-downstream-dealii/parameters.prm similarity index 91% rename from multiple-perpendicular-flaps/solid-right-dealii/parameters.prm rename to multiple-perpendicular-flaps/solid-downstream-dealii/parameters.prm index 19e26b376..f1a1c2d69 100644 --- a/multiple-perpendicular-flaps/solid-right-dealii/parameters.prm +++ b/multiple-perpendicular-flaps/solid-downstream-dealii/parameters.prm @@ -68,16 +68,16 @@ subsection precice configuration set precice config-file = ../precice-config.xml # Name of the participant in the precice-config.xml file - set Participant name = Solid2 + set Participant name = Solid-Downstream # Name of the coupling mesh in the precice-config.xml file - set Mesh name = Solid2-Mesh + set Mesh name = Solid-Downstream-Mesh # Name of the read data in the precice-config.xml file - set Read data name = Stress2 + set Read data name = Stress-Downstream # Name of the write data in the precice-config.xml file - set Write data name = Displacement2 + set Write data name = Displacement-Downstream # PF x-location set Flap location = 1.0 diff --git a/multiple-perpendicular-flaps/solid-right-dealii/plot-displacement.sh b/multiple-perpendicular-flaps/solid-downstream-dealii/plot-displacement.sh similarity index 56% rename from multiple-perpendicular-flaps/solid-right-dealii/plot-displacement.sh rename to multiple-perpendicular-flaps/solid-downstream-dealii/plot-displacement.sh index 0c71fe9c2..f68411664 100755 --- a/multiple-perpendicular-flaps/solid-right-dealii/plot-displacement.sh +++ b/multiple-perpendicular-flaps/solid-downstream-dealii/plot-displacement.sh @@ -4,6 +4,6 @@ set grid set title 'Displacement of the Flap Tip' set xlabel 'Time [s]' set ylabel 'X-Displacement [m]' -plot "precice-Solid2-watchpoint-flap_tip.log" using 1:4 title 'Top displacemement' with lines +plot "precice-Solid-Downstream-watchpoint-flap_tip.log" using 1:4 title 'Top displacemement' with lines EOF diff --git a/multiple-perpendicular-flaps/solid-left-dealii/run.sh b/multiple-perpendicular-flaps/solid-downstream-dealii/run.sh similarity index 100% rename from multiple-perpendicular-flaps/solid-left-dealii/run.sh rename to multiple-perpendicular-flaps/solid-downstream-dealii/run.sh diff --git a/multiple-perpendicular-flaps/solid-right-dealii/clean.sh b/multiple-perpendicular-flaps/solid-upstream-dealii/clean.sh similarity index 100% rename from multiple-perpendicular-flaps/solid-right-dealii/clean.sh rename to multiple-perpendicular-flaps/solid-upstream-dealii/clean.sh diff --git a/multiple-perpendicular-flaps/solid-left-dealii/parameters.prm b/multiple-perpendicular-flaps/solid-upstream-dealii/parameters.prm similarity index 91% rename from multiple-perpendicular-flaps/solid-left-dealii/parameters.prm rename to multiple-perpendicular-flaps/solid-upstream-dealii/parameters.prm index 03789c384..7483ccff6 100644 --- a/multiple-perpendicular-flaps/solid-left-dealii/parameters.prm +++ b/multiple-perpendicular-flaps/solid-upstream-dealii/parameters.prm @@ -68,16 +68,16 @@ subsection precice configuration set precice config-file = ../precice-config.xml # Name of the participant in the precice-config.xml file - set Participant name = Solid1 + set Participant name = Solid-Upstream # Name of the coupling mesh in the precice-config.xml file - set Mesh name = Solid1-Mesh + set Mesh name = Solid-Upstream-Mesh # Name of the read data in the precice-config.xml file - set Read data name = Stress1 + set Read data name = Stress-Upstream # Name of the write data in the precice-config.xml file - set Write data name = Displacement1 + set Write data name = Displacement-Upstream # PF x-location set Flap location = -1.0 diff --git a/multiple-perpendicular-flaps/solid-left-dealii/plot-displacement.sh b/multiple-perpendicular-flaps/solid-upstream-dealii/plot-displacement.sh similarity index 57% rename from multiple-perpendicular-flaps/solid-left-dealii/plot-displacement.sh rename to multiple-perpendicular-flaps/solid-upstream-dealii/plot-displacement.sh index fca87fafb..14d54ecc9 100755 --- a/multiple-perpendicular-flaps/solid-left-dealii/plot-displacement.sh +++ b/multiple-perpendicular-flaps/solid-upstream-dealii/plot-displacement.sh @@ -4,6 +4,6 @@ set grid set title 'Displacement of the Flap Tip' set xlabel 'Time [s]' set ylabel 'X-Displacement [m]' -plot "precice-Solid1-watchpoint-flap_tip.log" using 1:4 title 'Top displacemement' with lines +plot "precice-Solid-Upstream-watchpoint-flap_tip.log" using 1:4 title 'Top displacemement' with lines EOF diff --git a/multiple-perpendicular-flaps/solid-right-dealii/run.sh b/multiple-perpendicular-flaps/solid-upstream-dealii/run.sh similarity index 100% rename from multiple-perpendicular-flaps/solid-right-dealii/run.sh rename to multiple-perpendicular-flaps/solid-upstream-dealii/run.sh diff --git a/oscillator-overlap/README.md b/oscillator-overlap/README.md new file mode 100644 index 000000000..eccf9137e --- /dev/null +++ b/oscillator-overlap/README.md @@ -0,0 +1,48 @@ +--- +title: Oscillator (overlapping domain decomposition) +permalink: tutorials-oscillator-overlap.html +keywords: Python, ODE +summary: We solve an oscillator with two masses in a partitioned fashion with overlapping domain decomposition. Each mass is solved by an independent ODE. +--- + +{% note %} +Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/oscillator-overlap). Read how in the [tutorials introduction](https://www.precice.org/tutorials.html). +{% endnote %} + +## Setup + +This tutorial solves the same problem as the [oscillator tutorial](https://precice.org/tutorials-oscillator.html), but applies a different domain decomposition strategy. See the oscillator tutorial for details on the general setup. The partitioning of the mass-spring system is shown here: + +![Schematic drawing of oscillator example with overlapping domain decomposition](images/tutorials-oscillator-overlap-dd.png) + +Note that this case applies an overlapping Schwarz-type coupling method and not (like most other tutorials in this repository) a Dirichlet-Neumann coupling. This results in a symmetric setup of the solvers. We will refer to the solver computing the trajectory of $m_1$ as `Mass-Left` and to the solver computing the trajectory of $m_2$ as `Mass-Right`. For more information, please refer to [1]. + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-oscillator-overlap-precice-config.png) + +## Available solvers + +This tutorial is only available in Python. You need to have preCICE and the Python bindings installed on your system. + +- *Python*: An example solver using the preCICE [Python bindings](https://www.precice.org/installation-bindings-python.html). This solver also depends on the Python libraries `numpy`, which you can get from your system package manager or with `pip3 install --user `. + +## Running the Simulation + +### Python + +Open two separate terminals and start both participants by calling: + +```bash +cd python +./run.sh -l +``` + +and + +```bash +cd python +./run.sh -r +``` diff --git a/oscillator-overlap/clean-tutorial.sh b/oscillator-overlap/clean-tutorial.sh new file mode 120000 index 000000000..4713f5092 --- /dev/null +++ b/oscillator-overlap/clean-tutorial.sh @@ -0,0 +1 @@ +../tools/clean-tutorial-base.sh \ No newline at end of file diff --git a/oscillator-overlap/images/tutorials-oscillator-overlap-dd.pdf b/oscillator-overlap/images/tutorials-oscillator-overlap-dd.pdf new file mode 100644 index 000000000..6d9cad947 Binary files /dev/null and b/oscillator-overlap/images/tutorials-oscillator-overlap-dd.pdf differ diff --git a/oscillator-overlap/images/tutorials-oscillator-overlap-dd.png b/oscillator-overlap/images/tutorials-oscillator-overlap-dd.png new file mode 100644 index 000000000..d794e16d3 Binary files /dev/null and b/oscillator-overlap/images/tutorials-oscillator-overlap-dd.png differ diff --git a/oscillator-overlap/images/tutorials-oscillator-overlap-dd.tex b/oscillator-overlap/images/tutorials-oscillator-overlap-dd.tex new file mode 100644 index 000000000..c84a3d74b --- /dev/null +++ b/oscillator-overlap/images/tutorials-oscillator-overlap-dd.tex @@ -0,0 +1,37 @@ +\documentclass{standalone} +\usepackage{tikz} +\usetikzlibrary{positioning,calc,patterns,decorations.pathmorphing} + +\begin{document} + +\begin{tikzpicture} + \tikzstyle{spring}=[thick,decorate,decoration={zigzag,pre length=0.3cm,post length=0.3cm,segment length=6}] + \tikzstyle{ground}=[fill,pattern=north east lines,draw=none,minimum width=0.75cm,minimum height=0.3cm] + \tikzstyle{mass}=[draw, fill=gray!25, thick, minimum width=1cm, minimum height=1cm] + \node (W1) [ground, rotate=-90, minimum width=3cm] {}; + \node (M1) [mass, right= 2cm of W1.north] {$m_1$}; + \node (M2fake) [circle, draw=black, fill=gray!25, right= 2cm of M1] {}; + + \draw [dashed] (M2fake.north) -- ++ (0,.5); + \draw [->] ($(M2fake.north) + (0,.25)$) -- node[above](U2ToM1){$u_2$} ++ (1,0); + \draw [dashed] (M1.north) -- ++ (0,.5); + \draw [->] ($(M1.north) + (0,.25)$) -- node[above](U1FromM1){$u_1$} ++ (1,0); + \draw [spring] (W1.north) -- node[above]{$k_1$}(M1.west); + \draw [spring] (M1.east) -- node[above]{$k_{12}$}(M2fake.west); + + \node (M1fake) [circle, draw=black, fill=gray!25, right= 1cm of M2fake] {}; + \node (M2) [mass, right= 2cm of M1fake] {$m_2$}; + \draw [dashed] (M2.north) -- ++ (0,.5); + \draw [->] ($(M2.north) + (0,.25)$) -- node[above](U2FromM2){$u_2$} ++ (1,0); + \draw [dashed] (M1fake.north) -- ++ (0,.5); + \draw [->] ($(M1fake.north) + (0,.25)$) -- node[above](U1ToM2){$u_1$} ++ (1,0); + + \node (W2) [ground, rotate=90, minimum width=3cm, right= 2cm of M2, xshift=-1.5cm] {}; + \draw [spring] (M2.east) -- node[above]{$k_2$}(W2.north); + \draw [spring] (M1fake.east) -- node[below]{$k_{12}$}(M2.west); + + \draw[](U2FromM2.north) edge[->,out=135, in=45] node[above right]{ghost layer for $m_1$} (U2ToM1.north); + \draw[](U1FromM1.north) edge[->,out=45, in=135] node[above left]{ghost layer for $m_2$} (U1ToM2.north); + +\end{tikzpicture} +\end{document} diff --git a/oscillator-overlap/images/tutorials-oscillator-overlap-precice-config.png b/oscillator-overlap/images/tutorials-oscillator-overlap-precice-config.png new file mode 100644 index 000000000..f68475192 Binary files /dev/null and b/oscillator-overlap/images/tutorials-oscillator-overlap-precice-config.png differ diff --git a/oscillator-overlap/mass-left-python/clean.sh b/oscillator-overlap/mass-left-python/clean.sh new file mode 100755 index 000000000..91d01fde7 --- /dev/null +++ b/oscillator-overlap/mass-left-python/clean.sh @@ -0,0 +1,9 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +rm -rfv ./output/ + +clean_precice_logs . +clean_case_logs . diff --git a/oscillator-overlap/mass-left-python/run.sh b/oscillator-overlap/mass-left-python/run.sh new file mode 100755 index 000000000..d2e5f9515 --- /dev/null +++ b/oscillator-overlap/mass-left-python/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 ../solver-python/oscillator.py Mass-Left + +close_log diff --git a/oscillator-overlap/mass-right-python/clean.sh b/oscillator-overlap/mass-right-python/clean.sh new file mode 100755 index 000000000..91d01fde7 --- /dev/null +++ b/oscillator-overlap/mass-right-python/clean.sh @@ -0,0 +1,9 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +rm -rfv ./output/ + +clean_precice_logs . +clean_case_logs . diff --git a/oscillator-overlap/mass-right-python/run.sh b/oscillator-overlap/mass-right-python/run.sh new file mode 100755 index 000000000..4bd290c63 --- /dev/null +++ b/oscillator-overlap/mass-right-python/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 ../solver-python/oscillator.py Mass-Right + +close_log diff --git a/oscillator-overlap/precice-config.xml b/oscillator-overlap/precice-config.xml new file mode 100644 index 000000000..c745c603e --- /dev/null +++ b/oscillator-overlap/precice-config.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/oscillator-overlap/solver-python/oscillator.py b/oscillator-overlap/solver-python/oscillator.py new file mode 100644 index 000000000..52bc3fa4c --- /dev/null +++ b/oscillator-overlap/solver-python/oscillator.py @@ -0,0 +1,190 @@ +from __future__ import division + +import argparse +import numpy as np +from numpy.linalg import eig +import precice +from enum import Enum +import csv +import os + +import problemDefinition + + +class Scheme(Enum): + NEWMARK_BETA = "Newmark_beta" + GENERALIZED_ALPHA = "generalized_alpha" + + +class Participant(Enum): + MASS_LEFT = "Mass-Left" + MASS_RIGHT = "Mass-Right" + + +parser = argparse.ArgumentParser() +parser.add_argument("participantName", help="Name of the solver.", type=str, choices=[p.value for p in Participant]) +parser.add_argument("-ts", "--time-stepping", help="Time stepping scheme being used.", type=str, + choices=[s.value for s in Scheme], default=Scheme.NEWMARK_BETA.value) +args = parser.parse_args() + +participant_name = args.participantName + +if participant_name == Participant.MASS_LEFT.value: + write_data_name = 'Displacement-Left' + read_data_name = 'Displacement-Right' + mesh_name = 'Mass-Left-Mesh' + + this_mass = problemDefinition.MassLeft + this_spring = problemDefinition.SpringLeft + connecting_spring = problemDefinition.SpringMiddle + other_mass = problemDefinition.MassRight + +elif participant_name == Participant.MASS_RIGHT.value: + read_data_name = 'Displacement-Left' + write_data_name = 'Displacement-Right' + mesh_name = 'Mass-Right-Mesh' + + this_mass = problemDefinition.MassRight + this_spring = problemDefinition.SpringRight + connecting_spring = problemDefinition.SpringMiddle + other_mass = problemDefinition.MassLeft + +else: + raise Exception(f"wrong participant name: {participant_name}") + +mass = this_mass.m +stiffness = this_spring.k + connecting_spring.k +u0, v0, f0, d_dt_f0 = this_mass.u0, this_mass.v0, connecting_spring.k * other_mass.u0, connecting_spring.k * other_mass.v0 + +num_vertices = 1 # Number of vertices + +solver_process_index = 0 +solver_process_size = 1 + +configuration_file_name = "../precice-config.xml" + +participant = precice.Participant(participant_name, configuration_file_name, solver_process_index, solver_process_size) + +dimensions = participant.get_mesh_dimensions(mesh_name) + +vertex = np.zeros(dimensions) +read_data = np.zeros(num_vertices) +write_data = connecting_spring.k * u0 * np.ones(num_vertices) + +vertex_ids = [participant.set_mesh_vertex(mesh_name, vertex)] + +if participant.requires_initial_data(): + participant.write_data(mesh_name, write_data_name, vertex_ids, write_data) + +participant.initialize() +precice_dt = participant.get_max_time_step_size() +my_dt = precice_dt # use my_dt < precice_dt for subcycling + +# Initial Conditions +a0 = (f0 - stiffness * u0) / mass +u = u0 +v = v0 +a = a0 +t = 0 + +# Generalized Alpha Parameters +if args.time_stepping == Scheme.GENERALIZED_ALPHA.value: + alpha_f = 0.4 + alpha_m = 0.2 +elif args.time_stepping == Scheme.NEWMARK_BETA.value: + alpha_f = 0.0 + alpha_m = 0.0 +m = 3 * [None] # will be computed for each timestep depending on dt +gamma = 0.5 - alpha_m + alpha_f +beta = 0.25 * (gamma + 0.5) + +positions = [] +velocities = [] +times = [] + +u_write = [u] +v_write = [v] +t_write = [t] + +while participant.is_coupling_ongoing(): + if participant.requires_writing_checkpoint(): + u_cp = u + v_cp = v + a_cp = a + t_cp = t + # store data for plotting and postprocessing + positions += u_write + velocities += v_write + times += t_write + + # compute time step size for this time step + precice_dt = participant.get_max_time_step_size() + dt = np.min([precice_dt, my_dt]) + read_time = (1 - alpha_f) * dt + read_data = participant.read_data(mesh_name, read_data_name, vertex_ids, read_time) + f = connecting_spring.k * read_data[0] + + # do generalized alpha step + m[0] = (1 - alpha_m) / (beta * dt**2) + m[1] = (1 - alpha_m) / (beta * dt) + m[2] = (1 - alpha_m - 2 * beta) / (2 * beta) + k_bar = stiffness * (1 - alpha_f) + m[0] * mass + u_new = (f - alpha_f * stiffness * u + mass * (m[0] * u + m[1] * v + m[2] * a)) / k_bar + a_new = 1.0 / (beta * dt**2) * (u_new - u - dt * v) - (1 - 2 * beta) / (2 * beta) * a + v_new = v + dt * ((1 - gamma) * a + gamma * a_new) + t_new = t + dt + + write_data = [u_new] + + participant.write_data(mesh_name, write_data_name, vertex_ids, write_data) + + participant.advance(dt) + + if participant.requires_reading_checkpoint(): + u = u_cp + v = v_cp + a = a_cp + t = t_cp + # empty buffers for next window + u_write = [] + v_write = [] + t_write = [] + + else: + u = u_new + v = v_new + a = a_new + t = t_new + + # write data to buffers + u_write.append(u) + v_write.append(v) + t_write.append(t) + +# store final result +u = u_new +v = v_new +a = a_new +u_write.append(u) +v_write.append(v) +t_write.append(t) +positions += u_write +velocities += v_write +times += t_write + +participant.finalize() + +# print errors +error = np.max(abs(this_mass.u_analytical(np.array(times)) - np.array(positions))) +print("Error w.r.t analytical solution:") +print(f"{my_dt},{error}") + +# output trajectory +if not os.path.exists("output"): + os.makedirs("output") + +with open(f'output/trajectory-{participant_name}.csv', 'w') as file: + csv_write = csv.writer(file, delimiter=';') + csv_write.writerow(['time', 'position', 'velocity']) + for t, u, v in zip(times, positions, velocities): + csv_write.writerow([t, u, v]) diff --git a/oscillator-overlap/solver-python/problemDefinition.py b/oscillator-overlap/solver-python/problemDefinition.py new file mode 100644 index 000000000..b0ac2aea3 --- /dev/null +++ b/oscillator-overlap/solver-python/problemDefinition.py @@ -0,0 +1,68 @@ +import numpy as np +from numpy.linalg import eig + + +class SpringLeft: + k = 4 * np.pi**2 + + +class SpringMiddle: + k = 16 * (np.pi**2) + + +class SpringRight: + k = 4 * np.pi**2 + + +class MassLeft: + # mass + m = 1 + + # initial conditions (the way how we currently compute the analytical + # solution allows arbitrary u0, but requires v0 = 0) + u0 = 1.0 + v0 = 0.0 + + u_analytical, v_analytical = None, None # will be defined below + + +class MassRight: + # mass + m = 1 + + # initial conditions (the way how we currently compute the analytical + # solution allows arbitrary u0, but requires v0 = 0) + u0 = 0.0 + v0 = 0.0 + + u_analytical, v_analytical = None, None # will be defined below + + +# Mass matrix +M = np.array([ + [MassLeft.m, 0], + [0, MassRight.m] +]) +# Stiffness matrix +K = np.array([ + [SpringLeft.k + SpringMiddle.k, -SpringMiddle.k], + [-SpringMiddle.k, SpringRight.k + SpringMiddle.k] +]) + +# system: +# m ddu + k u = f +# compute analytical solution from eigenvalue ansatz + +eigenvalues, eigenvectors = eig(K) +omega = np.sqrt(eigenvalues) +A, B = eigenvectors + +c = np.linalg.solve(eigenvectors, [MassLeft.u0, MassRight.u0]) + +MassLeft.u_analytical = lambda t: c[0] * A[0] * np.cos(omega[0] * t) + c[1] * A[1] * np.cos(omega[1] * t) +MassLeft.v_analytical = lambda t: -c[0] * A[0] * omega[0] * \ + np.sin(omega[0] * t) - c[1] * A[1] * omega[1] * np.sin(omega[1] * t) + +MassRight.u_analytical = lambda t: c[0] * B[0] * np.cos(omega[0] * t) + c[1] * B[1] * np.cos(omega[1] * t) +MassRight.v_analytical = lambda t: -c[0] * B[0] * omega[0] * \ + np.sin(omega[0] * t) - c[1] * B[1] * omega[1] * np.sin(omega[1] * t) diff --git a/oscillator/.gitignore b/oscillator/.gitignore new file mode 100644 index 000000000..69310321e --- /dev/null +++ b/oscillator/.gitignore @@ -0,0 +1 @@ +fmi/Oscillator.fmu diff --git a/oscillator/README.md b/oscillator/README.md new file mode 100644 index 000000000..280cd1cc4 --- /dev/null +++ b/oscillator/README.md @@ -0,0 +1,73 @@ +--- +title: Oscillator +permalink: tutorials-oscillator.html +keywords: Python, ODE, FMI +summary: We solve an oscillator with two masses in a partitioned fashion. Each mass is solved by an independent ODE. +--- + +{% note %} +Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/oscillator). Read how in the [tutorials introduction](https://www.precice.org/tutorials.html). +{% endnote %} + +## Setup + +This tutorial solves a simple mass-spring oscillator with two masses and three springs. The system is cut at the middle spring and solved in a partitioned fashion: + +![Schematic drawing of oscillator example](images/tutorials-oscillator-schematic-drawing.png) + +Note that this case applies a Schwarz-type coupling method and not (like most other tutorials in this repository) a Dirichlet-Neumann coupling. This results in a symmetric setup of the solvers. We will refer to the solver computing the trajectory of $m_1$ as `Mass-Left` and to the solver computing the trajectory of $m_2$ as `Mass-Right`. For more information, please refer to [1]. + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-oscillator-precice-config.png) + +## Available solvers + +There are two different implementations: + +- *Python*: A solver using the preCICE [Python bindings](https://www.precice.org/installation-bindings-python.html). This solver also depends on the Python libraries `numpy`, which you can get from your system package manager or with `pip3 install --user `. Using the option `-ts` allows you to pick the time stepping scheme being used. Available choices are Newmark beta, generalized alpha, explicit Runge Kutta 4, and implicit RadauIIA. The solver uses subcycling: Each participant performs 4 time steps in each time window. The data of these 4 substeps is then used by preCICE to create a third order B-spline interpolation (`waveform-degree="3"` in `precice-config.xml`). +- *FMI*: A solver using the [preCICE-FMI runner](https://github.com/precice/fmi-runner) (requires at least v0.2). The Runner executes the FMU model `Oscillator.fmu` for computation. The provided run scripts (see below) build this model if not already there. For more information, please refer to [2]. + +## Running the simulation + +Open two separate terminals and start both participants. For example, you can run a simulation where the left participant is computed in Python and the right participant is computed with FMI with these commands: + +```bash +cd mass-left-python +./run.sh +``` + +and + +```bash +cd mass-right-fmi +./run.sh +``` + +Of course, you can also use the same solver for both sides. + +## Post-processing + +Each simulation run creates two files containing position and velocity of the two masses over time. These files are called `trajectory-Mass-Left.csv` and `trajectory-Mass-Right.csv`. You can use the script `plot-trajectory.py` for post-processing. Type `python3 plot-trajectory --help` to see available options. You can, for example, plot the trajectory of the left mass of the Python solver by running + +```bash +python3 plot-trajectory.py mass-left-python/output/trajectory-Mass-Left.csv TRAJECTORY +``` + +The solvers allow you to study the effect of different time stepping schemes on energy conservation. Newmark beta conserves energy: + +![Trajectory for Newmark beta scheme](images/tutorials-oscillator-trajectory-newmark-beta.png) + +Generalized alpha does not conserve energy: + +![Trajectory for generalized alpha scheme](images/tutorials-oscillator-trajectory-generalized-alpha.png) + +For details, refer to [1]. + +## References + +[1] V. Schüller, B. Rodenberg, B. Uekermann and H. Bungartz, A Simple Test Case for Convergence Order in Time and Energy Conservation of Black-Box Coupling Schemes, in: WCCM-APCOM2022. [URL](https://www.scipedia.com/public/Rodenberg_2022a) + +[2] L. Willeke, D. Schneider and B. Uekermann, A preCICE-FMI Runner to Couple FMUs to PDE-Based Simulations, Proceedings 15th Intern. Modelica Conference, 2023. [DOI](https://doi.org/10.3384/ecp204479) diff --git a/oscillator/clean-tutorial.sh b/oscillator/clean-tutorial.sh new file mode 120000 index 000000000..4713f5092 --- /dev/null +++ b/oscillator/clean-tutorial.sh @@ -0,0 +1 @@ +../tools/clean-tutorial-base.sh \ No newline at end of file diff --git a/oscillator/images/tutorials-oscillator-precice-config.png b/oscillator/images/tutorials-oscillator-precice-config.png new file mode 100644 index 000000000..560d48796 Binary files /dev/null and b/oscillator/images/tutorials-oscillator-precice-config.png differ diff --git a/oscillator/images/tutorials-oscillator-schematic-drawing.png b/oscillator/images/tutorials-oscillator-schematic-drawing.png new file mode 100644 index 000000000..de356f085 Binary files /dev/null and b/oscillator/images/tutorials-oscillator-schematic-drawing.png differ diff --git a/oscillator/images/tutorials-oscillator-schematic-drawing.tex b/oscillator/images/tutorials-oscillator-schematic-drawing.tex new file mode 100644 index 000000000..c404eb257 --- /dev/null +++ b/oscillator/images/tutorials-oscillator-schematic-drawing.tex @@ -0,0 +1,80 @@ +\documentclass{standalone} +\usepackage{tikz} +\usetikzlibrary{patterns,decorations.pathmorphing} + +\definecolor{color1}{HTML}{008b8b} +\definecolor{color2}{HTML}{808000} +\begin{document} +\begin{tikzpicture}[scale=1] + % left wall + \coordinate (wall1) at (0.2,1.5); + \fill [pattern = north west lines] (0,0) rectangle ++(.2,3); + \draw[thick] (0.2,0) -- (wall1) -- ++(0,1.5); + % right wall + \coordinate (wall2) at (8.2,1.5); + \fill [pattern = north west lines] (8.2,0) rectangle ++(.2,3); + \draw[thick] (8.2,0) -- (wall2) -- ++ (0,1.5); + % Mass 1 + \node[draw, + minimum width=1cm, + minimum height=0.75cm, + anchor=mid] (mass1) at (2.7,1.5) {$m_1$}; + % Mass 2 + \node[draw, + minimum width=1cm, + minimum height=0.75cm, + anchor=mid](mass2) at (5.7,1.5) {$m_2$}; + % spring 1 + \draw + [ + decoration={ + coil, + aspect=0.3, + segment length=1.5mm, + amplitude=2mm, + pre length=3mm, + post length=3mm}, + decorate + ] (0.2,1.5) -- (mass1.west) + node[midway,below=0.25cm,black]{$k_1$}; + % spring 12 + \draw + [ + decoration={ + coil, + aspect=0.3, + segment length=1.5mm, + amplitude=2mm, + pre length=3mm, + post length=3mm}, + decorate + ] (mass1.east) -- (mass2.west) + node[midway,below=0.25cm,black,xshift=0.35cm]{$k_{12}$}; + % spring 2 + \draw + [ + decoration={ + coil, + aspect=0.3, + segment length=1.5mm, + amplitude=2mm, + pre length=3mm, + post length=3mm}, + decorate + ] (mass2.east) -- (wall2) node[midway,below=0.25cm,black]{$k_{2}$}; + + % u1 arrow + \draw [very thick, + color1, + -latex + ] (mass1.north) -- ++(0,.5) ++(0,-0.25) -- ++ (1,0) + node[midway,above]{\small $u_1$}; + + % u2 arrow + \draw [very thick, + color2, + -latex + ] (mass2.north) -- ++(0,.5) ++(0,-0.25) -- ++ (1,0) + node[midway,above]{\small $u_2$}; +\end{tikzpicture} +\end{document} \ No newline at end of file diff --git a/oscillator/images/tutorials-oscillator-trajectory-generalized-alpha.png b/oscillator/images/tutorials-oscillator-trajectory-generalized-alpha.png new file mode 100644 index 000000000..100b8a9ba Binary files /dev/null and b/oscillator/images/tutorials-oscillator-trajectory-generalized-alpha.png differ diff --git a/oscillator/images/tutorials-oscillator-trajectory-newmark-beta.png b/oscillator/images/tutorials-oscillator-trajectory-newmark-beta.png new file mode 100644 index 000000000..44e47e1e6 Binary files /dev/null and b/oscillator/images/tutorials-oscillator-trajectory-newmark-beta.png differ diff --git a/oscillator/mass-left-fmi/clean.sh b/oscillator/mass-left-fmi/clean.sh new file mode 100755 index 000000000..91d01fde7 --- /dev/null +++ b/oscillator/mass-left-fmi/clean.sh @@ -0,0 +1,9 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +rm -rfv ./output/ + +clean_precice_logs . +clean_case_logs . diff --git a/oscillator/mass-left-fmi/fmi-settings.json b/oscillator/mass-left-fmi/fmi-settings.json new file mode 100644 index 000000000..dc4d752c2 --- /dev/null +++ b/oscillator/mass-left-fmi/fmi-settings.json @@ -0,0 +1,20 @@ +{ + "model_params": { + "mass.m": 1, + "spring_fixed.c": 39.4784176044, + "spring_middle.c": 157.913670417 + }, + "initial_conditions": { + "mass.u": 1, + "mass.v": 0, + "mass.a": -197.392088022 + }, + "simulation_params": { + "fmu_file_name": "../solver-fmi/Oscillator.fmu", + "output_file_name": "./output/trajectory-Mass-Left.csv", + "output": ["mass.u", "mass.v"], + "fmu_read_data_names": ["force_in"], + "fmu_write_data_names": ["force_out"], + "fmu_instance_name": "instance_left" + } +} diff --git a/oscillator/mass-left-fmi/precice-settings.json b/oscillator/mass-left-fmi/precice-settings.json new file mode 100644 index 000000000..48e3bb98c --- /dev/null +++ b/oscillator/mass-left-fmi/precice-settings.json @@ -0,0 +1,9 @@ +{ + "coupling_params": { + "participant_name": "Mass-Left", + "config_file_name": "../precice-config.xml", + "mesh_name": "Mass-Left-Mesh", + "write_data_name": "Force-Left", + "read_data_name": "Force-Right" + } +} diff --git a/oscillator/mass-left-fmi/run.sh b/oscillator/mass-left-fmi/run.sh new file mode 100755 index 000000000..804b17b24 --- /dev/null +++ b/oscillator/mass-left-fmi/run.sh @@ -0,0 +1,22 @@ +#!/bin/bash +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 +fi + +fmiprecice fmi-settings.json precice-settings.json +python3 ../solver-fmi/calculate-error.py ../mass-left-fmi/fmi-settings.json ../mass-left-fmi/precice-settings.json ../mass-right-fmi/fmi-settings.json ../mass-right-fmi/precice-settings.json Mass-Left + +close_log diff --git a/oscillator/mass-left-python/clean.sh b/oscillator/mass-left-python/clean.sh new file mode 100755 index 000000000..d4e26a453 --- /dev/null +++ b/oscillator/mass-left-python/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_fmi . diff --git a/oscillator/mass-left-python/run.sh b/oscillator/mass-left-python/run.sh new file mode 100755 index 000000000..d2e5f9515 --- /dev/null +++ b/oscillator/mass-left-python/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 ../solver-python/oscillator.py Mass-Left + +close_log diff --git a/oscillator/mass-right-fmi/clean.sh b/oscillator/mass-right-fmi/clean.sh new file mode 100755 index 000000000..c7e3552ac --- /dev/null +++ b/oscillator/mass-right-fmi/clean.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +rm -rfv ./output/ + +clean_precice_logs . diff --git a/oscillator/mass-right-fmi/fmi-settings.json b/oscillator/mass-right-fmi/fmi-settings.json new file mode 100644 index 000000000..fc59edc20 --- /dev/null +++ b/oscillator/mass-right-fmi/fmi-settings.json @@ -0,0 +1,20 @@ +{ + "model_params": { + "mass.m": 1, + "spring_fixed.c": 39.4784176044, + "spring_middle.c": 157.913670417 + }, + "initial_conditions": { + "mass.u": 0, + "mass.v": 0, + "mass.a": 157.913670417 + }, + "simulation_params": { + "fmu_file_name": "../solver-fmi/Oscillator.fmu", + "output_file_name": "./output/trajectory-Mass-Right.csv", + "output": ["mass.u", "mass.v"], + "fmu_read_data_names": ["force_in"], + "fmu_write_data_names": ["force_out"], + "fmu_instance_name": "instance_right" + } +} diff --git a/oscillator/mass-right-fmi/precice-settings.json b/oscillator/mass-right-fmi/precice-settings.json new file mode 100644 index 000000000..0142520b9 --- /dev/null +++ b/oscillator/mass-right-fmi/precice-settings.json @@ -0,0 +1,9 @@ +{ + "coupling_params": { + "participant_name": "Mass-Right", + "config_file_name": "../precice-config.xml", + "mesh_name": "Mass-Right-Mesh", + "write_data_name": "Force-Right", + "read_data_name": "Force-Left" + } +} diff --git a/oscillator/mass-right-fmi/run.sh b/oscillator/mass-right-fmi/run.sh new file mode 100755 index 000000000..a423d5f69 --- /dev/null +++ b/oscillator/mass-right-fmi/run.sh @@ -0,0 +1,22 @@ +#!/bin/bash +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 +fi + +fmiprecice fmi-settings.json precice-settings.json +python3 ../solver-fmi/calculate-error.py ../mass-left-fmi/fmi-settings.json ../mass-left-fmi/precice-settings.json ../mass-right-fmi/fmi-settings.json ../mass-right-fmi/precice-settings.json Mass-Right + +close_log diff --git a/oscillator/mass-right-python/clean.sh b/oscillator/mass-right-python/clean.sh new file mode 100755 index 000000000..c7e3552ac --- /dev/null +++ b/oscillator/mass-right-python/clean.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +rm -rfv ./output/ + +clean_precice_logs . diff --git a/oscillator/mass-right-python/run.sh b/oscillator/mass-right-python/run.sh new file mode 100755 index 000000000..4bd290c63 --- /dev/null +++ b/oscillator/mass-right-python/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 ../solver-python/oscillator.py Mass-Right + +close_log diff --git a/oscillator/plot-trajectory.py b/oscillator/plot-trajectory.py new file mode 100644 index 000000000..dd26e43c5 --- /dev/null +++ b/oscillator/plot-trajectory.py @@ -0,0 +1,55 @@ +import pandas as pd +from matplotlib import pyplot as plt +import argparse +from enum import Enum + + +class PlotType(Enum): + U_OVER_T = "position over time" + V_OVER_T = "velocity over time" + TRAJECTORY = "velocity over position (trajectory)" + + +parser = argparse.ArgumentParser() +parser.add_argument("csvFile", help="CSV file.", type=str) +parser.add_argument("plotType", help="Plot type.", type=str, choices=[pt.name for pt in PlotType]) +args = parser.parse_args() + +filename = args.csvFile +split_foldername = filename.split('/') +casename = split_foldername[0] +split_casename = casename.split('-') +solver = split_casename[-1] + +if solver == 'python': + df = pd.read_csv(filename, delimiter=';') + if args.plotType == PlotType.U_OVER_T.name: + plt.plot(df['time'].to_numpy(), df['position'].to_numpy()) + plt.title(PlotType.U_OVER_T.value) + elif args.plotType == PlotType.V_OVER_T.name: + plt.plot(df['time'].to_numpy(), df['velocity'].to_numpy()) + plt.title(PlotType.V_OVER_T.value) + elif args.plotType == PlotType.TRAJECTORY.name: + plt.plot(df['position'].to_numpy(), df['velocity'].to_numpy()) + plt.scatter([df['position'][0]], [df['velocity'][0]], label=f"(u,v) at t={df['time'][0]}") + plt.scatter([df['position'].iloc[-1]], [df['velocity'].iloc[-1]], + label=f"(u,v) at t={df['time'].iloc[-1]}", marker="*") + plt.title(PlotType.TRAJECTORY.value) + plt.legend() +elif solver == 'fmi': + df = pd.read_csv(filename, delimiter=',') + if args.plotType == PlotType.U_OVER_T.name: + plt.plot(df['time'].to_numpy(), df['mass.u'].to_numpy()) + plt.title(PlotType.U_OVER_T.value) + elif args.plotType == PlotType.V_OVER_T.name: + plt.plot(df['time'].to_numpy(), df['mass.v'].to_numpy()) + plt.title(PlotType.V_OVER_T.value) + elif args.plotType == PlotType.TRAJECTORY.name: + plt.plot(df[('mass.u')].to_numpy(), df['mass.v'].to_numpy()) + plt.scatter([df['mass.u'][0]], [df['mass.v'][0]], label=f"(u,v) at t={df['time'][0]}") + plt.scatter([df['mass.u'].iloc[-1]], [df['mass.v'].iloc[-1]], + label=f"(u,v) at t={df['time'].iloc[-1]}", marker="*") + plt.title(PlotType.TRAJECTORY.value) + plt.legend() + +plt.show() diff --git a/oscillator/precice-config.xml b/oscillator/precice-config.xml new file mode 100644 index 000000000..384e1a86d --- /dev/null +++ b/oscillator/precice-config.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/oscillator/solver-fmi/calculate-error.py b/oscillator/solver-fmi/calculate-error.py new file mode 100644 index 000000000..baecc291b --- /dev/null +++ b/oscillator/solver-fmi/calculate-error.py @@ -0,0 +1,93 @@ +import numpy as np +import pandas as pd +import json +import os +import argparse +from enum import Enum +import sys + + +class Participant(Enum): + MASS_LEFT = "Mass-Left" + MASS_RIGHT = "Mass-Right" + + +parser = argparse.ArgumentParser() +parser.add_argument("fmi_setting_file_left", help="Path to the fmi setting file for MassLeft.", type=str) +parser.add_argument("precice_setting_file_left", help="Path to the precice setting file for MassLeft.", type=str) +parser.add_argument("fmi_setting_file_right", help="Path to the fmi setting file for MassRight.", type=str) +parser.add_argument("precice_setting_file_right", help="Path to the precice setting file for MassRight.", type=str) +parser.add_argument("participant_name", help="Participant for which the error should be calculated", type=str, + choices=[p.value for p in Participant]) +args = parser.parse_args() + +# Get input files +fmi_file_left = args.fmi_setting_file_left +precice_file_left = args.precice_setting_file_left +fmi_file_right = args.fmi_setting_file_right +precice_file_right = args.precice_setting_file_right +participant_name = args.participant_name + +# Read json files +folder = os.path.dirname(os.path.join(os.getcwd(), os.path.dirname(sys.argv[0]), fmi_file_left)) +path = os.path.join(folder, os.path.basename(fmi_file_left)) +read_file = open(path, "r") +fmi_data_left = json.load(read_file) + +folder = os.path.dirname(os.path.join(os.getcwd(), os.path.dirname(sys.argv[0]), precice_file_left)) +path = os.path.join(folder, os.path.basename(precice_file_left)) +read_file = open(path, "r") +precice_data_left = json.load(read_file) + +folder = os.path.dirname(os.path.join(os.getcwd(), os.path.dirname(sys.argv[0]), fmi_file_right)) +path = os.path.join(folder, os.path.basename(fmi_file_right)) +read_file = open(path, "r") +fmi_data_right = json.load(read_file) + +folder = os.path.dirname(os.path.join(os.getcwd(), os.path.dirname(sys.argv[0]), precice_file_right)) +path = os.path.join(folder, os.path.basename(precice_file_right)) +read_file = open(path, "r") +precice_data_right = json.load(read_file) + + +# Define variables +k_1 = fmi_data_left["model_params"]["spring_fixed.c"] +k_2 = fmi_data_right["model_params"]["spring_fixed.c"] +u0_1 = fmi_data_left["initial_conditions"]["mass.u"] +u0_2 = fmi_data_right["initial_conditions"]["mass.u"] +k_12_left = fmi_data_left["model_params"]["spring_middle.c"] +k_12_right = fmi_data_right["model_params"]["spring_middle.c"] + +if k_12_left == k_12_right: + k_12 = k_12_left +else: + raise Exception("k_12 has to be equal in both participants. Please adjust input values.") + + +# Define analytical solution and read computed results +K = np.array([[k_1 + k_12, -k_12], [-k_12, k_2 + k_12]]) +eigenvalues, eigenvectors = np.linalg.eig(K) +omega = np.sqrt(eigenvalues) +A, B = eigenvectors +c = np.linalg.solve(eigenvectors, [u0_1, u0_2]) + +if participant_name == Participant.MASS_LEFT.value: + filename = fmi_data_left["simulation_params"]["output_file_name"] + df = pd.read_csv(filename, delimiter=',') + + def u_analytical(t): return c[0] * A[0] * np.cos(omega[0] * t) + c[1] * A[1] * np.cos(omega[1] * t) + +elif participant_name == Participant.MASS_RIGHT.value: + filename = fmi_data_right["simulation_params"]["output_file_name"] + df = pd.read_csv(filename, delimiter=',') + + def u_analytical(t): return c[0] * B[0] * np.cos(omega[0] * t) + c[1] * B[1] * np.cos(omega[1] * t) + +times = df.iloc[:, 0] +positions = df.iloc[:, 1] + + +# Calculate error +error = np.max(abs(u_analytical(np.array(times)) - np.array(positions))) +print("Error w.r.t analytical solution:") +print(f"{error}") diff --git a/oscillator/solver-fmi/fmu/CMakeLists.txt b/oscillator/solver-fmi/fmu/CMakeLists.txt new file mode 100644 index 000000000..974cef937 --- /dev/null +++ b/oscillator/solver-fmi/fmu/CMakeLists.txt @@ -0,0 +1,273 @@ +cmake_minimum_required (VERSION 3.16) + +set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + +FUNCTION(cat IN_FILE OUT_FILE) + file(READ ${IN_FILE} CONTENTS) + file(APPEND ${OUT_FILE} "${CONTENTS}") +ENDFUNCTION() + +project (Reference-FMUs) + +find_package (Python3) +find_package (Git) + +set(FMI_VERSION 2 CACHE STRING "FMI Version") +set_property(CACHE FMI_VERSION PROPERTY STRINGS 1 2 3) + +set(FMI_TYPE ME CACHE STRING "FMI Type (FMI 1.0 only)") +set_property(CACHE FMI_TYPE PROPERTY STRINGS ME CS) + +if (${FMI_VERSION} GREATER 1) + set(FMI_TYPE "") +endif () + +set(WITH_FMUSIM OFF CACHE BOOL "Add fmusim project") + +if (MSVC) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) + + # Minimum supported MSVC version is 1800 = Visual Studio 12.0/2013 + # See also https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html + if (MSVC_VERSION VERSION_LESS 1800) + message (SEND_ERROR "MSVC_VERSION ${MSVC_VERSION} is not a supported Visual Studio compiler version. Please use Visual Studio 2013 or any later version.") + endif () +endif () + +add_compile_definitions(FMI_VERSION=${FMI_VERSION}) + +if (${FMI_VERSION} GREATER 2) + + if (WIN32) + set(FMI_PLATFORM windows) + elseif (APPLE) + set(FMI_PLATFORM darwin) + else () + set(FMI_PLATFORM linux) + endif () + + if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8") + set (FMI_PLATFORM x86_64-${FMI_PLATFORM}) + else () + set (FMI_PLATFORM x86-${FMI_PLATFORM}) + endif () + +else () + + if (WIN32) + set(FMI_PLATFORM win) + elseif (APPLE) + set(FMI_PLATFORM darwin) + else () + set(FMI_PLATFORM linux) + endif () + + if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8") + set (FMI_PLATFORM ${FMI_PLATFORM}64) + else () + set (FMI_PLATFORM ${FMI_PLATFORM}32) + endif () + +endif () + +MESSAGE("FMI_PLATFORM: " ${FMI_PLATFORM}) + +if (${FMI_VERSION} LESS 3) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/all.c" "#define FMI_VERSION ${FMI_VERSION} + +#include \"fmi${FMI_VERSION}Functions.c\" +#include \"model.c\" +#include \"cosimulation.c\" +") +endif () + +set (MODEL_NAMES Oscillator) + +foreach (MODEL_NAME ${MODEL_NAMES}) + +set(TARGET_NAME ${MODEL_NAME}) + +SET(HEADERS + ${MODEL_NAME}/config.h + include/cosimulation.h + include/model.h +) + +if (${FMI_VERSION} EQUAL 2) + SET(HEADERS + ${HEADERS} + include/fmi2Functions.h + include/fmi2FunctionTypes.h + include/fmi2TypesPlatform.h + ) +elseif (${FMI_VERSION} EQUAL 3) + SET(HEADERS + ${HEADERS} + include/fmi3Functions.h + include/fmi3FunctionTypes.h + include/fmi3PlatformTypes.h + ) +endif() + +SET(SOURCES + ${MODEL_NAME}/model.c + src/fmi${FMI_VERSION}Functions.c + src/cosimulation.c +) + +add_library(${TARGET_NAME} SHARED + ${HEADERS} + ${SOURCES} + ${MODEL_NAME}/FMI${FMI_VERSION}${FMI_TYPE}.xml +) + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../..) + +target_compile_definitions(${TARGET_NAME} PRIVATE + DISABLE_PREFIX +) + +if (MSVC) + target_compile_options(${TARGET_NAME} PRIVATE /W4 /WX) +else() + target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra -Wpedantic -Werror) +endif() + +if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET_NAME} PRIVATE "-static-libgcc") +endif() + +if (CMAKE_C_COMPILER_ID STREQUAL "Intel") + target_link_options(${TARGET_NAME} PRIVATE "-static-intel" "-static-libgcc") +endif() + +if (${FMI_VERSION} EQUAL 1 AND "${FMI_TYPE}" STREQUAL CS) + target_compile_definitions(${TARGET_NAME} PRIVATE FMI_COSIMULATION) +endif() + +target_include_directories(${TARGET_NAME} PRIVATE + include + ${MODEL_NAME} +) + +set(FMU_BUILD_DIR temp/${MODEL_NAME}) + +set_target_properties(${TARGET_NAME} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + RUNTIME_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + RUNTIME_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + LIBRARY_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + LIBRARY_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + LIBRARY_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + ARCHIVE_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" + ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}" +) + +set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "") +set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${MODEL_NAME}) + +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib) + +# modelDescription.xml +add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/FMI${FMI_VERSION}${FMI_TYPE}.xml + "${FMU_BUILD_DIR}/modelDescription.xml" +) + +if (${Python3_Interpreter_FOUND} AND ${Git_FOUND}) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/set_tool_version.py" + "${FMU_BUILD_DIR}/modelDescription.xml" "${GIT_EXECUTABLE}" + ) +endif() + +# model specific header and source +foreach (SOURCE_FILE config.h model.c) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/${SOURCE_FILE}" + "${FMU_BUILD_DIR}/sources/${SOURCE_FILE}" + ) +endforeach(SOURCE_FILE) + +# documentation +if (${FMI_VERSION} EQUAL 1) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/readme.html" + "${FMU_BUILD_DIR}/documentation/_main.html" + ) +else() + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/readme.html" + "${FMU_BUILD_DIR}/documentation/index.html" + ) +endif() + +# license +add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/LICENSE.txt" + "${FMU_BUILD_DIR}/documentation/LICENSE.txt" +) + +# common headers +foreach (SOURCE_FILE model.h cosimulation.h) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/include/${SOURCE_FILE}" + "${FMU_BUILD_DIR}/sources/${SOURCE_FILE}" + ) +endforeach(SOURCE_FILE) + +# common sources +foreach (SOURCE_FILE fmi${FMI_VERSION}Functions.c cosimulation.c) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/src/${SOURCE_FILE}" + "${FMU_BUILD_DIR}/sources/${SOURCE_FILE}" + ) +endforeach(SOURCE_FILE) + +# all.c / buildDescription.xml +if (${FMI_VERSION} LESS 3) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_BINARY_DIR}/all.c" + "${FMU_BUILD_DIR}/sources/all.c" + ) +else() + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/buildDescription.xml" + "${FMU_BUILD_DIR}/sources/buildDescription.xml" + ) +endif() + +set(ARCHIVE_FILES "modelDescription.xml" "binaries" "documentation" "sources") + +if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/resources") + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/resources" + "${FMU_BUILD_DIR}/resources/" + ) + set(ARCHIVE_FILES ${ARCHIVE_FILES} "resources") +endif() + +# delete unintended files from binaries (Release configuration only) +if (MSVC) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND if $ neq 0 ( + ${CMAKE_COMMAND} -E rm -f + "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}/${MODEL_NAME}.exp" + "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}/${MODEL_NAME}.lib" + ) + ) +endif() + +# create ZIP archive +add_custom_command(TARGET ${TARGET_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E tar "cfv" ${CMAKE_CURRENT_BINARY_DIR}/${MODEL_NAME}.fmu --format=zip + ${ARCHIVE_FILES} + WORKING_DIRECTORY ${FMU_BUILD_DIR} COMMENT "Creating ZIP archive" +) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${MODEL_NAME}.fmu DESTINATION ${CMAKE_INSTALL_PREFIX}) + +endforeach(MODEL_NAME) + +if (WITH_FMUSIM) + add_subdirectory(fmusim) +endif () diff --git a/oscillator/solver-fmi/fmu/Oscillator/FMI2.xml b/oscillator/solver-fmi/fmu/Oscillator/FMI2.xml new file mode 100644 index 000000000..1a518ac3f --- /dev/null +++ b/oscillator/solver-fmi/fmu/Oscillator/FMI2.xml @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/oscillator/solver-fmi/fmu/Oscillator/FMI3.xml b/oscillator/solver-fmi/fmu/Oscillator/FMI3.xml new file mode 100644 index 000000000..27a6a02db --- /dev/null +++ b/oscillator/solver-fmi/fmu/Oscillator/FMI3.xml @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/oscillator/solver-fmi/fmu/Oscillator/buildDescription.xml b/oscillator/solver-fmi/fmu/Oscillator/buildDescription.xml new file mode 100644 index 000000000..7afd19366 --- /dev/null +++ b/oscillator/solver-fmi/fmu/Oscillator/buildDescription.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/oscillator/solver-fmi/fmu/Oscillator/config.h b/oscillator/solver-fmi/fmu/Oscillator/config.h new file mode 100644 index 000000000..e5d7f94d9 --- /dev/null +++ b/oscillator/solver-fmi/fmu/Oscillator/config.h @@ -0,0 +1,51 @@ +#ifndef config_h +#define config_h + +// define class name and unique id +#define MODEL_IDENTIFIER Oscillator +#define INSTANTIATION_TOKEN "{1AE5E10D-9521-4DE3-80B9-D0EAAA7D5AF1}" + +#define CO_SIMULATION +#define MODEL_EXCHANGE + +// define model size +#define NX 2 +#define NZ 1 + +#define SET_FLOAT64 +#define GET_OUTPUT_DERIVATIVE +#define EVENT_UPDATE + +#define FIXED_SOLVER_STEP 1e-3 +#define DEFAULT_STOP_TIME 3 + +typedef enum { + vr_time, + vr_mass_m, + vr_mass_u, + vr_mass_v, + vr_mass_a, + vr_spring_fixed_c, + vr_spring_middle_c, + vr_force_in, + vr_force_out, + vr_alpha_f, + vr_alpha_m +} ValueReference; + +typedef struct { + + double mass_m; + double mass_u; + double mass_v; + double mass_a; + double spring_fixed_c; + double spring_middle_c; + double force_in; + double force_out; + double alpha_f; + double alpha_m; + +} ModelData; + +#endif /* config_h */ diff --git a/oscillator/solver-fmi/fmu/Oscillator/model.c b/oscillator/solver-fmi/fmu/Oscillator/model.c new file mode 100644 index 000000000..26a2b8d95 --- /dev/null +++ b/oscillator/solver-fmi/fmu/Oscillator/model.c @@ -0,0 +1,171 @@ +#include "model.h" +#include // for DBL_MIN +#include // for fabs() +#include "config.h" + +#define V_MIN (0.1) +#define EVENT_EPSILON (1e-10) + +void setStartValues(ModelInstance *comp) +{ + M(mass_m) = 1; + M(mass_u) = 0; + M(mass_v) = 0; + M(spring_fixed_c) = 4 * 3.1416; + M(spring_middle_c) = 16 * 3.1416; + M(force_in) = 0; + M(force_out) = 0; + M(alpha_f) = 0; + M(alpha_m) = 0; + M(mass_a) = (M(force_in) - (M(spring_fixed_c) + M(spring_middle_c)) * M(mass_u)) / M(mass_m); +} + +Status calculateValues(ModelInstance *comp) +{ + + UNUSED(comp); + return OK; +} + +Status getFloat64(ModelInstance *comp, ValueReference vr, double *value, size_t *index) +{ + switch (vr) { + case vr_time: + value[(*index)++] = comp->time; + return OK; + case vr_mass_m: + value[(*index)++] = M(mass_m); + return OK; + case vr_mass_u: + value[(*index)++] = M(mass_u); + return OK; + case vr_mass_v: + value[(*index)++] = M(mass_v); + return OK; + case vr_mass_a: + value[(*index)++] = M(mass_a); + return OK; + case vr_spring_fixed_c: + value[(*index)++] = M(spring_fixed_c); + return OK; + case vr_spring_middle_c: + value[(*index)++] = M(spring_middle_c); + return OK; + case vr_force_in: + value[(*index)++] = M(force_in); + return OK; + case vr_force_out: + value[(*index)++] = M(force_out); + return OK; + case vr_alpha_f: + value[(*index)++] = M(alpha_f); + return OK; + case vr_alpha_m: + value[(*index)++] = M(alpha_m); + return OK; + default: + logError(comp, "Get Float64 is not allowed for value reference %u.", vr); + return Error; + } +} + +Status setFloat64(ModelInstance *comp, ValueReference vr, const double *value, size_t *index) +{ + switch (vr) { + + case vr_mass_m: + M(mass_m) = value[(*index)++]; + return OK; + case vr_mass_u: + M(mass_u) = value[(*index)++]; + return OK; + case vr_mass_v: + M(mass_v) = value[(*index)++]; + return OK; + case vr_mass_a: + M(mass_a) = value[(*index)++]; + return OK; + case vr_spring_fixed_c: + M(spring_fixed_c) = value[(*index)++]; + return OK; + case vr_spring_middle_c: + M(spring_middle_c) = value[(*index)++]; + return OK; + case vr_force_in: + M(force_in) = value[(*index)++]; + return OK; + case vr_force_out: + M(force_out) = value[(*index)++]; + return OK; + case vr_alpha_f: + M(alpha_f) = value[(*index)++]; + return OK; + case vr_alpha_m: + M(alpha_m) = value[(*index)++]; + return OK; + default: + logError(comp, "Unexpected value reference: %u.", vr); + return Error; + } +} + +Status getOutputDerivative(ModelInstance *comp, ValueReference valueReference, int order, double *value) +{ + + if (order != 1) { + logError(comp, "The output derivative order %d for value reference %u is not available.", order, valueReference); + return Error; + } + + switch (valueReference) { + + default: + logError(comp, "The output derivative for value reference %u is not available.", valueReference); + return Error; + } + + UNUSED(value); +} + +void eventUpdate(ModelInstance *comp) +{ + + if (false) { + + } else { + comp->valuesOfContinuousStatesChanged = false; + } + + comp->nominalsOfContinuousStatesChanged = false; + comp->terminateSimulation = false; + comp->nextEventTimeDefined = false; +} + +void getContinuousStates(ModelInstance *comp, double x[], size_t nx) +{ + UNUSED(comp); + UNUSED(nx); + UNUSED(x); +} + +void setContinuousStates(ModelInstance *comp, const double x[], size_t nx) +{ + UNUSED(comp); + UNUSED(nx); + UNUSED(x); +} + +void getDerivatives(ModelInstance *comp, double dx[], size_t nx) +{ + UNUSED(comp); + UNUSED(nx); + UNUSED(dx); +} + +void getEventIndicators(ModelInstance *comp, double z[], size_t nz) +{ + + UNUSED(nz); + UNUSED(comp); + UNUSED(z); +} diff --git a/oscillator/solver-fmi/fmu/Oscillator/readme.html b/oscillator/solver-fmi/fmu/Oscillator/readme.html new file mode 100644 index 000000000..ace31f418 --- /dev/null +++ b/oscillator/solver-fmi/fmu/Oscillator/readme.html @@ -0,0 +1,51 @@ + + + +Oscillator + + + +
+

Oscillator

+ +

This model is used for the partitioned simulation of an oscillator with three springs and two masses. The oscillator is cut in the middle spring for partitioning. Here, two springs with one mass between them are calculated. This model can be used to simulate the left partition as well as the right partition, as they are symmetric.

+ +
+ + diff --git a/oscillator/solver-fmi/fmu/README.md b/oscillator/solver-fmi/fmu/README.md new file mode 100644 index 000000000..6f837c3cb --- /dev/null +++ b/oscillator/solver-fmi/fmu/README.md @@ -0,0 +1,19 @@ +# Build instruction + +To build the Oscillator FMU you need [CMake](https://cmake.org/) ≥ 3.16 and a supported [build tool](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html) e.g. Visual Studio ≥ 2013 , Xcode or make. + +Generate the build files with the following commands: + +```bash +mkdir build +cd build +cmake -DFMI_TYPE=CS -DFMI_VERSION=3 .. +make +cp ./Oscillator.fmu ../.. +``` + +Instead of `make`, you can also use your preferred build tool to create the FMU. + +## License + +The FMU model `Oscillator.fmu` used for this tutorial is based on the [Reference-FMUs](https://github.com/modelica/Reference-FMUs) from the Modelica Association Project "FMI", which are released under the [2-Clause BSD License](https://github.com/precice/tutorials/blob/master/oscillator/fmi/fmu/thirdparty/LICENSE.txt). diff --git a/oscillator/solver-fmi/fmu/include/FMI.h b/oscillator/solver-fmi/fmu/include/FMI.h new file mode 100644 index 000000000..07111130f --- /dev/null +++ b/oscillator/solver-fmi/fmu/include/FMI.h @@ -0,0 +1,160 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#endif + +#include +#include + +#ifndef FMI_MAX_MESSAGE_LENGTH +#define FMI_MAX_MESSAGE_LENGTH 4096 +#endif + +#ifndef FMI_STATIC +#define FMI_STATIC +#endif + +typedef enum { + FMIOK, + FMIWarning, + FMIDiscard, + FMIError, + FMIFatal, + FMIPending +} FMIStatus; + +typedef enum { + + // FMI 3.0 variable types + FMIFloat32Type, + FMIDiscreteFloat32Type, + FMIFloat64Type, + FMIDiscreteFloat64Type, + FMIInt8Type, + FMIUInt8Type, + FMIInt16Type, + FMIUInt16Type, + FMIInt32Type, + FMIUInt32Type, + FMIInt64Type, + FMIUInt64Type, + FMIBooleanType, + FMIStringType, + FMIBinaryType, + FMIClockType, + + // Aliases for FMI 1.0 and 2.0 + FMIRealType = FMIFloat64Type, + FMIDiscreteRealType = FMIDiscreteFloat64Type, + FMIIntegerType = FMIInt32Type, + +} FMIVariableType; + +typedef enum { + FMIVersion1 = 1, + FMIVersion2 = 2, + FMIVersion3 = 3 +} FMIVersion; + +typedef enum { + FMIModelExchange, + FMICoSimulation, + FMIScheduledExecution +} FMIInterfaceType; + +typedef enum { + FMI2StartAndEndState = 1 << 0, + FMI2InstantiatedState = 1 << 1, + FMI2InitializationModeState = 1 << 2, + + // model exchange states + FMI2EventModeState = 1 << 3, + FMI2ContinuousTimeModeState = 1 << 4, + + // co-simulation states + FMI2StepCompleteState = 1 << 5, + FMI2StepInProgressState = 1 << 6, + FMI2StepFailedState = 1 << 7, + FMI2StepCanceledState = 1 << 8, + + FMI2TerminatedState = 1 << 9, + FMI2ErrorState = 1 << 10, + FMI2FatalState = 1 << 11, +} FMI2State; + +typedef unsigned int FMIValueReference; + +typedef struct FMIInstance_ FMIInstance; + +typedef struct FMI2Functions_ FMI2Functions; + +typedef struct FMI3Functions_ FMI3Functions; + +typedef void FMILogFunctionCall(FMIInstance *instance, FMIStatus status, const char *message, ...); + +typedef void FMILogMessage(FMIInstance *instance, FMIStatus status, const char *category, const char *message); + +struct FMIInstance_ { + + FMI2Functions *fmi2Functions; + FMI3Functions *fmi3Functions; + +#ifdef _WIN32 + HMODULE libraryHandle; +#else + void *libraryHandle; +#endif + + void *userData; + + FMILogMessage *logMessage; + FMILogFunctionCall *logFunctionCall; + + double time; + + char *buf1; + char *buf2; + + size_t bufsize1; + size_t bufsize2; + + void *component; + + const char *name; + + bool logFMICalls; + + FMI2State state; + + FMIStatus status; + + FMIVersion fmiVersion; + + FMIInterfaceType interfaceType; +}; + +FMI_STATIC FMIInstance *FMICreateInstance(const char *instanceName, const char *libraryPath, FMILogMessage *logMessage, FMILogFunctionCall *logFunctionCall); + +FMI_STATIC void FMIFreeInstance(FMIInstance *instance); + +FMI_STATIC const char *FMIValueReferencesToString(FMIInstance *instance, const FMIValueReference vr[], size_t nvr); + +FMI_STATIC const char *FMIValuesToString(FMIInstance *instance, size_t vValues, const size_t sizes[], const void *values, FMIVariableType variableType); + +FMI_STATIC FMIStatus FMIURIToPath(const char *uri, char *path, const size_t pathLength); + +FMI_STATIC FMIStatus FMIPathToURI(const char *path, char *uri, const size_t uriLength); + +FMI_STATIC FMIStatus FMIPlatformBinaryPath(const char *unzipdir, const char *modelIdentifier, FMIVersion fmiVersion, char *platformBinaryPath, size_t size); + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif diff --git a/oscillator/solver-fmi/fmu/include/FMI2.h b/oscillator/solver-fmi/fmu/include/FMI2.h new file mode 100644 index 000000000..7836d4471 --- /dev/null +++ b/oscillator/solver-fmi/fmu/include/FMI2.h @@ -0,0 +1,219 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "FMI.h" +#include "fmi2Functions.h" + +struct FMI2Functions_ { + + fmi2CallbackFunctions callbacks; + fmi2EventInfo eventInfo; + + /*************************************************** + Common Functions for FMI 2.0 + ****************************************************/ + + /* required functions */ + fmi2GetTypesPlatformTYPE *fmi2GetTypesPlatform; + fmi2GetVersionTYPE *fmi2GetVersion; + fmi2SetDebugLoggingTYPE *fmi2SetDebugLogging; + fmi2InstantiateTYPE *fmi2Instantiate; + fmi2FreeInstanceTYPE *fmi2FreeInstance; + fmi2SetupExperimentTYPE *fmi2SetupExperiment; + fmi2EnterInitializationModeTYPE *fmi2EnterInitializationMode; + fmi2ExitInitializationModeTYPE *fmi2ExitInitializationMode; + fmi2TerminateTYPE *fmi2Terminate; + fmi2ResetTYPE *fmi2Reset; + fmi2GetRealTYPE *fmi2GetReal; + fmi2GetIntegerTYPE *fmi2GetInteger; + fmi2GetBooleanTYPE *fmi2GetBoolean; + fmi2GetStringTYPE *fmi2GetString; + fmi2SetRealTYPE *fmi2SetReal; + fmi2SetIntegerTYPE *fmi2SetInteger; + fmi2SetBooleanTYPE *fmi2SetBoolean; + fmi2SetStringTYPE *fmi2SetString; + + /* optional functions */ + fmi2GetFMUstateTYPE *fmi2GetFMUstate; + fmi2SetFMUstateTYPE *fmi2SetFMUstate; + fmi2FreeFMUstateTYPE *fmi2FreeFMUstate; + fmi2SerializedFMUstateSizeTYPE *fmi2SerializedFMUstateSize; + fmi2SerializeFMUstateTYPE *fmi2SerializeFMUstate; + fmi2DeSerializeFMUstateTYPE *fmi2DeSerializeFMUstate; + fmi2GetDirectionalDerivativeTYPE *fmi2GetDirectionalDerivative; + + /*************************************************** + Functions for FMI 2.0 for Model Exchange + ****************************************************/ + + fmi2EnterEventModeTYPE *fmi2EnterEventMode; + fmi2NewDiscreteStatesTYPE *fmi2NewDiscreteStates; + fmi2EnterContinuousTimeModeTYPE *fmi2EnterContinuousTimeMode; + fmi2CompletedIntegratorStepTYPE *fmi2CompletedIntegratorStep; + fmi2SetTimeTYPE *fmi2SetTime; + fmi2SetContinuousStatesTYPE *fmi2SetContinuousStates; + fmi2GetDerivativesTYPE *fmi2GetDerivatives; + fmi2GetEventIndicatorsTYPE *fmi2GetEventIndicators; + fmi2GetContinuousStatesTYPE *fmi2GetContinuousStates; + fmi2GetNominalsOfContinuousStatesTYPE *fmi2GetNominalsOfContinuousStates; + + /*************************************************** + Functions for FMI 2.0 for Co-Simulation + ****************************************************/ + + fmi2SetRealInputDerivativesTYPE *fmi2SetRealInputDerivatives; + fmi2GetRealOutputDerivativesTYPE *fmi2GetRealOutputDerivatives; + fmi2DoStepTYPE *fmi2DoStep; + fmi2CancelStepTYPE *fmi2CancelStep; + fmi2GetStatusTYPE *fmi2GetStatus; + fmi2GetRealStatusTYPE *fmi2GetRealStatus; + fmi2GetIntegerStatusTYPE *fmi2GetIntegerStatus; + fmi2GetBooleanStatusTYPE *fmi2GetBooleanStatus; + fmi2GetStringStatusTYPE *fmi2GetStringStatus; +}; + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers of header files and setting logging status */ +FMI_STATIC const char *FMI2GetTypesPlatform(FMIInstance *instance); + +FMI_STATIC const char *FMI2GetVersion(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2SetDebugLogging(FMIInstance *instance, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]); + +FMI_STATIC FMIStatus FMI2Instantiate(FMIInstance *instance, const char *fmuResourceLocation, fmi2Type fmuType, fmi2String fmuGUID, + fmi2Boolean visible, fmi2Boolean loggingOn); + +FMI_STATIC void FMI2FreeInstance(FMIInstance *instance); + +/* Enter and exit initialization mode, terminate and reset */ +FMI_STATIC FMIStatus FMI2SetupExperiment(FMIInstance *instance, + fmi2Boolean toleranceDefined, + fmi2Real tolerance, + fmi2Real startTime, + fmi2Boolean stopTimeDefined, + fmi2Real stopTime); + +FMI_STATIC FMIStatus FMI2EnterInitializationMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2ExitInitializationMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2Terminate(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2Reset(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2SetupExperiment(FMIInstance *instance, + fmi2Boolean toleranceDefined, + fmi2Real tolerance, + fmi2Real startTime, + fmi2Boolean stopTimeDefined, + fmi2Real stopTime); + +/* Getting and setting variable values */ +FMI_STATIC FMIStatus FMI2GetReal(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]); + +FMI_STATIC FMIStatus FMI2GetInteger(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]); + +FMI_STATIC FMIStatus FMI2GetBoolean(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]); + +FMI_STATIC FMIStatus FMI2GetString(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]); + +FMI_STATIC FMIStatus FMI2SetReal(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]); + +FMI_STATIC FMIStatus FMI2SetInteger(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]); + +FMI_STATIC FMIStatus FMI2SetBoolean(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]); + +FMI_STATIC FMIStatus FMI2SetString(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]); + +/* Getting and setting the internal FMU state */ +FMI_STATIC FMIStatus FMI2GetFMUstate(FMIInstance *instance, fmi2FMUstate *FMUstate); + +FMI_STATIC FMIStatus FMI2SetFMUstate(FMIInstance *instance, fmi2FMUstate FMUstate); + +FMI_STATIC FMIStatus FMI2FreeFMUstate(FMIInstance *instance, fmi2FMUstate *FMUstate); + +FMI_STATIC FMIStatus FMI2SerializedFMUstateSize(FMIInstance *instance, fmi2FMUstate FMUstate, size_t *size); + +FMI_STATIC FMIStatus FMI2SerializeFMUstate(FMIInstance *instance, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size); + +FMI_STATIC FMIStatus FMI2DeSerializeFMUstate(FMIInstance *instance, const fmi2Byte serializedState[], size_t size, fmi2FMUstate *FMUstate); + +/* Getting partial derivatives */ +FMI_STATIC FMIStatus FMI2GetDirectionalDerivative(FMIInstance *instance, + const fmi2ValueReference vUnknown_ref[], size_t nUnknown, + const fmi2ValueReference vKnown_ref[], size_t nKnown, + const fmi2Real dvKnown[], + fmi2Real dvUnknown[]); + +/*************************************************** +Types for Functions for FMI2 for Model Exchange +****************************************************/ + +/* Enter and exit the different modes */ +FMI_STATIC FMIStatus FMI2EnterEventMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2NewDiscreteStates(FMIInstance *instance, fmi2EventInfo *eventInfo); + +FMI_STATIC FMIStatus FMI2EnterContinuousTimeMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI2CompletedIntegratorStep(FMIInstance *instance, + fmi2Boolean noSetFMUStatePriorToCurrentPoint, + fmi2Boolean *enterEventMode, + fmi2Boolean *terminateSimulation); + +/* Providing independent variables and re-initialization of caching */ +FMI_STATIC FMIStatus FMI2SetTime(FMIInstance *instance, fmi2Real time); + +FMI_STATIC FMIStatus FMI2SetContinuousStates(FMIInstance *instance, const fmi2Real x[], size_t nx); + +/* Evaluation of the model equations */ +FMI_STATIC FMIStatus FMI2GetDerivatives(FMIInstance *instance, fmi2Real derivatives[], size_t nx); + +FMI_STATIC FMIStatus FMI2GetEventIndicators(FMIInstance *instance, fmi2Real eventIndicators[], size_t ni); + +FMI_STATIC FMIStatus FMI2GetContinuousStates(FMIInstance *instance, fmi2Real x[], size_t nx); + +FMI_STATIC FMIStatus FMI2GetNominalsOfContinuousStates(FMIInstance *instance, fmi2Real x_nominal[], size_t nx); + +/*************************************************** +Types for Functions for FMI2 for Co-Simulation +****************************************************/ + +/* Simulating the slave */ +FMI_STATIC FMIStatus FMI2SetRealInputDerivatives(FMIInstance *instance, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + const fmi2Real value[]); + +FMI_STATIC FMIStatus FMI2GetRealOutputDerivatives(FMIInstance *instance, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + fmi2Real value[]); + +FMI_STATIC FMIStatus FMI2DoStep(FMIInstance *instance, + fmi2Real currentCommunicationPoint, + fmi2Real communicationStepSize, + fmi2Boolean noSetFMUStatePriorToCurrentPoint); + +FMI_STATIC FMIStatus FMI2CancelStep(FMIInstance *instance); + +/* Inquire slave status */ +FMI_STATIC FMIStatus FMI2GetStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Status *value); + +FMI_STATIC FMIStatus FMI2GetRealStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Real *value); + +FMI_STATIC FMIStatus FMI2GetIntegerStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Integer *value); + +FMI_STATIC FMIStatus FMI2GetBooleanStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Boolean *value); + +FMI_STATIC FMIStatus FMI2GetStringStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2String *value); + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif diff --git a/oscillator/solver-fmi/fmu/include/FMI3.h b/oscillator/solver-fmi/fmu/include/FMI3.h new file mode 100644 index 000000000..82dbe8034 --- /dev/null +++ b/oscillator/solver-fmi/fmu/include/FMI3.h @@ -0,0 +1,560 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "FMI.h" +#include "fmi3FunctionTypes.h" + +struct FMI3Functions_ { + + fmi3Boolean eventModeUsed; + + fmi3Boolean discreteStatesNeedUpdate; + fmi3Boolean terminateSimulation; + fmi3Boolean nominalsOfContinuousStatesChanged; + fmi3Boolean valuesOfContinuousStatesChanged; + fmi3Boolean nextEventTimeDefined; + fmi3Float64 nextEventTime; + + /*************************************************** + Common Functions for FMI 3.0 + ****************************************************/ + + /* Inquire version numbers and set debug logging */ + fmi3GetVersionTYPE *fmi3GetVersion; + fmi3SetDebugLoggingTYPE *fmi3SetDebugLogging; + + /* Creation and destruction of FMU instances */ + fmi3InstantiateModelExchangeTYPE *fmi3InstantiateModelExchange; + fmi3InstantiateCoSimulationTYPE *fmi3InstantiateCoSimulation; + fmi3InstantiateScheduledExecutionTYPE *fmi3InstantiateScheduledExecution; + fmi3FreeInstanceTYPE *fmi3FreeInstance; + + /* Enter and exit initialization mode, terminate and reset */ + fmi3EnterInitializationModeTYPE *fmi3EnterInitializationMode; + fmi3ExitInitializationModeTYPE *fmi3ExitInitializationMode; + fmi3EnterEventModeTYPE *fmi3EnterEventMode; + fmi3TerminateTYPE *fmi3Terminate; + fmi3ResetTYPE *fmi3Reset; + + /* Getting and setting variable values */ + fmi3GetFloat32TYPE *fmi3GetFloat32; + fmi3GetFloat64TYPE *fmi3GetFloat64; + fmi3GetInt8TYPE *fmi3GetInt8; + fmi3GetUInt8TYPE *fmi3GetUInt8; + fmi3GetInt16TYPE *fmi3GetInt16; + fmi3GetUInt16TYPE *fmi3GetUInt16; + fmi3GetInt32TYPE *fmi3GetInt32; + fmi3GetUInt32TYPE *fmi3GetUInt32; + fmi3GetInt64TYPE *fmi3GetInt64; + fmi3GetUInt64TYPE *fmi3GetUInt64; + fmi3GetBooleanTYPE *fmi3GetBoolean; + fmi3GetStringTYPE *fmi3GetString; + fmi3GetBinaryTYPE *fmi3GetBinary; + fmi3GetClockTYPE *fmi3GetClock; + fmi3SetFloat32TYPE *fmi3SetFloat32; + fmi3SetFloat64TYPE *fmi3SetFloat64; + fmi3SetInt8TYPE *fmi3SetInt8; + fmi3SetUInt8TYPE *fmi3SetUInt8; + fmi3SetInt16TYPE *fmi3SetInt16; + fmi3SetUInt16TYPE *fmi3SetUInt16; + fmi3SetInt32TYPE *fmi3SetInt32; + fmi3SetUInt32TYPE *fmi3SetUInt32; + fmi3SetInt64TYPE *fmi3SetInt64; + fmi3SetUInt64TYPE *fmi3SetUInt64; + fmi3SetBooleanTYPE *fmi3SetBoolean; + fmi3SetStringTYPE *fmi3SetString; + fmi3SetBinaryTYPE *fmi3SetBinary; + fmi3SetClockTYPE *fmi3SetClock; + + /* Getting Variable Dependency Information */ + fmi3GetNumberOfVariableDependenciesTYPE *fmi3GetNumberOfVariableDependencies; + fmi3GetVariableDependenciesTYPE *fmi3GetVariableDependencies; + + /* Getting and setting the internal FMU state */ + fmi3GetFMUStateTYPE *fmi3GetFMUState; + fmi3SetFMUStateTYPE *fmi3SetFMUState; + fmi3FreeFMUStateTYPE *fmi3FreeFMUState; + fmi3SerializedFMUStateSizeTYPE *fmi3SerializedFMUStateSize; + fmi3SerializeFMUStateTYPE *fmi3SerializeFMUState; + fmi3DeserializeFMUStateTYPE *fmi3DeserializeFMUState; + + /* Getting partial derivatives */ + fmi3GetDirectionalDerivativeTYPE *fmi3GetDirectionalDerivative; + fmi3GetAdjointDerivativeTYPE *fmi3GetAdjointDerivative; + + /* Entering and exiting the Configuration or Reconfiguration Mode */ + fmi3EnterConfigurationModeTYPE *fmi3EnterConfigurationMode; + fmi3ExitConfigurationModeTYPE *fmi3ExitConfigurationMode; + + /* Clock related functions */ + fmi3GetIntervalDecimalTYPE *fmi3GetIntervalDecimal; + fmi3GetIntervalFractionTYPE *fmi3GetIntervalFraction; + fmi3GetShiftDecimalTYPE *fmi3GetShiftDecimal; + fmi3GetShiftFractionTYPE *fmi3GetShiftFraction; + fmi3SetIntervalDecimalTYPE *fmi3SetIntervalDecimal; + fmi3SetIntervalFractionTYPE *fmi3SetIntervalFraction; + fmi3SetShiftDecimalTYPE *fmi3SetShiftDecimal; + fmi3SetShiftFractionTYPE *fmi3SetShiftFraction; + fmi3EvaluateDiscreteStatesTYPE *fmi3EvaluateDiscreteStates; + fmi3UpdateDiscreteStatesTYPE *fmi3UpdateDiscreteStates; + + /*************************************************** + Functions for Model Exchange + ****************************************************/ + + fmi3EnterContinuousTimeModeTYPE *fmi3EnterContinuousTimeMode; + fmi3CompletedIntegratorStepTYPE *fmi3CompletedIntegratorStep; + + /* Providing independent variables and re-initialization of caching */ + fmi3SetTimeTYPE *fmi3SetTime; + fmi3SetContinuousStatesTYPE *fmi3SetContinuousStates; + + /* Evaluation of the model equations */ + fmi3GetContinuousStateDerivativesTYPE *fmi3GetContinuousStateDerivatives; + fmi3GetEventIndicatorsTYPE *fmi3GetEventIndicators; + fmi3GetContinuousStatesTYPE *fmi3GetContinuousStates; + fmi3GetNominalsOfContinuousStatesTYPE *fmi3GetNominalsOfContinuousStates; + fmi3GetNumberOfEventIndicatorsTYPE *fmi3GetNumberOfEventIndicators; + fmi3GetNumberOfContinuousStatesTYPE *fmi3GetNumberOfContinuousStates; + + /*************************************************** + Functions for FMI 3.0 for Co-Simulation + ****************************************************/ + + fmi3EnterStepModeTYPE *fmi3EnterStepMode; + fmi3GetOutputDerivativesTYPE *fmi3GetOutputDerivatives; + fmi3DoStepTYPE *fmi3DoStep; + + /*************************************************** + Functions for Scheduled Execution + ****************************************************/ + + fmi3ActivateModelPartitionTYPE *fmi3ActivateModelPartition; +}; + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers and setting logging status */ +FMI_STATIC const char *FMI3GetVersion(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3SetDebugLogging(FMIInstance *instance, + fmi3Boolean loggingOn, + size_t nCategories, + const fmi3String categories[]); + +/* Creation and destruction of FMU instances and setting debug status */ +FMI_STATIC FMIStatus FMI3InstantiateModelExchange( + FMIInstance *instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn); + +FMI_STATIC FMIStatus FMI3InstantiateCoSimulation( + FMIInstance *instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3Boolean eventModeUsed, + fmi3Boolean earlyReturnAllowed, + const fmi3ValueReference requiredIntermediateVariables[], + size_t nRequiredIntermediateVariables, + fmi3IntermediateUpdateCallback intermediateUpdate); + +FMI_STATIC FMIStatus FMI3InstantiateScheduledExecution( + FMIInstance *instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3ClockUpdateCallback clockUpdate, + fmi3LockPreemptionCallback lockPreemption, + fmi3UnlockPreemptionCallback unlockPreemption); + +FMI_STATIC FMIStatus FMI3FreeInstance(FMIInstance *instance); + +/* Enter and exit initialization mode, enter event mode, terminate and reset */ +FMI_STATIC FMIStatus FMI3EnterInitializationMode(FMIInstance *instance, + fmi3Boolean toleranceDefined, + fmi3Float64 tolerance, + fmi3Float64 startTime, + fmi3Boolean stopTimeDefined, + fmi3Float64 stopTime); + +FMI_STATIC FMIStatus FMI3ExitInitializationMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3EnterEventMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3Terminate(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3Reset(FMIInstance *instance); + +/* Getting and setting variable values */ +FMI_STATIC FMIStatus FMI3GetFloat32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetFloat64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetInt8(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int8 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetUInt8(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt8 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetInt16(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int16 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetUInt16(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt16 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetInt32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetUInt32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetInt64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetUInt64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetBoolean(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Boolean values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetString(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3String values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetBinary(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + size_t sizes[], + fmi3Binary values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3GetClock(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Clock values[]); + +FMI_STATIC FMIStatus FMI3SetFloat32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetFloat64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetInt8(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int8 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetUInt8(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt8 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetInt16(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int16 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetUInt16(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt16 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetInt32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetUInt32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt32 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetInt64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetUInt64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetBoolean(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Boolean values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetString(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3String values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetBinary(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const size_t sizes[], + const fmi3Binary values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3SetClock(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Clock values[]); + +/* Getting Variable Dependency Information */ +FMI_STATIC FMIStatus FMI3GetNumberOfVariableDependencies(FMIInstance *instance, + fmi3ValueReference valueReference, + size_t *nDependencies); + +FMI_STATIC FMIStatus FMI3GetVariableDependencies(FMIInstance *instance, + fmi3ValueReference dependent, + size_t elementIndicesOfDependent[], + fmi3ValueReference independents[], + size_t elementIndicesOfIndependents[], + fmi3DependencyKind dependencyKinds[], + size_t nDependencies); + +/* Getting and setting the internal FMU state */ +FMI_STATIC FMIStatus FMI3GetFMUState(FMIInstance *instance, fmi3FMUState *FMUState); + +FMI_STATIC FMIStatus FMI3SetFMUState(FMIInstance *instance, fmi3FMUState FMUState); + +FMI_STATIC FMIStatus FMI3FreeFMUState(FMIInstance *instance, fmi3FMUState *FMUState); + +FMI_STATIC FMIStatus FMI3SerializedFMUStateSize(FMIInstance *instance, + fmi3FMUState FMUState, + size_t *size); + +FMI_STATIC FMIStatus FMI3SerializeFMUState(FMIInstance *instance, + fmi3FMUState FMUState, + fmi3Byte serializedState[], + size_t size); + +FMI_STATIC FMIStatus FMI3DeserializeFMUState(FMIInstance *instance, + const fmi3Byte serializedState[], + size_t size, + fmi3FMUState *FMUState); + +/* Getting partial derivatives */ +FMI_STATIC FMIStatus FMI3GetDirectionalDerivative(FMIInstance *instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity); + +FMI_STATIC FMIStatus FMI3GetAdjointDerivative(FMIInstance *instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity); + +/* Entering and exiting the Configuration or Reconfiguration Mode */ +FMI_STATIC FMIStatus FMI3EnterConfigurationMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3ExitConfigurationMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3GetIntervalDecimal(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 intervals[], + fmi3IntervalQualifier qualifiers[]); + +FMI_STATIC FMIStatus FMI3GetIntervalFraction(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 intervalCounters[], + fmi3UInt64 resolutions[], + fmi3IntervalQualifier qualifiers[]); + +FMI_STATIC FMIStatus FMI3GetShiftDecimal(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 shifts[]); + +FMI_STATIC FMIStatus FMI3GetShiftFraction(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 shiftCounters[], + fmi3UInt64 resolutions[]); + +FMI_STATIC FMIStatus FMI3SetIntervalDecimal(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 intervals[]); + +FMI_STATIC FMIStatus FMI3SetIntervalFraction(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 intervalCounters[], + const fmi3UInt64 resolutions[]); + +FMI_STATIC FMIStatus FMI3SetShiftDecimal(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 shifts[]); + +FMI_STATIC FMIStatus FMI3SetShiftFraction(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 shiftCounters[], + const fmi3UInt64 resolutions[]); + +FMI_STATIC FMIStatus FMI3EvaluateDiscreteStates(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3UpdateDiscreteStates(FMIInstance *instance, + fmi3Boolean *discreteStatesNeedUpdate, + fmi3Boolean *terminateSimulation, + fmi3Boolean *nominalsOfContinuousStatesChanged, + fmi3Boolean *valuesOfContinuousStatesChanged, + fmi3Boolean *nextEventTimeDefined, + fmi3Float64 *nextEventTime); + +/*************************************************** +Functions for Model Exchange +****************************************************/ + +FMI_STATIC FMIStatus FMI3EnterContinuousTimeMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3CompletedIntegratorStep(FMIInstance *instance, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *enterEventMode, + fmi3Boolean *terminateSimulation); + +/* Providing independent variables and re-initialization of caching */ +FMI_STATIC FMIStatus FMI3SetTime(FMIInstance *instance, fmi3Float64 time); + +FMI_STATIC FMIStatus FMI3SetContinuousStates(FMIInstance *instance, + const fmi3Float64 continuousStates[], + size_t nContinuousStates); + +/* Evaluation of the model equations */ +FMI_STATIC FMIStatus FMI3GetContinuousStateDerivatives(FMIInstance *instance, + fmi3Float64 derivatives[], + size_t nContinuousStates); + +FMI_STATIC FMIStatus FMI3GetEventIndicators(FMIInstance *instance, + fmi3Float64 eventIndicators[], + size_t nEventIndicators); + +FMI_STATIC FMIStatus FMI3GetContinuousStates(FMIInstance *instance, + fmi3Float64 continuousStates[], + size_t nContinuousStates); + +FMI_STATIC FMIStatus FMI3GetNominalsOfContinuousStates(FMIInstance *instance, + fmi3Float64 nominals[], + size_t nContinuousStates); + +FMI_STATIC FMIStatus FMI3GetNumberOfEventIndicators(FMIInstance *instance, + size_t *nEventIndicators); + +FMI_STATIC FMIStatus FMI3GetNumberOfContinuousStates(FMIInstance *instance, + size_t *nContinuousStates); + +/*************************************************** +Functions for Co-Simulation +****************************************************/ + +/* Simulating the FMU */ + +FMI_STATIC FMIStatus FMI3EnterStepMode(FMIInstance *instance); + +FMI_STATIC FMIStatus FMI3GetOutputDerivatives(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 orders[], + fmi3Float64 values[], + size_t nValues); + +FMI_STATIC FMIStatus FMI3DoStep(FMIInstance *instance, + fmi3Float64 currentCommunicationPoint, + fmi3Float64 communicationStepSize, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *eventHandlingNeeded, + fmi3Boolean *terminateSimulation, + fmi3Boolean *earlyReturn, + fmi3Float64 *lastSuccessfulTime); + +/*************************************************** +Functions for Scheduled Execution +****************************************************/ + +FMI_STATIC FMIStatus FMI3ActivateModelPartition(FMIInstance *instance, + fmi3ValueReference clockReference, + fmi3Float64 activationTime); + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif diff --git a/oscillator/solver-fmi/fmu/include/cosimulation.h b/oscillator/solver-fmi/fmu/include/cosimulation.h new file mode 100644 index 000000000..291f38618 --- /dev/null +++ b/oscillator/solver-fmi/fmu/include/cosimulation.h @@ -0,0 +1,8 @@ +#pragma once + +#include "model.h" + +#define EPSILON (FIXED_SOLVER_STEP * 1e-6) + +void doFixedStep(ModelInstance *comp, bool *stateEvent, bool *timeEvent); +void doAlphaStep(ModelInstance *comp, bool *stateEvent, bool *timeEvent); diff --git a/oscillator/solver-fmi/fmu/include/fmi2FunctionTypes.h b/oscillator/solver-fmi/fmu/include/fmi2FunctionTypes.h new file mode 100644 index 000000000..345a4449e --- /dev/null +++ b/oscillator/solver-fmi/fmu/include/fmi2FunctionTypes.h @@ -0,0 +1,266 @@ +#ifndef fmi2FunctionTypes_h +#define fmi2FunctionTypes_h + +#include "fmi2TypesPlatform.h" + +/* This header file must be utilized when compiling an FMU or an FMI master. + It declares data and function types for FMI 2.0.1 + + Revisions: + - Sep. 30, 2019: License changed to 2-clause BSD License (without extensions) + - Jul. 5, 2019: Remove const modifier from fields of fmi2CallbackFunctions (#216) + - Sep. 6, 2018: Parameter names added to function prototypes + - Apr. 9, 2014: all prefixes "fmi" renamed to "fmi2" (decision from April 8) + - Apr. 3, 2014: Added #include for size_t definition + - Mar. 27, 2014: Added #include "fmiTypesPlatform.h" (#179) + - Mar. 26, 2014: Introduced function argument "void" for the functions (#171) + fmiGetTypesPlatformTYPE and fmiGetVersionTYPE + - Oct. 11, 2013: Functions of ModelExchange and CoSimulation merged: + fmiInstantiateModelTYPE , fmiInstantiateSlaveTYPE -> fmiInstantiateTYPE + fmiFreeModelInstanceTYPE, fmiFreeSlaveInstanceTYPE -> fmiFreeInstanceTYPE + fmiEnterModelInitializationModeTYPE, fmiEnterSlaveInitializationModeTYPE -> fmiEnterInitializationModeTYPE + fmiExitModelInitializationModeTYPE , fmiExitSlaveInitializationModeTYPE -> fmiExitInitializationModeTYPE + fmiTerminateModelTYPE , fmiTerminateSlaveTYPE -> fmiTerminate + fmiResetSlave -> fmiReset (now also for ModelExchange and not only for CoSimulation) + Functions renamed + fmiUpdateDiscreteStatesTYPE -> fmiNewDiscreteStatesTYPE + Renamed elements of the enumeration fmiEventInfo + upcomingTimeEvent -> nextEventTimeDefined // due to generic naming scheme: varDefined + var + newUpdateDiscreteStatesNeeded -> newDiscreteStatesNeeded; + - June 13, 2013: Changed type fmiEventInfo + Functions removed: + fmiInitializeModelTYPE + fmiEventUpdateTYPE + fmiCompletedEventIterationTYPE + fmiInitializeSlaveTYPE + Functions added: + fmiEnterModelInitializationModeTYPE + fmiExitModelInitializationModeTYPE + fmiEnterEventModeTYPE + fmiUpdateDiscreteStatesTYPE + fmiEnterContinuousTimeModeTYPE + fmiEnterSlaveInitializationModeTYPE; + fmiExitSlaveInitializationModeTYPE; + - Feb. 17, 2013: Added third argument to fmiCompletedIntegratorStepTYPE + Changed function name "fmiTerminateType" to "fmiTerminateModelType" (due to #113) + Changed function name "fmiGetNominalContinuousStateTYPE" to + "fmiGetNominalsOfContinuousStatesTYPE" + Removed fmiGetStateValueReferencesTYPE. + - Nov. 14, 2011: First public Version + + + Copyright (C) 2008-2011 MODELISAR consortium, + 2012-2019 Modelica Association Project "FMI" + All rights reserved. + + This file is licensed by the copyright holders under the 2-Clause BSD License + (https://opensource.org/licenses/BSD-2-Clause): + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* make sure all compiler use the same alignment policies for structures */ +#if defined _MSC_VER || defined __GNUC__ +#pragma pack(push, 8) +#endif + +/* Include stddef.h, in order that size_t etc. is defined */ +#include + +/* Type definitions */ +typedef enum { + fmi2OK, + fmi2Warning, + fmi2Discard, + fmi2Error, + fmi2Fatal, + fmi2Pending +} fmi2Status; + +typedef enum { + fmi2ModelExchange, + fmi2CoSimulation +} fmi2Type; + +typedef enum { + fmi2DoStepStatus, + fmi2PendingStatus, + fmi2LastSuccessfulTime, + fmi2Terminated +} fmi2StatusKind; + +typedef void (*fmi2CallbackLogger)(fmi2ComponentEnvironment componentEnvironment, + fmi2String instanceName, + fmi2Status status, + fmi2String category, + fmi2String message, + ...); +typedef void *(*fmi2CallbackAllocateMemory)(size_t nobj, size_t size); +typedef void (*fmi2CallbackFreeMemory)(void *obj); +typedef void (*fmi2StepFinished)(fmi2ComponentEnvironment componentEnvironment, + fmi2Status status); + +typedef struct { + fmi2CallbackLogger logger; + fmi2CallbackAllocateMemory allocateMemory; + fmi2CallbackFreeMemory freeMemory; + fmi2StepFinished stepFinished; + fmi2ComponentEnvironment componentEnvironment; +} fmi2CallbackFunctions; + +typedef struct { + fmi2Boolean newDiscreteStatesNeeded; + fmi2Boolean terminateSimulation; + fmi2Boolean nominalsOfContinuousStatesChanged; + fmi2Boolean valuesOfContinuousStatesChanged; + fmi2Boolean nextEventTimeDefined; + fmi2Real nextEventTime; +} fmi2EventInfo; + +/* reset alignment policy to the one set before reading this file */ +#if defined _MSC_VER || defined __GNUC__ +#pragma pack(pop) +#endif + +/* Define fmi2 function pointer types to simplify dynamic loading */ + +/*************************************************** +Types for Common Functions +****************************************************/ + +/* Inquire version numbers of header files and setting logging status */ +typedef const char *fmi2GetTypesPlatformTYPE(void); +typedef const char *fmi2GetVersionTYPE(void); +typedef fmi2Status fmi2SetDebugLoggingTYPE(fmi2Component c, + fmi2Boolean loggingOn, + size_t nCategories, + const fmi2String categories[]); + +/* Creation and destruction of FMU instances and setting debug status */ +typedef fmi2Component fmi2InstantiateTYPE(fmi2String instanceName, + fmi2Type fmuType, + fmi2String fmuGUID, + fmi2String fmuResourceLocation, + const fmi2CallbackFunctions *functions, + fmi2Boolean visible, + fmi2Boolean loggingOn); +typedef void fmi2FreeInstanceTYPE(fmi2Component c); + +/* Enter and exit initialization mode, terminate and reset */ +typedef fmi2Status fmi2SetupExperimentTYPE(fmi2Component c, + fmi2Boolean toleranceDefined, + fmi2Real tolerance, + fmi2Real startTime, + fmi2Boolean stopTimeDefined, + fmi2Real stopTime); +typedef fmi2Status fmi2EnterInitializationModeTYPE(fmi2Component c); +typedef fmi2Status fmi2ExitInitializationModeTYPE(fmi2Component c); +typedef fmi2Status fmi2TerminateTYPE(fmi2Component c); +typedef fmi2Status fmi2ResetTYPE(fmi2Component c); + +/* Getting and setting variable values */ +typedef fmi2Status fmi2GetRealTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]); +typedef fmi2Status fmi2GetIntegerTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]); +typedef fmi2Status fmi2GetBooleanTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]); +typedef fmi2Status fmi2GetStringTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]); + +typedef fmi2Status fmi2SetRealTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]); +typedef fmi2Status fmi2SetIntegerTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]); +typedef fmi2Status fmi2SetBooleanTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]); +typedef fmi2Status fmi2SetStringTYPE(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]); + +/* Getting and setting the internal FMU state */ +typedef fmi2Status fmi2GetFMUstateTYPE(fmi2Component c, fmi2FMUstate *FMUstate); +typedef fmi2Status fmi2SetFMUstateTYPE(fmi2Component c, fmi2FMUstate FMUstate); +typedef fmi2Status fmi2FreeFMUstateTYPE(fmi2Component c, fmi2FMUstate *FMUstate); +typedef fmi2Status fmi2SerializedFMUstateSizeTYPE(fmi2Component c, fmi2FMUstate FMUstate, size_t *size); +typedef fmi2Status fmi2SerializeFMUstateTYPE(fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte[], size_t size); +typedef fmi2Status fmi2DeSerializeFMUstateTYPE(fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate *FMUstate); + +/* Getting partial derivatives */ +typedef fmi2Status fmi2GetDirectionalDerivativeTYPE(fmi2Component c, + const fmi2ValueReference vUnknown_ref[], size_t nUnknown, + const fmi2ValueReference vKnown_ref[], size_t nKnown, + const fmi2Real dvKnown[], + fmi2Real dvUnknown[]); + +/*************************************************** +Types for Functions for FMI2 for Model Exchange +****************************************************/ + +/* Enter and exit the different modes */ +typedef fmi2Status fmi2EnterEventModeTYPE(fmi2Component c); +typedef fmi2Status fmi2NewDiscreteStatesTYPE(fmi2Component c, fmi2EventInfo *fmi2eventInfo); +typedef fmi2Status fmi2EnterContinuousTimeModeTYPE(fmi2Component c); +typedef fmi2Status fmi2CompletedIntegratorStepTYPE(fmi2Component c, + fmi2Boolean noSetFMUStatePriorToCurrentPoint, + fmi2Boolean *enterEventMode, + fmi2Boolean *terminateSimulation); + +/* Providing independent variables and re-initialization of caching */ +typedef fmi2Status fmi2SetTimeTYPE(fmi2Component c, fmi2Real time); +typedef fmi2Status fmi2SetContinuousStatesTYPE(fmi2Component c, const fmi2Real x[], size_t nx); + +/* Evaluation of the model equations */ +typedef fmi2Status fmi2GetDerivativesTYPE(fmi2Component c, fmi2Real derivatives[], size_t nx); +typedef fmi2Status fmi2GetEventIndicatorsTYPE(fmi2Component c, fmi2Real eventIndicators[], size_t ni); +typedef fmi2Status fmi2GetContinuousStatesTYPE(fmi2Component c, fmi2Real x[], size_t nx); +typedef fmi2Status fmi2GetNominalsOfContinuousStatesTYPE(fmi2Component c, fmi2Real x_nominal[], size_t nx); + +/*************************************************** +Types for Functions for FMI2 for Co-Simulation +****************************************************/ + +/* Simulating the slave */ +typedef fmi2Status fmi2SetRealInputDerivativesTYPE(fmi2Component c, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + const fmi2Real value[]); +typedef fmi2Status fmi2GetRealOutputDerivativesTYPE(fmi2Component c, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + fmi2Real value[]); +typedef fmi2Status fmi2DoStepTYPE(fmi2Component c, + fmi2Real currentCommunicationPoint, + fmi2Real communicationStepSize, + fmi2Boolean noSetFMUStatePriorToCurrentPoint); +typedef fmi2Status fmi2CancelStepTYPE(fmi2Component c); + +/* Inquire slave status */ +typedef fmi2Status fmi2GetStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Status *value); +typedef fmi2Status fmi2GetRealStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Real *value); +typedef fmi2Status fmi2GetIntegerStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Integer *value); +typedef fmi2Status fmi2GetBooleanStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2Boolean *value); +typedef fmi2Status fmi2GetStringStatusTYPE(fmi2Component c, const fmi2StatusKind s, fmi2String *value); + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif + +#endif /* fmi2FunctionTypes_h */ diff --git a/oscillator/solver-fmi/fmu/include/fmi2Functions.h b/oscillator/solver-fmi/fmu/include/fmi2Functions.h new file mode 100644 index 000000000..f177e5611 --- /dev/null +++ b/oscillator/solver-fmi/fmu/include/fmi2Functions.h @@ -0,0 +1,321 @@ +#ifndef fmi2Functions_h +#define fmi2Functions_h + +/* This header file must be utilized when compiling a FMU. + It defines all functions of the + FMI 2.0.1 Model Exchange and Co-Simulation Interface. + + In order to have unique function names even if several FMUs + are compiled together (e.g. for embedded systems), every "real" function name + is constructed by prepending the function name by "FMI2_FUNCTION_PREFIX". + Therefore, the typical usage is: + + #define FMI2_FUNCTION_PREFIX MyModel_ + #include "fmi2Functions.h" + + As a result, a function that is defined as "fmi2GetDerivatives" in this header file, + is actually getting the name "MyModel_fmi2GetDerivatives". + + This only holds if the FMU is shipped in C source code, or is compiled in a + static link library. For FMUs compiled in a DLL/sharedObject, the "actual" function + names are used and "FMI2_FUNCTION_PREFIX" must not be defined. + + Revisions: + - Sep. 29, 2019: License changed to 2-clause BSD License (without extensions) + - Apr. 9, 2014: All prefixes "fmi" renamed to "fmi2" (decision from April 8) + - Mar. 26, 2014: FMI_Export set to empty value if FMI_Export and FMI_FUNCTION_PREFIX + are not defined (#173) + - Oct. 11, 2013: Functions of ModelExchange and CoSimulation merged: + fmiInstantiateModel , fmiInstantiateSlave -> fmiInstantiate + fmiFreeModelInstance, fmiFreeSlaveInstance -> fmiFreeInstance + fmiEnterModelInitializationMode, fmiEnterSlaveInitializationMode -> fmiEnterInitializationMode + fmiExitModelInitializationMode , fmiExitSlaveInitializationMode -> fmiExitInitializationMode + fmiTerminateModel, fmiTerminateSlave -> fmiTerminate + fmiResetSlave -> fmiReset (now also for ModelExchange and not only for CoSimulation) + Functions renamed: + fmiUpdateDiscreteStates -> fmiNewDiscreteStates + - June 13, 2013: Functions removed: + fmiInitializeModel + fmiEventUpdate + fmiCompletedEventIteration + fmiInitializeSlave + Functions added: + fmiEnterModelInitializationMode + fmiExitModelInitializationMode + fmiEnterEventMode + fmiUpdateDiscreteStates + fmiEnterContinuousTimeMode + fmiEnterSlaveInitializationMode; + fmiExitSlaveInitializationMode; + - Feb. 17, 2013: Portability improvements: + o DllExport changed to FMI_Export + o FUNCTION_PREFIX changed to FMI_FUNCTION_PREFIX + o Allow undefined FMI_FUNCTION_PREFIX (meaning no prefix is used) + Changed function name "fmiTerminate" to "fmiTerminateModel" (due to #113) + Changed function name "fmiGetNominalContinuousState" to + "fmiGetNominalsOfContinuousStates" + Removed fmiGetStateValueReferences. + - Nov. 14, 2011: Adapted to FMI 2.0: + o Split into two files (fmiFunctions.h, fmiTypes.h) in order + that code that dynamically loads an FMU can directly + utilize the header files). + o Added C++ encapsulation of C-part, in order that the header + file can be directly utilized in C++ code. + o fmiCallbackFunctions is passed as pointer to fmiInstantiateXXX + o stepFinished within fmiCallbackFunctions has as first + argument "fmiComponentEnvironment" and not "fmiComponent". + o New functions to get and set the complete FMU state + and to compute partial derivatives. + - Nov. 4, 2010: Adapted to specification text: + o fmiGetModelTypesPlatform renamed to fmiGetTypesPlatform + o fmiInstantiateSlave: Argument GUID replaced by fmuGUID + Argument mimetype replaced by mimeType + o tabs replaced by spaces + - Oct. 16, 2010: Functions for FMI for Co-simulation added + - Jan. 20, 2010: stateValueReferencesChanged added to struct fmiEventInfo (ticket #27) + (by M. Otter, DLR) + Added WIN32 pragma to define the struct layout (ticket #34) + (by J. Mauss, QTronic) + - Jan. 4, 2010: Removed argument intermediateResults from fmiInitialize + Renamed macro fmiGetModelFunctionsVersion to fmiGetVersion + Renamed macro fmiModelFunctionsVersion to fmiVersion + Replaced fmiModel by fmiComponent in decl of fmiInstantiateModel + (by J. Mauss, QTronic) + - Dec. 17, 2009: Changed extension "me" to "fmi" (by Martin Otter, DLR). + - Dez. 14, 2009: Added eventInfo to meInitialize and added + meGetNominalContinuousStates (by Martin Otter, DLR) + - Sept. 9, 2009: Added DllExport (according to Peter Nilsson's suggestion) + (by A. Junghanns, QTronic) + - Sept. 9, 2009: Changes according to FMI-meeting on July 21: + meInquireModelTypesVersion -> meGetModelTypesPlatform + meInquireModelFunctionsVersion -> meGetModelFunctionsVersion + meSetStates -> meSetContinuousStates + meGetStates -> meGetContinuousStates + removal of meInitializeModelClass + removal of meGetTime + change of arguments of meInstantiateModel + change of arguments of meCompletedIntegratorStep + (by Martin Otter, DLR): + - July 19, 2009: Added "me" as prefix to file names (by Martin Otter, DLR). + - March 2, 2009: Changed function definitions according to the last design + meeting with additional improvements (by Martin Otter, DLR). + - Dec. 3 , 2008: First version by Martin Otter (DLR) and Hans Olsson (Dynasim). + + + Copyright (C) 2008-2011 MODELISAR consortium, + 2012-2019 Modelica Association Project "FMI" + All rights reserved. + + This file is licensed by the copyright holders under the 2-Clause BSD License + (https://opensource.org/licenses/BSD-2-Clause): + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "fmi2FunctionTypes.h" +#include "fmi2TypesPlatform.h" + +/* + Export FMI2 API functions on Windows and under GCC. + If custom linking is desired then the FMI2_Export must be + defined before including this file. For instance, + it may be set to __declspec(dllimport). +*/ +#if !defined(FMI2_Export) +#if !defined(FMI2_FUNCTION_PREFIX) +#if defined _WIN32 || defined __CYGWIN__ +/* Note: both gcc & MSVC on Windows support this syntax. */ +#define FMI2_Export __declspec(dllexport) +#else +#if __GNUC__ >= 4 +#define FMI2_Export __attribute__((visibility("default"))) +#else +#define FMI2_Export +#endif +#endif +#else +#define FMI2_Export +#endif +#endif + +/* Macros to construct the real function name + (prepend function name by FMI2_FUNCTION_PREFIX) */ +#if defined(FMI2_FUNCTION_PREFIX) +#define fmi2Paste(a, b) a##b +#define fmi2PasteB(a, b) fmi2Paste(a, b) +#define fmi2FullName(name) fmi2PasteB(FMI2_FUNCTION_PREFIX, name) +#else +#define fmi2FullName(name) name +#endif + +/*************************************************** +Common Functions +****************************************************/ +#define fmi2GetTypesPlatform fmi2FullName(fmi2GetTypesPlatform) +#define fmi2GetVersion fmi2FullName(fmi2GetVersion) +#define fmi2SetDebugLogging fmi2FullName(fmi2SetDebugLogging) +#define fmi2Instantiate fmi2FullName(fmi2Instantiate) +#define fmi2FreeInstance fmi2FullName(fmi2FreeInstance) +#define fmi2SetupExperiment fmi2FullName(fmi2SetupExperiment) +#define fmi2EnterInitializationMode fmi2FullName(fmi2EnterInitializationMode) +#define fmi2ExitInitializationMode fmi2FullName(fmi2ExitInitializationMode) +#define fmi2Terminate fmi2FullName(fmi2Terminate) +#define fmi2Reset fmi2FullName(fmi2Reset) +#define fmi2GetReal fmi2FullName(fmi2GetReal) +#define fmi2GetInteger fmi2FullName(fmi2GetInteger) +#define fmi2GetBoolean fmi2FullName(fmi2GetBoolean) +#define fmi2GetString fmi2FullName(fmi2GetString) +#define fmi2SetReal fmi2FullName(fmi2SetReal) +#define fmi2SetInteger fmi2FullName(fmi2SetInteger) +#define fmi2SetBoolean fmi2FullName(fmi2SetBoolean) +#define fmi2SetString fmi2FullName(fmi2SetString) +#define fmi2GetFMUstate fmi2FullName(fmi2GetFMUstate) +#define fmi2SetFMUstate fmi2FullName(fmi2SetFMUstate) +#define fmi2FreeFMUstate fmi2FullName(fmi2FreeFMUstate) +#define fmi2SerializedFMUstateSize fmi2FullName(fmi2SerializedFMUstateSize) +#define fmi2SerializeFMUstate fmi2FullName(fmi2SerializeFMUstate) +#define fmi2DeSerializeFMUstate fmi2FullName(fmi2DeSerializeFMUstate) +#define fmi2GetDirectionalDerivative fmi2FullName(fmi2GetDirectionalDerivative) + +/*************************************************** +Functions for FMI2 for Model Exchange +****************************************************/ +#define fmi2EnterEventMode fmi2FullName(fmi2EnterEventMode) +#define fmi2NewDiscreteStates fmi2FullName(fmi2NewDiscreteStates) +#define fmi2EnterContinuousTimeMode fmi2FullName(fmi2EnterContinuousTimeMode) +#define fmi2CompletedIntegratorStep fmi2FullName(fmi2CompletedIntegratorStep) +#define fmi2SetTime fmi2FullName(fmi2SetTime) +#define fmi2SetContinuousStates fmi2FullName(fmi2SetContinuousStates) +#define fmi2GetDerivatives fmi2FullName(fmi2GetDerivatives) +#define fmi2GetEventIndicators fmi2FullName(fmi2GetEventIndicators) +#define fmi2GetContinuousStates fmi2FullName(fmi2GetContinuousStates) +#define fmi2GetNominalsOfContinuousStates fmi2FullName(fmi2GetNominalsOfContinuousStates) + +/*************************************************** +Functions for FMI2 for Co-Simulation +****************************************************/ +#define fmi2SetRealInputDerivatives fmi2FullName(fmi2SetRealInputDerivatives) +#define fmi2GetRealOutputDerivatives fmi2FullName(fmi2GetRealOutputDerivatives) +#define fmi2DoStep fmi2FullName(fmi2DoStep) +#define fmi2CancelStep fmi2FullName(fmi2CancelStep) +#define fmi2GetStatus fmi2FullName(fmi2GetStatus) +#define fmi2GetRealStatus fmi2FullName(fmi2GetRealStatus) +#define fmi2GetIntegerStatus fmi2FullName(fmi2GetIntegerStatus) +#define fmi2GetBooleanStatus fmi2FullName(fmi2GetBooleanStatus) +#define fmi2GetStringStatus fmi2FullName(fmi2GetStringStatus) + +/* Version number */ +#define fmi2Version "2.0" + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers of header files */ +FMI2_Export fmi2GetTypesPlatformTYPE fmi2GetTypesPlatform; +FMI2_Export fmi2GetVersionTYPE fmi2GetVersion; +FMI2_Export fmi2SetDebugLoggingTYPE fmi2SetDebugLogging; + +/* Creation and destruction of FMU instances */ +FMI2_Export fmi2InstantiateTYPE fmi2Instantiate; +FMI2_Export fmi2FreeInstanceTYPE fmi2FreeInstance; + +/* Enter and exit initialization mode, terminate and reset */ +FMI2_Export fmi2SetupExperimentTYPE fmi2SetupExperiment; +FMI2_Export fmi2EnterInitializationModeTYPE fmi2EnterInitializationMode; +FMI2_Export fmi2ExitInitializationModeTYPE fmi2ExitInitializationMode; +FMI2_Export fmi2TerminateTYPE fmi2Terminate; +FMI2_Export fmi2ResetTYPE fmi2Reset; + +/* Getting and setting variables values */ +FMI2_Export fmi2GetRealTYPE fmi2GetReal; +FMI2_Export fmi2GetIntegerTYPE fmi2GetInteger; +FMI2_Export fmi2GetBooleanTYPE fmi2GetBoolean; +FMI2_Export fmi2GetStringTYPE fmi2GetString; + +FMI2_Export fmi2SetRealTYPE fmi2SetReal; +FMI2_Export fmi2SetIntegerTYPE fmi2SetInteger; +FMI2_Export fmi2SetBooleanTYPE fmi2SetBoolean; +FMI2_Export fmi2SetStringTYPE fmi2SetString; + +/* Getting and setting the internal FMU state */ +FMI2_Export fmi2GetFMUstateTYPE fmi2GetFMUstate; +FMI2_Export fmi2SetFMUstateTYPE fmi2SetFMUstate; +FMI2_Export fmi2FreeFMUstateTYPE fmi2FreeFMUstate; +FMI2_Export fmi2SerializedFMUstateSizeTYPE fmi2SerializedFMUstateSize; +FMI2_Export fmi2SerializeFMUstateTYPE fmi2SerializeFMUstate; +FMI2_Export fmi2DeSerializeFMUstateTYPE fmi2DeSerializeFMUstate; + +/* Getting partial derivatives */ +FMI2_Export fmi2GetDirectionalDerivativeTYPE fmi2GetDirectionalDerivative; + +/*************************************************** +Functions for FMI2 for Model Exchange +****************************************************/ + +/* Enter and exit the different modes */ +FMI2_Export fmi2EnterEventModeTYPE fmi2EnterEventMode; +FMI2_Export fmi2NewDiscreteStatesTYPE fmi2NewDiscreteStates; +FMI2_Export fmi2EnterContinuousTimeModeTYPE fmi2EnterContinuousTimeMode; +FMI2_Export fmi2CompletedIntegratorStepTYPE fmi2CompletedIntegratorStep; + +/* Providing independent variables and re-initialization of caching */ +FMI2_Export fmi2SetTimeTYPE fmi2SetTime; +FMI2_Export fmi2SetContinuousStatesTYPE fmi2SetContinuousStates; + +/* Evaluation of the model equations */ +FMI2_Export fmi2GetDerivativesTYPE fmi2GetDerivatives; +FMI2_Export fmi2GetEventIndicatorsTYPE fmi2GetEventIndicators; +FMI2_Export fmi2GetContinuousStatesTYPE fmi2GetContinuousStates; +FMI2_Export fmi2GetNominalsOfContinuousStatesTYPE fmi2GetNominalsOfContinuousStates; + +/*************************************************** +Functions for FMI2 for Co-Simulation +****************************************************/ + +/* Simulating the slave */ +FMI2_Export fmi2SetRealInputDerivativesTYPE fmi2SetRealInputDerivatives; +FMI2_Export fmi2GetRealOutputDerivativesTYPE fmi2GetRealOutputDerivatives; + +FMI2_Export fmi2DoStepTYPE fmi2DoStep; +FMI2_Export fmi2CancelStepTYPE fmi2CancelStep; + +/* Inquire slave status */ +FMI2_Export fmi2GetStatusTYPE fmi2GetStatus; +FMI2_Export fmi2GetRealStatusTYPE fmi2GetRealStatus; +FMI2_Export fmi2GetIntegerStatusTYPE fmi2GetIntegerStatus; +FMI2_Export fmi2GetBooleanStatusTYPE fmi2GetBooleanStatus; +FMI2_Export fmi2GetStringStatusTYPE fmi2GetStringStatus; + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif + +#endif /* fmi2Functions_h */ diff --git a/oscillator/solver-fmi/fmu/include/fmi2TypesPlatform.h b/oscillator/solver-fmi/fmu/include/fmi2TypesPlatform.h new file mode 100644 index 000000000..6b63cb1c5 --- /dev/null +++ b/oscillator/solver-fmi/fmu/include/fmi2TypesPlatform.h @@ -0,0 +1,107 @@ +#ifndef fmi2TypesPlatform_h +#define fmi2TypesPlatform_h + +/* Standard header file to define the argument types of the + functions of the Functional Mock-up Interface 2.0.1 + This header file must be utilized both by the model and + by the simulation engine. + + Revisions: + - Sep. 29, 2019: License changed to 2-clause BSD License (without extensions) + - Apr. 9, 2014: All prefixes "fmi" renamed to "fmi2" (decision from April 8) + - Mar 31, 2014: New datatype fmiChar introduced. + - Feb. 17, 2013: Changed fmiTypesPlatform from "standard32" to "default". + Removed fmiUndefinedValueReference since no longer needed + (because every state is defined in ScalarVariables). + - March 20, 2012: Renamed from fmiPlatformTypes.h to fmiTypesPlatform.h + - Nov. 14, 2011: Use the header file "fmiPlatformTypes.h" for FMI 2.0 + both for "FMI for model exchange" and for "FMI for co-simulation" + New types "fmiComponentEnvironment", "fmiState", and "fmiByte". + The implementation of "fmiBoolean" is change from "char" to "int". + The #define "fmiPlatform" changed to "fmiTypesPlatform" + (in order that #define and function call are consistent) + - Oct. 4, 2010: Renamed header file from "fmiModelTypes.h" to fmiPlatformTypes.h" + for the co-simulation interface + - Jan. 4, 2010: Renamed meModelTypes_h to fmiModelTypes_h (by Mauss, QTronic) + - Dec. 21, 2009: Changed "me" to "fmi" and "meModel" to "fmiComponent" + according to meeting on Dec. 18 (by Martin Otter, DLR) + - Dec. 6, 2009: Added meUndefinedValueReference (by Martin Otter, DLR) + - Sept. 9, 2009: Changes according to FMI-meeting on July 21: + Changed "version" to "platform", "standard" to "standard32", + Added a precise definition of "standard32" as comment + (by Martin Otter, DLR) + - July 19, 2009: Added "me" as prefix to file names, added meTrue/meFalse, + and changed meValueReferenced from int to unsigned int + (by Martin Otter, DLR). + - March 2, 2009: Moved enums and function pointer definitions to + ModelFunctions.h (by Martin Otter, DLR). + - Dec. 3, 2008 : First version by Martin Otter (DLR) and + Hans Olsson (Dynasim). + + + Copyright (C) 2008-2011 MODELISAR consortium, + 2012-2019 Modelica Association Project "FMI" + All rights reserved. + + This file is licensed by the copyright holders under the 2-Clause BSD License + (https://opensource.org/licenses/BSD-2-Clause): + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- +*/ + +/* Platform (unique identification of this header file) */ +#define fmi2TypesPlatform "default" + +/* Type definitions of variables passed as arguments + Version "default" means: + + fmi2Component : an opaque object pointer + fmi2ComponentEnvironment: an opaque object pointer + fmi2FMUstate : an opaque object pointer + fmi2ValueReference : handle to the value of a variable + fmi2Real : double precision floating-point data type + fmi2Integer : basic signed integer data type + fmi2Boolean : basic signed integer data type + fmi2Char : character data type + fmi2String : a pointer to a vector of fmi2Char characters + ('\0' terminated, UTF8 encoded) + fmi2Byte : smallest addressable unit of the machine, typically one byte. +*/ +typedef void *fmi2Component; /* Pointer to FMU instance */ +typedef void *fmi2ComponentEnvironment; /* Pointer to FMU environment */ +typedef void *fmi2FMUstate; /* Pointer to internal FMU state */ +typedef unsigned int fmi2ValueReference; +typedef double fmi2Real; +typedef int fmi2Integer; +typedef int fmi2Boolean; +typedef char fmi2Char; +typedef const fmi2Char *fmi2String; +typedef char fmi2Byte; + +/* Values for fmi2Boolean */ +#define fmi2True 1 +#define fmi2False 0 + +#endif /* fmi2TypesPlatform_h */ diff --git a/oscillator/solver-fmi/fmu/include/fmi3FunctionTypes.h b/oscillator/solver-fmi/fmu/include/fmi3FunctionTypes.h new file mode 100644 index 000000000..8af7f89bd --- /dev/null +++ b/oscillator/solver-fmi/fmu/include/fmi3FunctionTypes.h @@ -0,0 +1,637 @@ +#ifndef fmi3FunctionTypes_h +#define fmi3FunctionTypes_h + +#include "fmi3PlatformTypes.h" + +/* +This header file defines the data and function types of FMI 3.0. +It must be used when compiling an FMU or an FMI importer. + +Copyright (C) 2011 MODELISAR consortium, + 2012-2022 Modelica Association Project "FMI" + All rights reserved. + +This file is licensed by the copyright holders under the 2-Clause BSD License +(https://opensource.org/licenses/BSD-2-Clause): + +---------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +---------------------------------------------------------------------------- +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Include stddef.h, in order that size_t etc. is defined */ +#include + +/* Type definitions */ + +/* tag::Status[] */ +typedef enum { + fmi3OK, + fmi3Warning, + fmi3Discard, + fmi3Error, + fmi3Fatal, +} fmi3Status; +/* end::Status[] */ + +/* tag::DependencyKind[] */ +typedef enum { + fmi3Independent, + fmi3Constant, + fmi3Fixed, + fmi3Tunable, + fmi3Discrete, + fmi3Dependent +} fmi3DependencyKind; +/* end::DependencyKind[] */ + +/* tag::IntervalQualifier[] */ +typedef enum { + fmi3IntervalNotYetKnown, + fmi3IntervalUnchanged, + fmi3IntervalChanged +} fmi3IntervalQualifier; +/* end::IntervalQualifier[] */ + +/* tag::CallbackLogMessage[] */ +typedef void (*fmi3LogMessageCallback)(fmi3InstanceEnvironment instanceEnvironment, + fmi3Status status, + fmi3String category, + fmi3String message); +/* end::CallbackLogMessage[] */ + +/* tag::CallbackClockUpdate[] */ +typedef void (*fmi3ClockUpdateCallback)( + fmi3InstanceEnvironment instanceEnvironment); +/* end::CallbackClockUpdate[] */ + +/* tag::CallbackIntermediateUpdate[] */ +typedef void (*fmi3IntermediateUpdateCallback)( + fmi3InstanceEnvironment instanceEnvironment, + fmi3Float64 intermediateUpdateTime, + fmi3Boolean intermediateVariableSetRequested, + fmi3Boolean intermediateVariableGetAllowed, + fmi3Boolean intermediateStepFinished, + fmi3Boolean canReturnEarly, + fmi3Boolean *earlyReturnRequested, + fmi3Float64 *earlyReturnTime); +/* end::CallbackIntermediateUpdate[] */ + +/* tag::CallbackPreemptionLock[] */ +typedef void (*fmi3LockPreemptionCallback)(); +typedef void (*fmi3UnlockPreemptionCallback)(); +/* end::CallbackPreemptionLock[] */ + +/* Define fmi3 function pointer types to simplify dynamic loading */ + +/*************************************************** +Types for Common Functions +****************************************************/ + +/* Inquire version numbers and setting logging status */ +/* tag::GetVersion[] */ +typedef const char *fmi3GetVersionTYPE(void); +/* end::GetVersion[] */ + +/* tag::SetDebugLogging[] */ +typedef fmi3Status fmi3SetDebugLoggingTYPE(fmi3Instance instance, + fmi3Boolean loggingOn, + size_t nCategories, + const fmi3String categories[]); +/* end::SetDebugLogging[] */ + +/* Creation and destruction of FMU instances and setting debug status */ +/* tag::Instantiate[] */ +typedef fmi3Instance fmi3InstantiateModelExchangeTYPE( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage); + +typedef fmi3Instance fmi3InstantiateCoSimulationTYPE( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3Boolean eventModeUsed, + fmi3Boolean earlyReturnAllowed, + const fmi3ValueReference requiredIntermediateVariables[], + size_t nRequiredIntermediateVariables, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3IntermediateUpdateCallback intermediateUpdate); + +typedef fmi3Instance fmi3InstantiateScheduledExecutionTYPE( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3ClockUpdateCallback clockUpdate, + fmi3LockPreemptionCallback lockPreemption, + fmi3UnlockPreemptionCallback unlockPreemption); +/* end::Instantiate[] */ + +/* tag::FreeInstance[] */ +typedef void fmi3FreeInstanceTYPE(fmi3Instance instance); +/* end::FreeInstance[] */ + +/* Enter and exit initialization mode, enter event mode, terminate and reset */ +/* tag::EnterInitializationMode[] */ +typedef fmi3Status fmi3EnterInitializationModeTYPE(fmi3Instance instance, + fmi3Boolean toleranceDefined, + fmi3Float64 tolerance, + fmi3Float64 startTime, + fmi3Boolean stopTimeDefined, + fmi3Float64 stopTime); +/* end::EnterInitializationMode[] */ + +/* tag::ExitInitializationMode[] */ +typedef fmi3Status fmi3ExitInitializationModeTYPE(fmi3Instance instance); +/* end::ExitInitializationMode[] */ + +/* tag::EnterEventMode[] */ +typedef fmi3Status fmi3EnterEventModeTYPE(fmi3Instance instance); +/* end::EnterEventMode[] */ + +/* tag::Terminate[] */ +typedef fmi3Status fmi3TerminateTYPE(fmi3Instance instance); +/* end::Terminate[] */ + +/* tag::Reset[] */ +typedef fmi3Status fmi3ResetTYPE(fmi3Instance instance); +/* end::Reset[] */ + +/* Getting and setting variable values */ +/* tag::Getters[] */ +typedef fmi3Status fmi3GetFloat32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float32 values[], + size_t nValues); + +typedef fmi3Status fmi3GetFloat64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 values[], + size_t nValues); + +typedef fmi3Status fmi3GetInt8TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int8 values[], + size_t nValues); + +typedef fmi3Status fmi3GetUInt8TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt8 values[], + size_t nValues); + +typedef fmi3Status fmi3GetInt16TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int16 values[], + size_t nValues); + +typedef fmi3Status fmi3GetUInt16TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt16 values[], + size_t nValues); + +typedef fmi3Status fmi3GetInt32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int32 values[], + size_t nValues); + +typedef fmi3Status fmi3GetUInt32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt32 values[], + size_t nValues); + +typedef fmi3Status fmi3GetInt64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int64 values[], + size_t nValues); + +typedef fmi3Status fmi3GetUInt64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 values[], + size_t nValues); + +typedef fmi3Status fmi3GetBooleanTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Boolean values[], + size_t nValues); + +typedef fmi3Status fmi3GetStringTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3String values[], + size_t nValues); + +typedef fmi3Status fmi3GetBinaryTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + size_t valueSizes[], + fmi3Binary values[], + size_t nValues); +/* end::Getters[] */ + +/* tag::GetClock[] */ +typedef fmi3Status fmi3GetClockTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Clock values[]); +/* end::GetClock[] */ + +/* tag::Setters[] */ +typedef fmi3Status fmi3SetFloat32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float32 values[], + size_t nValues); + +typedef fmi3Status fmi3SetFloat64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 values[], + size_t nValues); + +typedef fmi3Status fmi3SetInt8TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int8 values[], + size_t nValues); + +typedef fmi3Status fmi3SetUInt8TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt8 values[], + size_t nValues); + +typedef fmi3Status fmi3SetInt16TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int16 values[], + size_t nValues); + +typedef fmi3Status fmi3SetUInt16TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt16 values[], + size_t nValues); + +typedef fmi3Status fmi3SetInt32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 values[], + size_t nValues); + +typedef fmi3Status fmi3SetUInt32TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt32 values[], + size_t nValues); + +typedef fmi3Status fmi3SetInt64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int64 values[], + size_t nValues); + +typedef fmi3Status fmi3SetUInt64TYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 values[], + size_t nValues); + +typedef fmi3Status fmi3SetBooleanTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Boolean values[], + size_t nValues); + +typedef fmi3Status fmi3SetStringTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3String values[], + size_t nValues); + +typedef fmi3Status fmi3SetBinaryTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const size_t valueSizes[], + const fmi3Binary values[], + size_t nValues); +/* end::Setters[] */ +/* tag::SetClock[] */ +typedef fmi3Status fmi3SetClockTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Clock values[]); +/* end::SetClock[] */ + +/* Getting Variable Dependency Information */ +/* tag::GetNumberOfVariableDependencies[] */ +typedef fmi3Status fmi3GetNumberOfVariableDependenciesTYPE(fmi3Instance instance, + fmi3ValueReference valueReference, + size_t *nDependencies); +/* end::GetNumberOfVariableDependencies[] */ + +/* tag::GetVariableDependencies[] */ +typedef fmi3Status fmi3GetVariableDependenciesTYPE(fmi3Instance instance, + fmi3ValueReference dependent, + size_t elementIndicesOfDependent[], + fmi3ValueReference independents[], + size_t elementIndicesOfIndependents[], + fmi3DependencyKind dependencyKinds[], + size_t nDependencies); +/* end::GetVariableDependencies[] */ + +/* Getting and setting the internal FMU state */ +/* tag::GetFMUState[] */ +typedef fmi3Status fmi3GetFMUStateTYPE(fmi3Instance instance, fmi3FMUState *FMUState); +/* end::GetFMUState[] */ + +/* tag::SetFMUState[] */ +typedef fmi3Status fmi3SetFMUStateTYPE(fmi3Instance instance, fmi3FMUState FMUState); +/* end::SetFMUState[] */ + +/* tag::FreeFMUState[] */ +typedef fmi3Status fmi3FreeFMUStateTYPE(fmi3Instance instance, fmi3FMUState *FMUState); +/* end::FreeFMUState[] */ + +/* tag::SerializedFMUStateSize[] */ +typedef fmi3Status fmi3SerializedFMUStateSizeTYPE(fmi3Instance instance, + fmi3FMUState FMUState, + size_t *size); +/* end::SerializedFMUStateSize[] */ + +/* tag::SerializeFMUState[] */ +typedef fmi3Status fmi3SerializeFMUStateTYPE(fmi3Instance instance, + fmi3FMUState FMUState, + fmi3Byte serializedState[], + size_t size); +/* end::SerializeFMUState[] */ + +/* tag::DeserializeFMUState[] */ +typedef fmi3Status fmi3DeserializeFMUStateTYPE(fmi3Instance instance, + const fmi3Byte serializedState[], + size_t size, + fmi3FMUState *FMUState); +/* end::DeserializeFMUState[] */ + +/* Getting partial derivatives */ +/* tag::GetDirectionalDerivative[] */ +typedef fmi3Status fmi3GetDirectionalDerivativeTYPE(fmi3Instance instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity); +/* end::GetDirectionalDerivative[] */ + +/* tag::GetAdjointDerivative[] */ +typedef fmi3Status fmi3GetAdjointDerivativeTYPE(fmi3Instance instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity); +/* end::GetAdjointDerivative[] */ + +/* Entering and exiting the Configuration or Reconfiguration Mode */ + +/* tag::EnterConfigurationMode[] */ +typedef fmi3Status fmi3EnterConfigurationModeTYPE(fmi3Instance instance); +/* end::EnterConfigurationMode[] */ + +/* tag::ExitConfigurationMode[] */ +typedef fmi3Status fmi3ExitConfigurationModeTYPE(fmi3Instance instance); +/* end::ExitConfigurationMode[] */ + +/* tag::GetIntervalDecimal[] */ +typedef fmi3Status fmi3GetIntervalDecimalTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 intervals[], + fmi3IntervalQualifier qualifiers[]); +/* end::GetIntervalDecimal[] */ + +/* tag::GetIntervalFraction[] */ +typedef fmi3Status fmi3GetIntervalFractionTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 counters[], + fmi3UInt64 resolutions[], + fmi3IntervalQualifier qualifiers[]); +/* end::GetIntervalFraction[] */ + +/* tag::GetShiftDecimal[] */ +typedef fmi3Status fmi3GetShiftDecimalTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 shifts[]); +/* end::GetShiftDecimal[] */ + +/* tag::GetShiftFraction[] */ +typedef fmi3Status fmi3GetShiftFractionTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 counters[], + fmi3UInt64 resolutions[]); +/* end::GetShiftFraction[] */ + +/* tag::SetIntervalDecimal[] */ +typedef fmi3Status fmi3SetIntervalDecimalTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 intervals[]); +/* end::SetIntervalDecimal[] */ + +/* tag::SetIntervalFraction[] */ +typedef fmi3Status fmi3SetIntervalFractionTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 counters[], + const fmi3UInt64 resolutions[]); +/* end::SetIntervalFraction[] */ + +/* tag::SetShiftDecimal[] */ +typedef fmi3Status fmi3SetShiftDecimalTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 shifts[]); +/* end::SetShiftDecimal[] */ + +/* tag::SetShiftFraction[] */ +typedef fmi3Status fmi3SetShiftFractionTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 counters[], + const fmi3UInt64 resolutions[]); +/* end::SetShiftFraction[] */ + +/* tag::EvaluateDiscreteStates[] */ +typedef fmi3Status fmi3EvaluateDiscreteStatesTYPE(fmi3Instance instance); +/* end::EvaluateDiscreteStates[] */ + +/* tag::UpdateDiscreteStates[] */ +typedef fmi3Status fmi3UpdateDiscreteStatesTYPE(fmi3Instance instance, + fmi3Boolean *discreteStatesNeedUpdate, + fmi3Boolean *terminateSimulation, + fmi3Boolean *nominalsOfContinuousStatesChanged, + fmi3Boolean *valuesOfContinuousStatesChanged, + fmi3Boolean *nextEventTimeDefined, + fmi3Float64 *nextEventTime); +/* end::UpdateDiscreteStates[] */ + +/*************************************************** +Types for Functions for Model Exchange +****************************************************/ + +/* tag::EnterContinuousTimeMode[] */ +typedef fmi3Status fmi3EnterContinuousTimeModeTYPE(fmi3Instance instance); +/* end::EnterContinuousTimeMode[] */ + +/* tag::CompletedIntegratorStep[] */ +typedef fmi3Status fmi3CompletedIntegratorStepTYPE(fmi3Instance instance, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *enterEventMode, + fmi3Boolean *terminateSimulation); +/* end::CompletedIntegratorStep[] */ + +/* Providing independent variables and re-initialization of caching */ +/* tag::SetTime[] */ +typedef fmi3Status fmi3SetTimeTYPE(fmi3Instance instance, fmi3Float64 time); +/* end::SetTime[] */ + +/* tag::SetContinuousStates[] */ +typedef fmi3Status fmi3SetContinuousStatesTYPE(fmi3Instance instance, + const fmi3Float64 continuousStates[], + size_t nContinuousStates); +/* end::SetContinuousStates[] */ + +/* Evaluation of the model equations */ +/* tag::GetDerivatives[] */ +typedef fmi3Status fmi3GetContinuousStateDerivativesTYPE(fmi3Instance instance, + fmi3Float64 derivatives[], + size_t nContinuousStates); +/* end::GetDerivatives[] */ + +/* tag::GetEventIndicators[] */ +typedef fmi3Status fmi3GetEventIndicatorsTYPE(fmi3Instance instance, + fmi3Float64 eventIndicators[], + size_t nEventIndicators); +/* end::GetEventIndicators[] */ + +/* tag::GetContinuousStates[] */ +typedef fmi3Status fmi3GetContinuousStatesTYPE(fmi3Instance instance, + fmi3Float64 continuousStates[], + size_t nContinuousStates); +/* end::GetContinuousStates[] */ + +/* tag::GetNominalsOfContinuousStates[] */ +typedef fmi3Status fmi3GetNominalsOfContinuousStatesTYPE(fmi3Instance instance, + fmi3Float64 nominals[], + size_t nContinuousStates); +/* end::GetNominalsOfContinuousStates[] */ + +/* tag::GetNumberOfEventIndicators[] */ +typedef fmi3Status fmi3GetNumberOfEventIndicatorsTYPE(fmi3Instance instance, + size_t *nEventIndicators); +/* end::GetNumberOfEventIndicators[] */ + +/* tag::GetNumberOfContinuousStates[] */ +typedef fmi3Status fmi3GetNumberOfContinuousStatesTYPE(fmi3Instance instance, + size_t *nContinuousStates); +/* end::GetNumberOfContinuousStates[] */ + +/*************************************************** +Types for Functions for Co-Simulation +****************************************************/ + +/* Simulating the FMU */ + +/* tag::EnterStepMode[] */ +typedef fmi3Status fmi3EnterStepModeTYPE(fmi3Instance instance); +/* end::EnterStepMode[] */ + +/* tag::GetOutputDerivatives[] */ +typedef fmi3Status fmi3GetOutputDerivativesTYPE(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 orders[], + fmi3Float64 values[], + size_t nValues); +/* end::GetOutputDerivatives[] */ + +/* tag::DoStep[] */ +typedef fmi3Status fmi3DoStepTYPE(fmi3Instance instance, + fmi3Float64 currentCommunicationPoint, + fmi3Float64 communicationStepSize, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *eventHandlingNeeded, + fmi3Boolean *terminateSimulation, + fmi3Boolean *earlyReturn, + fmi3Float64 *lastSuccessfulTime); +/* end::DoStep[] */ + +/*************************************************** +Types for Functions for Scheduled Execution +****************************************************/ + +/* tag::ActivateModelPartition[] */ +typedef fmi3Status fmi3ActivateModelPartitionTYPE(fmi3Instance instance, + fmi3ValueReference clockReference, + fmi3Float64 activationTime); +/* end::ActivateModelPartition[] */ + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif + +#endif /* fmi3FunctionTypes_h */ diff --git a/oscillator/solver-fmi/fmu/include/fmi3Functions.h b/oscillator/solver-fmi/fmu/include/fmi3Functions.h new file mode 100644 index 000000000..68e6814b8 --- /dev/null +++ b/oscillator/solver-fmi/fmu/include/fmi3Functions.h @@ -0,0 +1,343 @@ +#ifndef fmi3Functions_h +#define fmi3Functions_h + +/* +This header file declares the functions of FMI 3.0. +It must be used when compiling an FMU. + +In order to have unique function names even if several FMUs +are compiled together (e.g. for embedded systems), every "real" function name +is constructed by prepending the function name by "FMI3_FUNCTION_PREFIX". +Therefore, the typical usage is: + + #define FMI3_FUNCTION_PREFIX MyModel_ + #include "fmi3Functions.h" + +As a result, a function that is defined as "fmi3GetContinuousStateDerivatives" in this header file, +is actually getting the name "MyModel_fmi3GetContinuousStateDerivatives". + +This only holds if the FMU is shipped in C source code, or is compiled in a +static link library. For FMUs compiled in a DLL/sharedObject, the "actual" function +names are used and "FMI3_FUNCTION_PREFIX" must not be defined. + +Copyright (C) 2008-2011 MODELISAR consortium, + 2012-2022 Modelica Association Project "FMI" + All rights reserved. + +This file is licensed by the copyright holders under the 2-Clause BSD License +(https://opensource.org/licenses/BSD-2-Clause): + +---------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +---------------------------------------------------------------------------- +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "fmi3FunctionTypes.h" +#include "fmi3PlatformTypes.h" + +/* +Allow override of FMI3_FUNCTION_PREFIX: If FMI3_OVERRIDE_FUNCTION_PREFIX +is defined, then FMI3_ACTUAL_FUNCTION_PREFIX will be used, if defined, +or no prefix if undefined. Otherwise FMI3_FUNCTION_PREFIX will be used, +if defined. +*/ +#if !defined(FMI3_OVERRIDE_FUNCTION_PREFIX) && defined(FMI3_FUNCTION_PREFIX) +#define FMI3_ACTUAL_FUNCTION_PREFIX FMI3_FUNCTION_PREFIX +#endif + +/* +Export FMI3 API functions on Windows and under GCC. +If custom linking is desired then the FMI3_Export must be +defined before including this file. For instance, +it may be set to __declspec(dllimport). +*/ +#if !defined(FMI3_Export) +#if !defined(FMI3_ACTUAL_FUNCTION_PREFIX) +#if defined _WIN32 || defined __CYGWIN__ +/* Note: both gcc & MSVC on Windows support this syntax. */ +#define FMI3_Export __declspec(dllexport) +#else +#if __GNUC__ >= 4 +#define FMI3_Export __attribute__((visibility("default"))) +#else +#define FMI3_Export +#endif +#endif +#else +#define FMI3_Export +#endif +#endif + +/* Macros to construct the real function name (prepend function name by FMI3_FUNCTION_PREFIX) */ +#if defined(FMI3_ACTUAL_FUNCTION_PREFIX) +#define fmi3Paste(a, b) a##b +#define fmi3PasteB(a, b) fmi3Paste(a, b) +#define fmi3FullName(name) fmi3PasteB(FMI3_ACTUAL_FUNCTION_PREFIX, name) +#else +#define fmi3FullName(name) name +#endif + +/* FMI version */ +#define fmi3Version "3.0" + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers and set debug logging */ +#define fmi3GetVersion fmi3FullName(fmi3GetVersion) +#define fmi3SetDebugLogging fmi3FullName(fmi3SetDebugLogging) + +/* Creation and destruction of FMU instances */ +#define fmi3InstantiateModelExchange fmi3FullName(fmi3InstantiateModelExchange) +#define fmi3InstantiateCoSimulation fmi3FullName(fmi3InstantiateCoSimulation) +#define fmi3InstantiateScheduledExecution fmi3FullName(fmi3InstantiateScheduledExecution) +#define fmi3FreeInstance fmi3FullName(fmi3FreeInstance) + +/* Enter and exit initialization mode, terminate and reset */ +#define fmi3EnterInitializationMode fmi3FullName(fmi3EnterInitializationMode) +#define fmi3ExitInitializationMode fmi3FullName(fmi3ExitInitializationMode) +#define fmi3EnterEventMode fmi3FullName(fmi3EnterEventMode) +#define fmi3Terminate fmi3FullName(fmi3Terminate) +#define fmi3Reset fmi3FullName(fmi3Reset) + +/* Getting and setting variable values */ +#define fmi3GetFloat32 fmi3FullName(fmi3GetFloat32) +#define fmi3GetFloat64 fmi3FullName(fmi3GetFloat64) +#define fmi3GetInt8 fmi3FullName(fmi3GetInt8) +#define fmi3GetUInt8 fmi3FullName(fmi3GetUInt8) +#define fmi3GetInt16 fmi3FullName(fmi3GetInt16) +#define fmi3GetUInt16 fmi3FullName(fmi3GetUInt16) +#define fmi3GetInt32 fmi3FullName(fmi3GetInt32) +#define fmi3GetUInt32 fmi3FullName(fmi3GetUInt32) +#define fmi3GetInt64 fmi3FullName(fmi3GetInt64) +#define fmi3GetUInt64 fmi3FullName(fmi3GetUInt64) +#define fmi3GetBoolean fmi3FullName(fmi3GetBoolean) +#define fmi3GetString fmi3FullName(fmi3GetString) +#define fmi3GetBinary fmi3FullName(fmi3GetBinary) +#define fmi3GetClock fmi3FullName(fmi3GetClock) +#define fmi3SetFloat32 fmi3FullName(fmi3SetFloat32) +#define fmi3SetFloat64 fmi3FullName(fmi3SetFloat64) +#define fmi3SetInt8 fmi3FullName(fmi3SetInt8) +#define fmi3SetUInt8 fmi3FullName(fmi3SetUInt8) +#define fmi3SetInt16 fmi3FullName(fmi3SetInt16) +#define fmi3SetUInt16 fmi3FullName(fmi3SetUInt16) +#define fmi3SetInt32 fmi3FullName(fmi3SetInt32) +#define fmi3SetUInt32 fmi3FullName(fmi3SetUInt32) +#define fmi3SetInt64 fmi3FullName(fmi3SetInt64) +#define fmi3SetUInt64 fmi3FullName(fmi3SetUInt64) +#define fmi3SetBoolean fmi3FullName(fmi3SetBoolean) +#define fmi3SetString fmi3FullName(fmi3SetString) +#define fmi3SetBinary fmi3FullName(fmi3SetBinary) +#define fmi3SetClock fmi3FullName(fmi3SetClock) + +/* Getting Variable Dependency Information */ +#define fmi3GetNumberOfVariableDependencies fmi3FullName(fmi3GetNumberOfVariableDependencies) +#define fmi3GetVariableDependencies fmi3FullName(fmi3GetVariableDependencies) + +/* Getting and setting the internal FMU state */ +#define fmi3GetFMUState fmi3FullName(fmi3GetFMUState) +#define fmi3SetFMUState fmi3FullName(fmi3SetFMUState) +#define fmi3FreeFMUState fmi3FullName(fmi3FreeFMUState) +#define fmi3SerializedFMUStateSize fmi3FullName(fmi3SerializedFMUStateSize) +#define fmi3SerializeFMUState fmi3FullName(fmi3SerializeFMUState) +#define fmi3DeserializeFMUState fmi3FullName(fmi3DeserializeFMUState) + +/* Getting partial derivatives */ +#define fmi3GetDirectionalDerivative fmi3FullName(fmi3GetDirectionalDerivative) +#define fmi3GetAdjointDerivative fmi3FullName(fmi3GetAdjointDerivative) + +/* Entering and exiting the Configuration or Reconfiguration Mode */ +#define fmi3EnterConfigurationMode fmi3FullName(fmi3EnterConfigurationMode) +#define fmi3ExitConfigurationMode fmi3FullName(fmi3ExitConfigurationMode) + +/* Clock related functions */ +#define fmi3GetIntervalDecimal fmi3FullName(fmi3GetIntervalDecimal) +#define fmi3GetIntervalFraction fmi3FullName(fmi3GetIntervalFraction) +#define fmi3GetShiftDecimal fmi3FullName(fmi3GetShiftDecimal) +#define fmi3GetShiftFraction fmi3FullName(fmi3GetShiftFraction) +#define fmi3SetIntervalDecimal fmi3FullName(fmi3SetIntervalDecimal) +#define fmi3SetIntervalFraction fmi3FullName(fmi3SetIntervalFraction) +#define fmi3SetShiftDecimal fmi3FullName(fmi3SetShiftDecimal) +#define fmi3SetShiftFraction fmi3FullName(fmi3SetShiftFraction) +#define fmi3EvaluateDiscreteStates fmi3FullName(fmi3EvaluateDiscreteStates) +#define fmi3UpdateDiscreteStates fmi3FullName(fmi3UpdateDiscreteStates) + +/*************************************************** +Functions for Model Exchange +****************************************************/ + +#define fmi3EnterContinuousTimeMode fmi3FullName(fmi3EnterContinuousTimeMode) +#define fmi3CompletedIntegratorStep fmi3FullName(fmi3CompletedIntegratorStep) + +/* Providing independent variables and re-initialization of caching */ +#define fmi3SetTime fmi3FullName(fmi3SetTime) +#define fmi3SetContinuousStates fmi3FullName(fmi3SetContinuousStates) + +/* Evaluation of the model equations */ +#define fmi3GetContinuousStateDerivatives fmi3FullName(fmi3GetContinuousStateDerivatives) +#define fmi3GetEventIndicators fmi3FullName(fmi3GetEventIndicators) +#define fmi3GetContinuousStates fmi3FullName(fmi3GetContinuousStates) +#define fmi3GetNominalsOfContinuousStates fmi3FullName(fmi3GetNominalsOfContinuousStates) +#define fmi3GetNumberOfEventIndicators fmi3FullName(fmi3GetNumberOfEventIndicators) +#define fmi3GetNumberOfContinuousStates fmi3FullName(fmi3GetNumberOfContinuousStates) + +/*************************************************** +Functions for Co-Simulation +****************************************************/ + +/* Simulating the FMU */ +#define fmi3EnterStepMode fmi3FullName(fmi3EnterStepMode) +#define fmi3GetOutputDerivatives fmi3FullName(fmi3GetOutputDerivatives) +#define fmi3DoStep fmi3FullName(fmi3DoStep) +#define fmi3ActivateModelPartition fmi3FullName(fmi3ActivateModelPartition) + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers and set debug logging */ +FMI3_Export fmi3GetVersionTYPE fmi3GetVersion; +FMI3_Export fmi3SetDebugLoggingTYPE fmi3SetDebugLogging; + +/* Creation and destruction of FMU instances */ +FMI3_Export fmi3InstantiateModelExchangeTYPE fmi3InstantiateModelExchange; +FMI3_Export fmi3InstantiateCoSimulationTYPE fmi3InstantiateCoSimulation; +FMI3_Export fmi3InstantiateScheduledExecutionTYPE fmi3InstantiateScheduledExecution; +FMI3_Export fmi3FreeInstanceTYPE fmi3FreeInstance; + +/* Enter and exit initialization mode, terminate and reset */ +FMI3_Export fmi3EnterInitializationModeTYPE fmi3EnterInitializationMode; +FMI3_Export fmi3ExitInitializationModeTYPE fmi3ExitInitializationMode; +FMI3_Export fmi3EnterEventModeTYPE fmi3EnterEventMode; +FMI3_Export fmi3TerminateTYPE fmi3Terminate; +FMI3_Export fmi3ResetTYPE fmi3Reset; + +/* Getting and setting variables values */ +FMI3_Export fmi3GetFloat32TYPE fmi3GetFloat32; +FMI3_Export fmi3GetFloat64TYPE fmi3GetFloat64; +FMI3_Export fmi3GetInt8TYPE fmi3GetInt8; +FMI3_Export fmi3GetUInt8TYPE fmi3GetUInt8; +FMI3_Export fmi3GetInt16TYPE fmi3GetInt16; +FMI3_Export fmi3GetUInt16TYPE fmi3GetUInt16; +FMI3_Export fmi3GetInt32TYPE fmi3GetInt32; +FMI3_Export fmi3GetUInt32TYPE fmi3GetUInt32; +FMI3_Export fmi3GetInt64TYPE fmi3GetInt64; +FMI3_Export fmi3GetUInt64TYPE fmi3GetUInt64; +FMI3_Export fmi3GetBooleanTYPE fmi3GetBoolean; +FMI3_Export fmi3GetStringTYPE fmi3GetString; +FMI3_Export fmi3GetBinaryTYPE fmi3GetBinary; +FMI3_Export fmi3GetClockTYPE fmi3GetClock; +FMI3_Export fmi3SetFloat32TYPE fmi3SetFloat32; +FMI3_Export fmi3SetFloat64TYPE fmi3SetFloat64; +FMI3_Export fmi3SetInt8TYPE fmi3SetInt8; +FMI3_Export fmi3SetUInt8TYPE fmi3SetUInt8; +FMI3_Export fmi3SetInt16TYPE fmi3SetInt16; +FMI3_Export fmi3SetUInt16TYPE fmi3SetUInt16; +FMI3_Export fmi3SetInt32TYPE fmi3SetInt32; +FMI3_Export fmi3SetUInt32TYPE fmi3SetUInt32; +FMI3_Export fmi3SetInt64TYPE fmi3SetInt64; +FMI3_Export fmi3SetUInt64TYPE fmi3SetUInt64; +FMI3_Export fmi3SetBooleanTYPE fmi3SetBoolean; +FMI3_Export fmi3SetStringTYPE fmi3SetString; +FMI3_Export fmi3SetBinaryTYPE fmi3SetBinary; +FMI3_Export fmi3SetClockTYPE fmi3SetClock; + +/* Getting Variable Dependency Information */ +FMI3_Export fmi3GetNumberOfVariableDependenciesTYPE fmi3GetNumberOfVariableDependencies; +FMI3_Export fmi3GetVariableDependenciesTYPE fmi3GetVariableDependencies; + +/* Getting and setting the internal FMU state */ +FMI3_Export fmi3GetFMUStateTYPE fmi3GetFMUState; +FMI3_Export fmi3SetFMUStateTYPE fmi3SetFMUState; +FMI3_Export fmi3FreeFMUStateTYPE fmi3FreeFMUState; +FMI3_Export fmi3SerializedFMUStateSizeTYPE fmi3SerializedFMUStateSize; +FMI3_Export fmi3SerializeFMUStateTYPE fmi3SerializeFMUState; +FMI3_Export fmi3DeserializeFMUStateTYPE fmi3DeserializeFMUState; + +/* Getting partial derivatives */ +FMI3_Export fmi3GetDirectionalDerivativeTYPE fmi3GetDirectionalDerivative; +FMI3_Export fmi3GetAdjointDerivativeTYPE fmi3GetAdjointDerivative; + +/* Entering and exiting the Configuration or Reconfiguration Mode */ +FMI3_Export fmi3EnterConfigurationModeTYPE fmi3EnterConfigurationMode; +FMI3_Export fmi3ExitConfigurationModeTYPE fmi3ExitConfigurationMode; + +/* Clock related functions */ +FMI3_Export fmi3GetIntervalDecimalTYPE fmi3GetIntervalDecimal; +FMI3_Export fmi3GetIntervalFractionTYPE fmi3GetIntervalFraction; +FMI3_Export fmi3GetShiftDecimalTYPE fmi3GetShiftDecimal; +FMI3_Export fmi3GetShiftFractionTYPE fmi3GetShiftFraction; +FMI3_Export fmi3SetIntervalDecimalTYPE fmi3SetIntervalDecimal; +FMI3_Export fmi3SetIntervalFractionTYPE fmi3SetIntervalFraction; +FMI3_Export fmi3SetShiftDecimalTYPE fmi3SetShiftDecimal; +FMI3_Export fmi3SetShiftFractionTYPE fmi3SetShiftFraction; +FMI3_Export fmi3EvaluateDiscreteStatesTYPE fmi3EvaluateDiscreteStates; +FMI3_Export fmi3UpdateDiscreteStatesTYPE fmi3UpdateDiscreteStates; + +/*************************************************** +Functions for Model Exchange +****************************************************/ + +FMI3_Export fmi3EnterContinuousTimeModeTYPE fmi3EnterContinuousTimeMode; +FMI3_Export fmi3CompletedIntegratorStepTYPE fmi3CompletedIntegratorStep; + +/* Providing independent variables and re-initialization of caching */ +/* tag::SetTimeTYPE[] */ +FMI3_Export fmi3SetTimeTYPE fmi3SetTime; +/* end::SetTimeTYPE[] */ +FMI3_Export fmi3SetContinuousStatesTYPE fmi3SetContinuousStates; + +/* Evaluation of the model equations */ +FMI3_Export fmi3GetContinuousStateDerivativesTYPE fmi3GetContinuousStateDerivatives; +FMI3_Export fmi3GetEventIndicatorsTYPE fmi3GetEventIndicators; +FMI3_Export fmi3GetContinuousStatesTYPE fmi3GetContinuousStates; +FMI3_Export fmi3GetNominalsOfContinuousStatesTYPE fmi3GetNominalsOfContinuousStates; +FMI3_Export fmi3GetNumberOfEventIndicatorsTYPE fmi3GetNumberOfEventIndicators; +FMI3_Export fmi3GetNumberOfContinuousStatesTYPE fmi3GetNumberOfContinuousStates; + +/*************************************************** +Functions for Co-Simulation +****************************************************/ + +/* Simulating the FMU */ +FMI3_Export fmi3EnterStepModeTYPE fmi3EnterStepMode; +FMI3_Export fmi3GetOutputDerivativesTYPE fmi3GetOutputDerivatives; +FMI3_Export fmi3DoStepTYPE fmi3DoStep; + +/*************************************************** +Functions for Scheduled Execution +****************************************************/ + +FMI3_Export fmi3ActivateModelPartitionTYPE fmi3ActivateModelPartition; + +#ifdef __cplusplus +} /* end of extern "C" { */ +#endif + +#endif /* fmi3Functions_h */ diff --git a/oscillator/solver-fmi/fmu/include/fmi3PlatformTypes.h b/oscillator/solver-fmi/fmu/include/fmi3PlatformTypes.h new file mode 100644 index 000000000..1f42b4159 --- /dev/null +++ b/oscillator/solver-fmi/fmu/include/fmi3PlatformTypes.h @@ -0,0 +1,93 @@ +#ifndef fmi3PlatformTypes_h +#define fmi3PlatformTypes_h + +/* +This header file defines the data types of FMI 3.0. +It must be used by both FMU and FMI master. + +Copyright (C) 2008-2011 MODELISAR consortium, + 2012-2022 Modelica Association Project "FMI" + All rights reserved. + +This file is licensed by the copyright holders under the 2-Clause BSD License +(https://opensource.org/licenses/BSD-2-Clause): + +---------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +---------------------------------------------------------------------------- +*/ + +/* Include the integer and boolean type definitions */ +#include +#include + +/* tag::Component[] */ +typedef void *fmi3Instance; /* Pointer to the FMU instance */ +/* end::Component[] */ + +/* tag::ComponentEnvironment[] */ +typedef void *fmi3InstanceEnvironment; /* Pointer to the FMU environment */ +/* end::ComponentEnvironment[] */ + +/* tag::FMUState[] */ +typedef void *fmi3FMUState; /* Pointer to the internal FMU state */ +/* end::FMUState[] */ + +/* tag::ValueReference[] */ +typedef uint32_t fmi3ValueReference; /* Handle to the value of a variable */ +/* end::ValueReference[] */ + +/* tag::VariableTypes[] */ +typedef float fmi3Float32; /* Single precision floating point (32-bit) */ +/* tag::fmi3Float64[] */ +typedef double fmi3Float64; /* Double precision floating point (64-bit) */ +/* end::fmi3Float64[] */ +typedef int8_t fmi3Int8; /* 8-bit signed integer */ +typedef uint8_t fmi3UInt8; /* 8-bit unsigned integer */ +typedef int16_t fmi3Int16; /* 16-bit signed integer */ +typedef uint16_t fmi3UInt16; /* 16-bit unsigned integer */ +typedef int32_t fmi3Int32; /* 32-bit signed integer */ +typedef uint32_t fmi3UInt32; /* 32-bit unsigned integer */ +typedef int64_t fmi3Int64; /* 64-bit signed integer */ +typedef uint64_t fmi3UInt64; /* 64-bit unsigned integer */ +typedef bool fmi3Boolean; /* Data type to be used with fmi3True and fmi3False */ +typedef char fmi3Char; /* Data type for one character */ +typedef const fmi3Char *fmi3String; /* Data type for character strings + ('\0' terminated, UTF-8 encoded) */ +typedef uint8_t fmi3Byte; /* Smallest addressable unit of the machine + (typically one byte) */ +typedef const fmi3Byte *fmi3Binary; /* Data type for binary data + (out-of-band length terminated) */ +typedef bool fmi3Clock; /* Data type to be used with fmi3ClockActive and + fmi3ClockInactive */ + +/* Values for fmi3Boolean */ +#define fmi3True true +#define fmi3False false + +/* Values for fmi3Clock */ +#define fmi3ClockActive true +#define fmi3ClockInactive false +/* end::VariableTypes[] */ + +#endif /* fmi3PlatformTypes_h */ diff --git a/oscillator/solver-fmi/fmu/include/fmiFunctions.h b/oscillator/solver-fmi/fmu/include/fmiFunctions.h new file mode 100644 index 000000000..635348509 --- /dev/null +++ b/oscillator/solver-fmi/fmu/include/fmiFunctions.h @@ -0,0 +1,228 @@ +#ifndef fmiFunctions_h +#define fmiFunctions_h + +/* This header file must be utilized when compiling a FMU. + It defines all functions of Co-Simulation Interface. + In order to have unique function names even if several FMUs + are compiled together (e.g. for embedded systems), every "real" function name + is constructed by prepending the function name by + "MODEL_IDENTIFIER" + "_" where "MODEL_IDENTIFIER" is the short name + of the model used as the name of the zip-file where the model is stored. + Therefore, the typical usage is: + + #define MODEL_IDENTIFIER MyModel + #include "fmiFunctions.h" + + As a result, a function that is defined as "fmiGetDerivatives" in this header file, + is actually getting the name "MyModel_fmiGetDerivatives". + + Revisions: + - November 4, 2010: Adapted to specification text: + o fmiGetModelTypesPlatform renamed to fmiGetTypesPlatform + o fmiInstantiateSlave: Argument GUID replaced by fmuGUID + Argument mimetype replaced by mimeType + o tabs replaced by spaces + - October 16, 2010: First public Version + + + Copyright(c) 2017, MODELICA Association Project FMI. All rights reserved. + This file is licensed by the copyright holders under the BSD License + (http://www.opensource.org/licenses/bsd-license.html): + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- +*/ + +#include +#include "fmiPlatformTypes.h" + +/* Export fmi functions on Windows */ +#ifdef _MSC_VER +#define DllExport __declspec(dllexport) +#else +#define DllExport +#endif + +/* Macros to construct the real function name + (prepend function name by MODEL_IDENTIFIER + "_") */ + +#define fmiPaste(a, b) a##b +#define fmiPasteB(a, b) fmiPaste(a, b) +#define fmiFullName(name) fmiPasteB(MODEL_IDENTIFIER, name) + +/*************************************************** +Common Functions +****************************************************/ +#define fmiGetTypesPlatform fmiFullName(_fmiGetTypesPlatform) +#define fmiGetVersion fmiFullName(_fmiGetVersion) +#define fmiSetDebugLogging fmiFullName(_fmiSetDebugLogging) + +/*Data Exchange*/ +#define fmiSetReal fmiFullName(_fmiSetReal) +#define fmiSetInteger fmiFullName(_fmiSetInteger) +#define fmiSetBoolean fmiFullName(_fmiSetBoolean) +#define fmiSetString fmiFullName(_fmiSetString) + +#define fmiGetReal fmiFullName(_fmiGetReal) +#define fmiGetInteger fmiFullName(_fmiGetInteger) +#define fmiGetBoolean fmiFullName(_fmiGetBoolean) +#define fmiGetString fmiFullName(_fmiGetString) + +/*************************************************** +Functions for FMI for Co-Simulation +****************************************************/ +#define fmiInstantiateSlave fmiFullName(_fmiInstantiateSlave) +#define fmiInitializeSlave fmiFullName(_fmiInitializeSlave) +#define fmiTerminateSlave fmiFullName(_fmiTerminateSlave) +#define fmiResetSlave fmiFullName(_fmiResetSlave) +#define fmiFreeSlaveInstance fmiFullName(_fmiFreeSlaveInstance) +#define fmiSetRealInputDerivatives fmiFullName(_fmiSetRealInputDerivatives) +#define fmiGetRealOutputDerivatives fmiFullName(_fmiGetRealOutputDerivatives) +#define fmiDoStep fmiFullName(_fmiDoStep) +#define fmiCancelStep fmiFullName(_fmiCancelStep) +#define fmiGetStatus fmiFullName(_fmiGetStatus) +#define fmiGetRealStatus fmiFullName(_fmiGetRealStatus) +#define fmiGetIntegerStatus fmiFullName(_fmiGetIntegerStatus) +#define fmiGetBooleanStatus fmiFullName(_fmiGetBooleanStatus) +#define fmiGetStringStatus fmiFullName(_fmiGetStringStatus) + +/* Version number */ +#define fmiVersion "1.0" + +/* make sure all compiler use the same alignment policies for structures */ +#ifdef WIN32 +#pragma pack(push, 8) +#endif + +/* Type definitions */ +typedef enum { fmiOK, + fmiWarning, + fmiDiscard, + fmiError, + fmiFatal, + fmiPending } fmiStatus; + +typedef void (*fmiCallbackLogger)(fmiComponent c, fmiString instanceName, fmiStatus status, + fmiString category, fmiString message, ...); +typedef void *(*fmiCallbackAllocateMemory)(size_t nobj, size_t size); +typedef void (*fmiCallbackFreeMemory)(void *obj); +typedef void (*fmiStepFinished)(fmiComponent c, fmiStatus status); + +typedef struct { + fmiCallbackLogger logger; + fmiCallbackAllocateMemory allocateMemory; + fmiCallbackFreeMemory freeMemory; + fmiStepFinished stepFinished; +} fmiCallbackFunctions; + +typedef struct { + fmiBoolean iterationConverged; + fmiBoolean stateValueReferencesChanged; + fmiBoolean stateValuesChanged; + fmiBoolean terminateSimulation; + fmiBoolean upcomingTimeEvent; + fmiReal nextEventTime; +} fmiEventInfo; + +/* reset alignment policy to the one set before reading this file */ +#ifdef WIN32 +#pragma pack(pop) +#endif + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers of header files */ +DllExport const char *fmiGetTypesPlatform(); +DllExport const char *fmiGetVersion(); + +DllExport fmiStatus fmiSetDebugLogging(fmiComponent c, fmiBoolean loggingOn); + +/* Data Exchange Functions*/ +DllExport fmiStatus fmiGetReal(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiReal value[]); +DllExport fmiStatus fmiGetInteger(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiInteger value[]); +DllExport fmiStatus fmiGetBoolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiBoolean value[]); +DllExport fmiStatus fmiGetString(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiString value[]); + +DllExport fmiStatus fmiSetReal(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiReal value[]); +DllExport fmiStatus fmiSetInteger(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger value[]); +DllExport fmiStatus fmiSetBoolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiBoolean value[]); +DllExport fmiStatus fmiSetString(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiString value[]); + +/*************************************************** +Functions for FMI for Co-Simulation +****************************************************/ + +/* Creation and destruction of slave instances and setting debug status */ +DllExport fmiComponent fmiInstantiateSlave(fmiString instanceName, + fmiString fmuGUID, + fmiString fmuLocation, + fmiString mimeType, + fmiReal timeout, + fmiBoolean visible, + fmiBoolean interactive, + fmiCallbackFunctions functions, + fmiBoolean loggingOn); + +DllExport fmiStatus fmiInitializeSlave(fmiComponent c, + fmiReal tStart, + fmiBoolean StopTimeDefined, + fmiReal tStop); + +DllExport fmiStatus fmiTerminateSlave(fmiComponent c); +DllExport fmiStatus fmiResetSlave(fmiComponent c); +DllExport void fmiFreeSlaveInstance(fmiComponent c); + +DllExport fmiStatus fmiSetRealInputDerivatives(fmiComponent c, + const fmiValueReference vr[], + size_t nvr, + const fmiInteger order[], + const fmiReal value[]); + +DllExport fmiStatus fmiGetRealOutputDerivatives(fmiComponent c, + const fmiValueReference vr[], + size_t nvr, + const fmiInteger order[], + fmiReal value[]); + +DllExport fmiStatus fmiCancelStep(fmiComponent c); +DllExport fmiStatus fmiDoStep(fmiComponent c, + fmiReal currentCommunicationPoint, + fmiReal communicationStepSize, + fmiBoolean newStep); + +typedef enum { fmiDoStepStatus, + fmiPendingStatus, + fmiLastSuccessfulTime } fmiStatusKind; + +DllExport fmiStatus fmiGetStatus(fmiComponent c, const fmiStatusKind s, fmiStatus *value); +DllExport fmiStatus fmiGetRealStatus(fmiComponent c, const fmiStatusKind s, fmiReal *value); +DllExport fmiStatus fmiGetIntegerStatus(fmiComponent c, const fmiStatusKind s, fmiInteger *value); +DllExport fmiStatus fmiGetBooleanStatus(fmiComponent c, const fmiStatusKind s, fmiBoolean *value); +DllExport fmiStatus fmiGetStringStatus(fmiComponent c, const fmiStatusKind s, fmiString *value); + +#endif // fmiFunctions_h diff --git a/oscillator/solver-fmi/fmu/include/fmiModelFunctions.h b/oscillator/solver-fmi/fmu/include/fmiModelFunctions.h new file mode 100644 index 000000000..d6632a084 --- /dev/null +++ b/oscillator/solver-fmi/fmu/include/fmiModelFunctions.h @@ -0,0 +1,207 @@ +#ifndef fmiModelFunctions_h +#define fmiModelFunctions_h + +/* This header file must be utilized when compiling a model. + It defines all functions of the Model Execution Interface. + In order to have unique function names even if several models + are compiled together (e.g. for embedded systems), every "real" function name + is constructed by prepending the function name by + "MODEL_IDENTIFIER" + "_" where "MODEL_IDENTIFIER" is the short name + of the model used as the name of the zip-file where the model is stored. + Therefore, the typical usage is: + + #define MODEL_IDENTIFIER MyModel + #include "fmiModelFunctions.h" + + As a result, a function that is defined as "fmiGetDerivatives" in this header file, + is actually getting the name "MyModel_fmiGetDerivatives". + + Revisions: + - Jan. 20, 2010: stateValueReferencesChanged added to struct fmiEventInfo (ticket #27) + (by M. Otter, DLR) + Added WIN32 pragma to define the struct layout (ticket #34) + (by J. Mauss, QTronic) + - Jan. 4, 2010: Removed argument intermediateResults from fmiInitialize + Renamed macro fmiGetModelFunctionsVersion to fmiGetVersion + Renamed macro fmiModelFunctionsVersion to fmiVersion + Replaced fmiModel by fmiComponent in decl of fmiInstantiateModel + (by J. Mauss, QTronic) + - Dec. 17, 2009: Changed extension "me" to "fmi" (by Martin Otter, DLR). + - Dez. 14, 2009: Added eventInfo to meInitialize and added + meGetNominalContinuousStates (by Martin Otter, DLR) + - Sept. 9, 2009: Added DllExport (according to Peter Nilsson's suggestion) + (by A. Junghanns, QTronic) + - Sept. 9, 2009: Changes according to FMI-meeting on July 21: + meInquireModelTypesVersion -> meGetModelTypesPlatform + meInquireModelFunctionsVersion -> meGetModelFunctionsVersion + meSetStates -> meSetContinuousStates + meGetStates -> meGetContinuousStates + removal of meInitializeModelClass + removal of meGetTime + change of arguments of meInstantiateModel + change of arguments of meCompletedIntegratorStep + (by Martin Otter, DLR): + - July 19, 2009: Added "me" as prefix to file names (by Martin Otter, DLR). + - March 2, 2009: Changed function definitions according to the last design + meeting with additional improvements (by Martin Otter, DLR). + - Dec. 3 , 2008: First version by Martin Otter (DLR) and Hans Olsson (Dynasim). + + + Copyright(c) 2017, MODELICA Association Project FMI. All rights reserved. + This file is licensed by the copyright holders under the BSD License + (http://www.opensource.org/licenses/bsd-license.html): + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- + + with the extension: + + You may distribute or publicly perform any modification only under the + terms of this license. +*/ + +#include +#include "fmiModelTypes.h" + +/* Export fmi functions on Windows */ +#ifdef _MSC_VER +#define DllExport __declspec(dllexport) +#else +#define DllExport +#endif + +/* Macros to construct the real function name + (prepend function name by MODEL_IDENTIFIER + "_") */ + +#define fmiPaste(a, b) a##b +#define fmiPasteB(a, b) fmiPaste(a, b) +#define fmiFullName(name) fmiPasteB(MODEL_IDENTIFIER, name) + +#define fmiGetModelTypesPlatform fmiFullName(_fmiGetModelTypesPlatform) +#define fmiGetVersion fmiFullName(_fmiGetVersion) +#define fmiInstantiateModel fmiFullName(_fmiInstantiateModel) +#define fmiFreeModelInstance fmiFullName(_fmiFreeModelInstance) +#define fmiSetDebugLogging fmiFullName(_fmiSetDebugLogging) +#define fmiSetTime fmiFullName(_fmiSetTime) +#define fmiSetContinuousStates fmiFullName(_fmiSetContinuousStates) +#define fmiCompletedIntegratorStep fmiFullName(_fmiCompletedIntegratorStep) +#define fmiSetReal fmiFullName(_fmiSetReal) +#define fmiSetInteger fmiFullName(_fmiSetInteger) +#define fmiSetBoolean fmiFullName(_fmiSetBoolean) +#define fmiSetString fmiFullName(_fmiSetString) +#define fmiInitialize fmiFullName(_fmiInitialize) +#define fmiGetDerivatives fmiFullName(_fmiGetDerivatives) +#define fmiGetEventIndicators fmiFullName(_fmiGetEventIndicators) +#define fmiGetReal fmiFullName(_fmiGetReal) +#define fmiGetInteger fmiFullName(_fmiGetInteger) +#define fmiGetBoolean fmiFullName(_fmiGetBoolean) +#define fmiGetString fmiFullName(_fmiGetString) +#define fmiEventUpdate fmiFullName(_fmiEventUpdate) +#define fmiGetContinuousStates fmiFullName(_fmiGetContinuousStates) +#define fmiGetNominalContinuousStates fmiFullName(_fmiGetNominalContinuousStates) +#define fmiGetStateValueReferences fmiFullName(_fmiGetStateValueReferences) +#define fmiTerminate fmiFullName(_fmiTerminate) + +/* Version number */ +#define fmiVersion "1.0" + +/* Inquire version numbers of header files */ +DllExport const char *fmiGetModelTypesPlatform(); +DllExport const char *fmiGetVersion(); + +/* make sure all compiler use the same alignment policies for structures */ +#ifdef WIN32 +#pragma pack(push, 8) +#endif + +/* Type definitions */ +typedef enum { fmiOK, + fmiWarning, + fmiDiscard, + fmiError, + fmiFatal } fmiStatus; + +typedef void (*fmiCallbackLogger)(fmiComponent c, fmiString instanceName, fmiStatus status, + fmiString category, fmiString message, ...); +typedef void *(*fmiCallbackAllocateMemory)(size_t nobj, size_t size); +typedef void (*fmiCallbackFreeMemory)(void *obj); + +typedef struct { + fmiCallbackLogger logger; + fmiCallbackAllocateMemory allocateMemory; + fmiCallbackFreeMemory freeMemory; +} fmiCallbackFunctions; + +typedef struct { + fmiBoolean iterationConverged; + fmiBoolean stateValueReferencesChanged; + fmiBoolean stateValuesChanged; + fmiBoolean terminateSimulation; + fmiBoolean upcomingTimeEvent; + fmiReal nextEventTime; +} fmiEventInfo; + +/* reset alignment policy to the one set before reading this file */ +#ifdef WIN32 +#pragma pack(pop) +#endif + +/* Creation and destruction of model instances and setting debug status */ +DllExport fmiComponent fmiInstantiateModel(fmiString instanceName, + fmiString GUID, + fmiCallbackFunctions functions, + fmiBoolean loggingOn); +DllExport void fmiFreeModelInstance(fmiComponent c); +DllExport fmiStatus fmiSetDebugLogging(fmiComponent c, fmiBoolean loggingOn); + +/* Providing independent variables and re-initialization of caching */ +DllExport fmiStatus fmiSetTime(fmiComponent c, fmiReal time); +DllExport fmiStatus fmiSetContinuousStates(fmiComponent c, const fmiReal x[], size_t nx); +DllExport fmiStatus fmiCompletedIntegratorStep(fmiComponent c, fmiBoolean *callEventUpdate); +DllExport fmiStatus fmiSetReal(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiReal value[]); +DllExport fmiStatus fmiSetInteger(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiInteger value[]); +DllExport fmiStatus fmiSetBoolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiBoolean value[]); +DllExport fmiStatus fmiSetString(fmiComponent c, const fmiValueReference vr[], size_t nvr, const fmiString value[]); + +/* Evaluation of the model equations */ +DllExport fmiStatus fmiInitialize(fmiComponent c, fmiBoolean toleranceControlled, + fmiReal relativeTolerance, fmiEventInfo *eventInfo); + +DllExport fmiStatus fmiGetDerivatives(fmiComponent c, fmiReal derivatives[], size_t nx); +DllExport fmiStatus fmiGetEventIndicators(fmiComponent c, fmiReal eventIndicators[], size_t ni); + +DllExport fmiStatus fmiGetReal(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiReal value[]); +DllExport fmiStatus fmiGetInteger(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiInteger value[]); +DllExport fmiStatus fmiGetBoolean(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiBoolean value[]); +DllExport fmiStatus fmiGetString(fmiComponent c, const fmiValueReference vr[], size_t nvr, fmiString value[]); + +DllExport fmiStatus fmiEventUpdate(fmiComponent c, fmiBoolean intermediateResults, fmiEventInfo *eventInfo); +DllExport fmiStatus fmiGetContinuousStates(fmiComponent c, fmiReal states[], size_t nx); +DllExport fmiStatus fmiGetNominalContinuousStates(fmiComponent c, fmiReal x_nominal[], size_t nx); +DllExport fmiStatus fmiGetStateValueReferences(fmiComponent c, fmiValueReference vrx[], size_t nx); +DllExport fmiStatus fmiTerminate(fmiComponent c); + +#endif // fmiModelFunctions_h diff --git a/oscillator/solver-fmi/fmu/include/fmiModelTypes.h b/oscillator/solver-fmi/fmu/include/fmiModelTypes.h new file mode 100644 index 000000000..da92984ad --- /dev/null +++ b/oscillator/solver-fmi/fmu/include/fmiModelTypes.h @@ -0,0 +1,91 @@ +#ifndef fmiModelTypes_h +#define fmiModelTypes_h + +/* Standard header file to define the argument types of the + functions of the Model Execution Interface. + This header file must be utilized both by the model and + by the simulation engine. + + Revisions: + - Jan. 4, 2010: Renamed meModelTypes_h to fmiModelTypes_h (by Mauss, QTronic) + - Dec. 21, 2009: Changed "me" to "fmi" and "meModel" to "fmiComponent" + according to meeting on Dec. 18 (by Martin Otter, DLR) + - Dec. 6, 2009: Added meUndefinedValueReference (by Martin Otter, DLR) + - Sept. 9, 2009: Changes according to FMI-meeting on July 21: + Changed "version" to "platform", "standard" to "standard32", + Added a precise definition of "standard32" as comment + (by Martin Otter, DLR) + - July 19, 2009: Added "me" as prefix to file names, added meTrue/meFalse, + and changed meValueReferenced from int to unsigned int + (by Martin Otter, DLR). + - March 2, 2009: Moved enums and function pointer definitions to + ModelFunctions.h (by Martin Otter, DLR). + - Dec. 3, 2008 : First version by Martin Otter (DLR) and + Hans Olsson (Dynasim). + + + Copyright(c) 2017, MODELICA Association Project FMI. All rights reserved. + This file is licensed by the copyright holders under the BSD License + (http://www.opensource.org/licenses/bsd-license.html) + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- + + with the extension: + + You may distribute or publicly perform any modification only under the + terms of this license. +*/ + +/* Platform (combination of machine, compiler, operating system) */ +#define fmiModelTypesPlatform "standard32" + +/* Type definitions of variables passed as arguments + Version "standard32" means: + + fmiComponent : 32 bit pointer + fmiValueReference: 32 bit + fmiReal : 64 bit + fmiInteger : 32 bit + fmiBoolean : 8 bit + fmiString : 32 bit pointer + +*/ +typedef void *fmiComponent; +typedef unsigned int fmiValueReference; +typedef double fmiReal; +typedef int fmiInteger; +typedef char fmiBoolean; +typedef const char *fmiString; + +/* Values for fmiBoolean */ +#define fmiTrue 1 +#define fmiFalse 0 + +/* Undefined value for fmiValueReference (largest unsigned int value) */ +#define fmiUndefinedValueReference (fmiValueReference)(-1) + +#endif diff --git a/oscillator/solver-fmi/fmu/include/fmiPlatformTypes.h b/oscillator/solver-fmi/fmu/include/fmiPlatformTypes.h new file mode 100644 index 000000000..ef9a78514 --- /dev/null +++ b/oscillator/solver-fmi/fmu/include/fmiPlatformTypes.h @@ -0,0 +1,73 @@ +#ifndef fmiPlatformTypes_h +#define fmiPlatformTypes_h + +/* Standard header file to define the argument types of the + functions of the Model Execution Interface. + This header file must be utilized both by the model and + by the simulation engine. + + Revisions: + - October 2010: First public Version + + + Copyright(c) 2017, MODELICA Association Project FMI. All rights reserved. + This file is licensed by the copyright holders under the BSD License + (http://www.opensource.org/licenses/bsd-license.html): + + + ---------------------------------------------------------------------------- + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------- +*/ + +/* Platform (combination of machine, compiler, operating system) */ +#define fmiPlatform "standard32" + +/* Type definitions of variables passed as arguments + Version "standard32" means: + + fmiComponent : 32 bit pointer + fmiValueReference: 32 bit + fmiReal : 64 bit + fmiInteger : 32 bit + fmiBoolean : 8 bit + fmiString : 32 bit pointer + +*/ +typedef void *fmiComponent; +typedef unsigned int fmiValueReference; +typedef double fmiReal; +typedef int fmiInteger; +typedef char fmiBoolean; +typedef const char *fmiString; + +/* Values for fmiBoolean */ +#define fmiTrue 1 +#define fmiFalse 0 + +/* Undefined value for fmiValueReference (largest unsigned int value) */ +#define fmiUndefinedValueReference (fmiValueReference)(-1) + +#endif diff --git a/oscillator/solver-fmi/fmu/include/model.h b/oscillator/solver-fmi/fmu/include/model.h new file mode 100644 index 000000000..f27a3c99a --- /dev/null +++ b/oscillator/solver-fmi/fmu/include/model.h @@ -0,0 +1,235 @@ +#pragma once + +#if FMI_VERSION != 1 && FMI_VERSION != 2 && FMI_VERSION != 3 +#error FMI_VERSION must be one of 1, 2 or 3 +#endif + +#define UNUSED(x) (void) (x) + +#include // for bool +#include // for size_t +#include + +#include "config.h" + +#if FMI_VERSION == 1 + +#define not_modelError (Instantiated | Initialized | Terminated) + +typedef enum { + Instantiated = 1 << 0, + Initialized = 1 << 1, + Terminated = 1 << 2, + modelError = 1 << 3 +} ModelState; + +#elif FMI_VERSION == 2 + +typedef enum { + StartAndEnd = 1 << 0, + Instantiated = 1 << 1, + InitializationMode = 1 << 2, + + // ME states + EventMode = 1 << 3, + ContinuousTimeMode = 1 << 4, + + // CS states + StepComplete = 1 << 5, + StepInProgress = 1 << 6, + StepFailed = 1 << 7, + StepCanceled = 1 << 8, + + Terminated = 1 << 9, + modelError = 1 << 10, + modelFatal = 1 << 11, +} ModelState; + +#else + +typedef enum { + StartAndEnd = 1 << 0, + ConfigurationMode = 1 << 1, + Instantiated = 1 << 2, + InitializationMode = 1 << 3, + EventMode = 1 << 4, + ContinuousTimeMode = 1 << 5, + StepMode = 1 << 6, + ClockActivationMode = 1 << 7, + StepDiscarded = 1 << 8, + ReconfigurationMode = 1 << 9, + IntermediateUpdateMode = 1 << 10, + Terminated = 1 << 11, + modelError = 1 << 12, + modelFatal = 1 << 13, +} ModelState; + +#endif + +typedef enum { + ModelExchange, + CoSimulation, + ScheduledExecution, +} InterfaceType; + +typedef enum { + OK, + Warning, + Discard, + Error, + Fatal, + Pending +} Status; + +#if FMI_VERSION < 3 +typedef void (*loggerType)(void *componentEnvironment, const char *instanceName, int status, const char *category, const char *message, ...); +#else +typedef void (*loggerType)(void *componentEnvironment, int status, const char *category, const char *message); +#endif + +typedef void (*lockPreemptionType)(); +typedef void (*unlockPreemptionType)(); + +typedef void (*intermediateUpdateType)(void *instanceEnvironment, + double intermediateUpdateTime, + bool intermediateVariableSetRequested, + bool intermediateVariableGetAllowed, + bool intermediateStepFinished, + bool canReturnEarly, + bool *earlyReturnRequested, + double *earlyReturnTime); + +typedef void (*clockUpdateType)(void *instanceEnvironment); + +typedef struct { + + double startTime; + double time; + double solverStepSize; + const char *instanceName; + InterfaceType type; + const char *resourceLocation; + + Status status; + + // callback functions + loggerType logger; + intermediateUpdateType intermediateUpdate; + clockUpdateType clockUpdate; + + lockPreemptionType lockPreemtion; + unlockPreemptionType unlockPreemtion; + + bool logEvents; + bool logErrors; + + void *componentEnvironment; + ModelState state; + + // event info + bool newDiscreteStatesNeeded; + bool terminateSimulation; + bool nominalsOfContinuousStatesChanged; + bool valuesOfContinuousStatesChanged; + bool nextEventTimeDefined; + double nextEventTime; + bool clocksTicked; + + bool isDirtyValues; + + ModelData modelData; + +#if NZ > 0 + // event indicators + double z[NZ]; +#endif + + // internal solver steps + uint64_t nSteps; + + // Co-Simulation + bool earlyReturnAllowed; + bool eventModeUsed; + +} ModelInstance; + +ModelInstance *createModelInstance( + loggerType logger, + intermediateUpdateType intermediateUpdate, + void *componentEnvironment, + const char *instanceName, + const char *instantiationToken, + const char *resourceLocation, + bool loggingOn, + InterfaceType interfaceType); + +void freeModelInstance(ModelInstance *comp); + +void reset(ModelInstance *comp); + +void setStartValues(ModelInstance *comp); + +Status calculateValues(ModelInstance *comp); + +Status getFloat32(ModelInstance *comp, ValueReference vr, float value[], size_t *index); +Status getFloat64(ModelInstance *comp, ValueReference vr, double value[], size_t *index); +Status getInt8(ModelInstance *comp, ValueReference vr, int8_t value[], size_t *index); +Status getUInt8(ModelInstance *comp, ValueReference vr, uint8_t value[], size_t *index); +Status getInt16(ModelInstance *comp, ValueReference vr, int16_t value[], size_t *index); +Status getUInt16(ModelInstance *comp, ValueReference vr, uint16_t value[], size_t *index); +Status getInt32(ModelInstance *comp, ValueReference vr, int32_t value[], size_t *index); +Status getUInt32(ModelInstance *comp, ValueReference vr, uint32_t value[], size_t *index); +Status getInt64(ModelInstance *comp, ValueReference vr, int64_t value[], size_t *index); +Status getUInt64(ModelInstance *comp, ValueReference vr, uint64_t value[], size_t *index); +Status getBoolean(ModelInstance *comp, ValueReference vr, bool value[], size_t *index); +Status getString(ModelInstance *comp, ValueReference vr, const char *value[], size_t *index); +Status getBinary(ModelInstance *comp, ValueReference vr, size_t size[], const char *value[], size_t *index); + +Status setFloat32(ModelInstance *comp, ValueReference vr, const float value[], size_t *index); +Status setFloat64(ModelInstance *comp, ValueReference vr, const double value[], size_t *index); +Status setInt8(ModelInstance *comp, ValueReference vr, const int8_t value[], size_t *index); +Status setUInt8(ModelInstance *comp, ValueReference vr, const uint8_t value[], size_t *index); +Status setInt16(ModelInstance *comp, ValueReference vr, const int16_t value[], size_t *index); +Status setUInt16(ModelInstance *comp, ValueReference vr, const uint16_t value[], size_t *index); +Status setInt32(ModelInstance *comp, ValueReference vr, const int32_t value[], size_t *index); +Status setUInt32(ModelInstance *comp, ValueReference vr, const uint32_t value[], size_t *index); +Status setInt64(ModelInstance *comp, ValueReference vr, const int64_t value[], size_t *index); +Status setUInt64(ModelInstance *comp, ValueReference vr, const uint64_t value[], size_t *index); +Status setBoolean(ModelInstance *comp, ValueReference vr, const bool value[], size_t *index); +Status setString(ModelInstance *comp, ValueReference vr, const char *const value[], size_t *index); +Status setBinary(ModelInstance *comp, ValueReference vr, const size_t size[], const char *const value[], size_t *index); + +Status activateClock(ModelInstance *comp, ValueReference vr); +Status getClock(ModelInstance *comp, ValueReference vr, bool *value); +Status setClock(ModelInstance *comp, ValueReference vr, const bool *value); + +Status getInterval(ModelInstance *comp, ValueReference vr, double *interval, int *qualifier); + +Status activateModelPartition(ModelInstance *comp, ValueReference vr, double activationTime); + +void getContinuousStates(ModelInstance *comp, double x[], size_t nx); +void setContinuousStates(ModelInstance *comp, const double x[], size_t nx); +void getDerivatives(ModelInstance *comp, double dx[], size_t nx); +Status getOutputDerivative(ModelInstance *comp, ValueReference valueReference, int order, double *value); +Status getPartialDerivative(ModelInstance *comp, ValueReference unknown, ValueReference known, double *partialDerivative); +void getEventIndicators(ModelInstance *comp, double z[], size_t nz); +void eventUpdate(ModelInstance *comp); +// void updateEventTime(ModelInstance *comp); + +bool invalidNumber(ModelInstance *comp, const char *f, const char *arg, size_t actual, size_t expected); +bool invalidState(ModelInstance *comp, const char *f, int statesExpected); +bool nullPointer(ModelInstance *comp, const char *f, const char *arg, const void *p); +void logError(ModelInstance *comp, const char *message, ...); +Status setDebugLogging(ModelInstance *comp, bool loggingOn, size_t nCategories, const char *const categories[]); +void logEvent(ModelInstance *comp, const char *message, ...); +void logError(ModelInstance *comp, const char *message, ...); + +void *getFMUState(ModelInstance *comp); +void setFMUState(ModelInstance *comp, void *FMUState); + +// shorthand to access the variables +#define M(u) (comp->modelData.u) + +// "stringification" macros +#define xstr(s) str(s) +#define str(s) #s diff --git a/oscillator/solver-fmi/fmu/set_tool_version.py b/oscillator/solver-fmi/fmu/set_tool_version.py new file mode 100644 index 000000000..ba855c9cc --- /dev/null +++ b/oscillator/solver-fmi/fmu/set_tool_version.py @@ -0,0 +1,45 @@ +import os.path +import subprocess +import sys + + +def set_tool_version(filename, git_executable='git'): + """ Set the Git tag or hash in the generationTool attribute if the repo is clean """ + + cwd = os.path.dirname(__file__) + + changed_files = subprocess.check_output( + [git_executable, 'status', '--porcelain', '--untracked=no'], cwd=cwd).decode('ascii').strip() + + if changed_files: + return + + version = subprocess.check_output([git_executable, 'tag', '--contains'], cwd=cwd).decode('ascii').strip() + + if not version: + version = subprocess.check_output([git_executable, 'rev-parse', '--short', + 'HEAD'], cwd=cwd).decode('ascii').strip() + + if not version: + return + + with open(filename, 'r') as f: + lines = f.read() + + lines = lines.replace('"Reference FMUs (development build)"', f'"Reference FMUs ({version})"') + + with open(filename, 'w') as f: + f.write(lines) + + +if __name__ == '__main__': + + try: + if len(sys.argv) > 2: + set_tool_version(sys.argv[1], sys.argv[2]) + elif len(sys.argv) > 1: + set_tool_version(sys.argv[1]) + else: + raise RuntimeError('Not enough arguments') + except Exception as e: + print(e) diff --git a/oscillator/solver-fmi/fmu/src/FMI.c b/oscillator/solver-fmi/fmu/src/FMI.c new file mode 100644 index 000000000..b3fd16044 --- /dev/null +++ b/oscillator/solver-fmi/fmu/src/FMI.c @@ -0,0 +1,329 @@ +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#pragma comment(lib, "shlwapi.lib") +#else +#include +#include +#endif + +#ifdef _MSC_VER +#define strdup _strdup +#endif + +#include "FMI.h" + +#define INITIAL_MESSAGE_BUFFER_SIZE 1024 + +FMIInstance *FMICreateInstance(const char *instanceName, const char *libraryPath, FMILogMessage *logMessage, FMILogFunctionCall *logFunctionCall) +{ + +#ifdef _WIN32 + TCHAR Buffer[1024]; + GetCurrentDirectory(1024, Buffer); + + WCHAR dllDirectory[MAX_PATH]; + + // convert path to unicode + mbstowcs(dllDirectory, libraryPath, MAX_PATH); + + // remove the file name + PathRemoveFileSpecW(dllDirectory); + + // add the binaries directory temporarily to the DLL path to allow discovery of dependencies + DLL_DIRECTORY_COOKIE dllDirectoryCookie = AddDllDirectory(dllDirectory); + + // TODO: log getLastSystemError() + + HMODULE libraryHandle = LoadLibraryExA(libraryPath, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + + // remove the binaries directory from the DLL path + if (dllDirectoryCookie) { + RemoveDllDirectory(dllDirectoryCookie); + } + + // TODO: log error + +#else + void *libraryHandle = dlopen(libraryPath, RTLD_LAZY); +#endif + + if (!libraryHandle) { + return NULL; + } + + FMIInstance *instance = (FMIInstance *) calloc(1, sizeof(FMIInstance)); + + instance->libraryHandle = libraryHandle; + + instance->logMessage = logMessage; + instance->logFunctionCall = logFunctionCall; + + instance->bufsize1 = INITIAL_MESSAGE_BUFFER_SIZE; + instance->bufsize2 = INITIAL_MESSAGE_BUFFER_SIZE; + + instance->buf1 = (char *) calloc(instance->bufsize1, sizeof(char)); + instance->buf2 = (char *) calloc(instance->bufsize1, sizeof(char)); + + instance->name = strdup(instanceName); + + instance->status = FMIOK; + + return instance; +} + +void FMIFreeInstance(FMIInstance *instance) +{ + + if (!instance) { + return; + } + + // unload the shared library + if (instance->libraryHandle) { +#ifdef _WIN32 + FreeLibrary(instance->libraryHandle); +#else + dlclose(instance->libraryHandle); +#endif + instance->libraryHandle = NULL; + } + + free(instance->buf1); + free(instance->buf2); + free((void *) instance->name); + + free(instance->fmi2Functions); + free(instance->fmi3Functions); + + free(instance); +} + +const char *FMIValueReferencesToString(FMIInstance *instance, const FMIValueReference vr[], size_t nvr) +{ + + size_t pos = 0; + + do { + pos += snprintf(&instance->buf1[pos], instance->bufsize1 - pos, "{"); + + for (size_t i = 0; i < nvr; i++) { + + pos += snprintf(&instance->buf1[pos], instance->bufsize1 - pos, i < nvr - 1 ? "%u, " : "%u", vr[i]); + + if (pos > instance->bufsize1 - 2) { + pos = 0; + instance->bufsize1 *= 2; + instance->buf1 = (char *) realloc(instance->buf1, instance->bufsize1); + break; + } + } + } while (pos == 0); + + pos += snprintf(&instance->buf1[pos], instance->bufsize1 - pos, "}"); + + return instance->buf1; +} + +const char *FMIValuesToString(FMIInstance *instance, size_t vValues, const size_t sizes[], const void *values, FMIVariableType variableType) +{ + + size_t pos = 0; + + do { + pos += snprintf(&instance->buf2[pos], instance->bufsize2 - pos, "{"); + + for (size_t i = 0; i < vValues; i++) { + + char *s = &instance->buf2[pos]; + size_t n = instance->bufsize2 - pos; + + switch (variableType) { + case FMIFloat32Type: + case FMIDiscreteFloat32Type: + pos += snprintf(s, n, "%.7g", ((float *) values)[i]); + break; + case FMIFloat64Type: + case FMIDiscreteFloat64Type: + pos += snprintf(s, n, "%.16g", ((double *) values)[i]); + break; + case FMIInt8Type: + pos += snprintf(s, n, "%" PRId8, ((int8_t *) values)[i]); + break; + case FMIUInt8Type: + pos += snprintf(s, n, "%" PRIu8, ((uint8_t *) values)[i]); + break; + case FMIInt16Type: + pos += snprintf(s, n, "%" PRId16, ((int16_t *) values)[i]); + break; + case FMIUInt16Type: + pos += snprintf(s, n, "%" PRIu16, ((uint16_t *) values)[i]); + break; + case FMIInt32Type: + pos += snprintf(s, n, "%" PRId32, ((int32_t *) values)[i]); + break; + case FMIUInt32Type: + pos += snprintf(s, n, "%" PRIu32, ((uint32_t *) values)[i]); + break; + case FMIInt64Type: + pos += snprintf(s, n, "%" PRId64, ((int64_t *) values)[i]); + break; + case FMIUInt64Type: + pos += snprintf(s, n, "%" PRIu64, ((uint64_t *) values)[i]); + break; + case FMIBooleanType: + switch (instance->fmiVersion) { + case FMIVersion1: + pos += snprintf(s, n, "%d", ((char *) values)[i]); + break; + case FMIVersion2: + pos += snprintf(s, n, "%d", ((int *) values)[i]); + break; + case FMIVersion3: + pos += snprintf(s, n, "%d", ((bool *) values)[i]); + break; + } + break; + case FMIStringType: + pos += snprintf(s, n, "\"%s\"", ((const char **) values)[i]); + break; + case FMIBinaryType: { + const size_t size = sizes[i]; + const unsigned char *v = ((const unsigned char **) values)[i]; + for (size_t j = 0; j < size; j++) { + pos += snprintf(&instance->buf2[pos], instance->bufsize2 - pos, "%02hhx", v[j]); + } + break; + } + case FMIClockType: + pos += snprintf(s, n, "%d", ((bool *) values)[i]); + break; + } + + if (i < vValues - 1) { + pos += snprintf(&instance->buf2[pos], instance->bufsize2 - pos, ", "); + } + + // resize the buffer if we ran out of space + if (pos > instance->bufsize2 - 2) { + pos = 0; + instance->bufsize2 *= 2; + instance->buf2 = (char *) realloc(instance->buf2, instance->bufsize2); + break; + } + } + + } while (pos == 0); // run again if the buffer has been resized + + pos += snprintf(&instance->buf2[pos], instance->bufsize2 - pos, "}"); + + return instance->buf2; +} + +FMIStatus FMIURIToPath(const char *uri, char *path, const size_t pathLength) +{ + +#ifdef _WIN32 + DWORD pcchPath = (DWORD) pathLength; + + if (PathCreateFromUrlA(uri, path, &pcchPath, 0) != S_OK) { + return FMIError; + } +#else + const char *scheme1 = "file:///"; + const char *scheme2 = "file:/"; + + strncpy(path, uri, pathLength); + + if (strncmp(uri, scheme1, strlen(scheme1)) == 0) { + strncpy(path, &uri[strlen(scheme1)] - 1, pathLength); + } else if (strncmp(uri, scheme2, strlen(scheme2)) == 0) { + strncpy(path, &uri[strlen(scheme2) - 1], pathLength); + } else { + return FMIError; + } +#endif + +#ifdef _WIN32 + const char *sep = "\\"; +#else + const char *sep = "/"; +#endif + + if (path[strlen(path) - 1] != sep[0]) { + strncat(path, sep, pathLength); + } + + return FMIOK; +} + +FMIStatus FMIPathToURI(const char *path, char *uri, const size_t uriLength) +{ + +#ifdef _WIN32 + DWORD pcchUri = (DWORD) uriLength; + + if (UrlCreateFromPathA(path, uri, &pcchUri, 0) != S_OK) { + return FMIError; + } +#else + snprintf(uri, uriLength, "file://%s", path); + + if (path[strlen(path) - 1] != '/') { + strncat(uri, "/", uriLength); + } +#endif + + return FMIOK; +} + +FMIStatus FMIPlatformBinaryPath(const char *unzipdir, const char *modelIdentifier, FMIVersion fmiVersion, char *platformBinaryPath, size_t size) +{ + +#if defined(_WIN32) + const char *platform = "win"; + const char *system = "windows"; + const char sep = '\\'; + const char *ext = ".dll"; +#elif defined(__APPLE__) + const char *platform = "darwin"; + const char *system = "darwin"; + const char sep = '/'; + const char *ext = ".dylib"; +#else + const char *platform = "linux"; + const char *system = "linux"; + const char sep = '/'; + const char *ext = ".so"; +#endif + +#if defined(_WIN64) || defined(__x86_64__) + const char *bits = "64"; + const char *arch = "x86_64"; +#else + const char *bits = "32"; + const char *arch = "x86"; +#endif + const char *bin = "binaries"; + char optSep[2] = ""; + int rc; + + if (unzipdir[strlen(unzipdir) - 1] != sep) { + optSep[0] = sep; + } + if (fmiVersion == 3) { + rc = snprintf(platformBinaryPath, size, "%s%s%s%c%s-%s%c%s%s", unzipdir, optSep, bin, sep, arch, system, sep, modelIdentifier, ext); + } else { + rc = snprintf(platformBinaryPath, size, "%s%s%s%c%s%s%c%s%s", unzipdir, optSep, bin, sep, platform, bits, sep, modelIdentifier, ext); + } + + if (rc >= size) { + return FMIError; + } + + return FMIOK; +} diff --git a/oscillator/solver-fmi/fmu/src/FMI2.c b/oscillator/solver-fmi/fmu/src/FMI2.c new file mode 100644 index 000000000..b0321c653 --- /dev/null +++ b/oscillator/solver-fmi/fmu/src/FMI2.c @@ -0,0 +1,569 @@ +#ifdef _WIN32 +#include +#include "Shlwapi.h" +#pragma comment(lib, "shlwapi.lib") +#define strdup _strdup +#define INTERNET_MAX_URL_LENGTH 2083 // from wininet.h +#else +#include +#include +#endif + +#include +#include +#include + +#include "FMI2.h" + +static void cb_logMessage2(fmi2ComponentEnvironment componentEnvironment, fmi2String instanceName, fmi2Status status, fmi2String category, fmi2String message, ...) +{ + + if (!componentEnvironment) + return; + + FMIInstance *instance = componentEnvironment; + + char buf[FMI_MAX_MESSAGE_LENGTH]; + + va_list args; + + va_start(args, message); + vsnprintf(buf, FMI_MAX_MESSAGE_LENGTH, message, args); + va_end(args); + + if (!instance->logMessage) + return; + + instance->logMessage(instance, (FMIStatus) status, category, buf); +} + +#if defined(FMI2_FUNCTION_PREFIX) +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi2Functions->fmi2##f = fmi2##f; \ + } while (0) +#elif defined(_WIN32) +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi2Functions->fmi2##f = (fmi2##f##TYPE *) GetProcAddress(instance->libraryHandle, "fmi2" #f); \ + if (!instance->fmi2Functions->fmi2##f) { \ + instance->logMessage(instance, FMIFatal, "fatal", "Symbol fmi2" #f " is missing in shared library."); \ + return fmi2Fatal; \ + } \ + } while (0) +#else +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi2Functions->fmi2##f = (fmi2##f##TYPE *) dlsym(instance->libraryHandle, "fmi2" #f); \ + if (!instance->fmi2Functions->fmi2##f) { \ + instance->logMessage(instance, FMIFatal, "fatal", "Symbol fmi2" #f " is missing in shared library."); \ + return FMIFatal; \ + } \ + } while (0) +#endif + +#define CALL(f) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2##f(instance->component); \ + if (instance->logFunctionCall) { \ + instance->logFunctionCall(instance, status, "fmi2" #f "()"); \ + } \ + return status; \ + } while (0) + +#define CALL_ARGS(f, m, ...) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2##f(instance->component, __VA_ARGS__); \ + if (instance->logFunctionCall) { \ + instance->logFunctionCall(instance, status, "fmi2" #f "(" m ")", __VA_ARGS__); \ + } \ + return status; \ + } while (0) + +#define CALL_ARRAY(s, t) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2##s##t(instance->component, vr, nvr, value); \ + if (instance->logFunctionCall) { \ + FMIValueReferencesToString(instance, vr, nvr); \ + FMIValuesToString(instance, nvr, NULL, value, FMI##t##Type); \ + instance->logFunctionCall(instance, status, "fmi2" #s #t "(vr=%s, nvr=%zu, value=%s)", instance->buf1, nvr, instance->buf2); \ + } \ + return status; \ + } while (0) + +/*************************************************** +Common Functions +****************************************************/ + +/* Inquire version numbers of header files and setting logging status */ +const char *FMI2GetTypesPlatform(FMIInstance *instance) +{ + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, FMIOK, "fmi2GetTypesPlatform()"); + } + return instance->fmi2Functions->fmi2GetTypesPlatform(); +} + +const char *FMI2GetVersion(FMIInstance *instance) +{ + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, FMIOK, "fmi2GetVersion()"); + } + return instance->fmi2Functions->fmi2GetVersion(); +} + +FMIStatus FMI2SetDebugLogging(FMIInstance *instance, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2SetDebugLogging(instance->component, loggingOn, nCategories, categories); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nCategories, NULL, categories, FMIStringType); + instance->logFunctionCall(instance, status, "fmi2SetDebugLogging(loggingOn=%d, nCategories=%zu, categories=%s)", + loggingOn, nCategories, instance->buf2); + } + return status; +} + +/* Creation and destruction of FMU instances and setting debug status */ +FMIStatus FMI2Instantiate(FMIInstance *instance, const char *fmuResourceLocation, fmi2Type fmuType, fmi2String fmuGUID, + fmi2Boolean visible, fmi2Boolean loggingOn) +{ + + instance->fmiVersion = FMIVersion2; + + instance->fmi2Functions = calloc(1, sizeof(FMI2Functions)); + + if (!instance->fmi2Functions) { + return FMIError; + } + + instance->fmi2Functions->eventInfo.newDiscreteStatesNeeded = fmi2False; + instance->fmi2Functions->eventInfo.terminateSimulation = fmi2False; + instance->fmi2Functions->eventInfo.nominalsOfContinuousStatesChanged = fmi2False; + instance->fmi2Functions->eventInfo.valuesOfContinuousStatesChanged = fmi2False; + instance->fmi2Functions->eventInfo.nextEventTimeDefined = fmi2False; + instance->fmi2Functions->eventInfo.nextEventTime = 0.0; + + instance->state = FMI2StartAndEndState; + +#if !defined(FMI_VERSION) || FMI_VERSION == 2 + + /*************************************************** + Common Functions + ****************************************************/ + + /* required functions */ + LOAD_SYMBOL(GetTypesPlatform); + LOAD_SYMBOL(GetVersion); + LOAD_SYMBOL(SetDebugLogging); + LOAD_SYMBOL(Instantiate); + LOAD_SYMBOL(FreeInstance); + LOAD_SYMBOL(SetupExperiment); + LOAD_SYMBOL(EnterInitializationMode); + LOAD_SYMBOL(ExitInitializationMode); + LOAD_SYMBOL(Terminate); + LOAD_SYMBOL(Reset); + LOAD_SYMBOL(GetReal); + LOAD_SYMBOL(GetInteger); + LOAD_SYMBOL(GetBoolean); + LOAD_SYMBOL(GetString); + LOAD_SYMBOL(SetReal); + LOAD_SYMBOL(SetInteger); + LOAD_SYMBOL(SetBoolean); + LOAD_SYMBOL(SetString); + + /* optional functions */ + LOAD_SYMBOL(GetFMUstate); + LOAD_SYMBOL(SetFMUstate); + LOAD_SYMBOL(FreeFMUstate); + LOAD_SYMBOL(SerializedFMUstateSize); + LOAD_SYMBOL(SerializeFMUstate); + LOAD_SYMBOL(DeSerializeFMUstate); + LOAD_SYMBOL(GetDirectionalDerivative); + + if (fmuType == fmi2ModelExchange) { +#ifndef CO_SIMULATION + /*************************************************** + Model Exchange + ****************************************************/ + + LOAD_SYMBOL(EnterEventMode); + LOAD_SYMBOL(NewDiscreteStates); + LOAD_SYMBOL(EnterContinuousTimeMode); + LOAD_SYMBOL(CompletedIntegratorStep); + LOAD_SYMBOL(SetTime); + LOAD_SYMBOL(SetContinuousStates); + LOAD_SYMBOL(GetDerivatives); + LOAD_SYMBOL(GetEventIndicators); + LOAD_SYMBOL(GetContinuousStates); + LOAD_SYMBOL(GetNominalsOfContinuousStates); +#endif + } else { +#ifndef MODEL_EXCHANGE + /*************************************************** + Co-Simulation + ****************************************************/ + + LOAD_SYMBOL(SetRealInputDerivatives); + LOAD_SYMBOL(GetRealOutputDerivatives); + LOAD_SYMBOL(DoStep); + LOAD_SYMBOL(CancelStep); + LOAD_SYMBOL(GetStatus); + LOAD_SYMBOL(GetRealStatus); + LOAD_SYMBOL(GetIntegerStatus); + LOAD_SYMBOL(GetBooleanStatus); + LOAD_SYMBOL(GetStringStatus); +#endif + } + +#endif + + instance->fmi2Functions->callbacks.logger = cb_logMessage2; + instance->fmi2Functions->callbacks.allocateMemory = calloc; + instance->fmi2Functions->callbacks.freeMemory = free; + instance->fmi2Functions->callbacks.stepFinished = NULL; + instance->fmi2Functions->callbacks.componentEnvironment = instance; + + instance->component = instance->fmi2Functions->fmi2Instantiate(instance->name, fmuType, fmuGUID, fmuResourceLocation, &instance->fmi2Functions->callbacks, visible, loggingOn); + + if (instance->logFunctionCall) { + fmi2CallbackFunctions *f = &instance->fmi2Functions->callbacks; + instance->logFunctionCall(instance, instance->component ? FMIOK : FMIError, + "fmi2Instantiate(instanceName=\"%s\", fmuType=%d, fmuGUID=\"%s\", fmuResourceLocation=\"%s\", functions={logger=0x%p, allocateMemory=0x%p, freeMemory=0x%p, stepFinished=0x%p, componentEnvironment=0x%p}, visible=%d, loggingOn=%d)", + instance->name, fmuType, fmuGUID, fmuResourceLocation, f->logger, f->allocateMemory, f->freeMemory, f->stepFinished, f->componentEnvironment, visible, loggingOn); + } + + if (!instance->component) { + return FMIError; + } + + instance->interfaceType = (FMIInterfaceType) fmuType; + instance->state = FMI2InstantiatedState; + + return FMIOK; +} + +void FMI2FreeInstance(FMIInstance *instance) +{ + + if (!instance) { + return; + } + + instance->fmi2Functions->fmi2FreeInstance(instance->component); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, FMIOK, "fmi2FreeInstance()"); + } +} + +/* Enter and exit initialization mode, terminate and reset */ +FMIStatus FMI2SetupExperiment(FMIInstance *instance, + fmi2Boolean toleranceDefined, + fmi2Real tolerance, + fmi2Real startTime, + fmi2Boolean stopTimeDefined, + fmi2Real stopTime) +{ + + instance->time = startTime; + + CALL_ARGS(SetupExperiment, "toleranceDefined=%d, tolerance=%.16g, startTime=%.16g, stopTimeDefined=%d, stopTime=%.16g", toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); +} + +FMIStatus FMI2EnterInitializationMode(FMIInstance *instance) +{ + instance->state = FMI2InitializationModeState; + CALL(EnterInitializationMode); +} + +FMIStatus FMI2ExitInitializationMode(FMIInstance *instance) +{ + instance->state = instance->interfaceType == FMIModelExchange ? FMI2EventModeState : FMI2StepCompleteState; + CALL(ExitInitializationMode); +} + +FMIStatus FMI2Terminate(FMIInstance *instance) +{ + instance->state = FMI2TerminatedState; + CALL(Terminate); +} + +FMIStatus FMI2Reset(FMIInstance *instance) +{ + instance->state = FMI2InstantiatedState; + CALL(Reset); +} + +/* Getting and setting variable values */ +FMIStatus FMI2GetReal(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) +{ + CALL_ARRAY(Get, Real); +} + +FMIStatus FMI2GetInteger(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) +{ + CALL_ARRAY(Get, Integer); +} + +FMIStatus FMI2GetBoolean(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]) +{ + CALL_ARRAY(Get, Boolean); +} + +FMIStatus FMI2GetString(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) +{ + CALL_ARRAY(Get, String); +} + +FMIStatus FMI2SetReal(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) +{ + CALL_ARRAY(Set, Real); +} + +FMIStatus FMI2SetInteger(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) +{ + CALL_ARRAY(Set, Integer); +} + +FMIStatus FMI2SetBoolean(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) +{ + CALL_ARRAY(Set, Boolean); +} + +FMIStatus FMI2SetString(FMIInstance *instance, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) +{ + CALL_ARRAY(Set, String); +} + +/* Getting and setting the internal FMU state */ +FMIStatus FMI2GetFMUstate(FMIInstance *instance, fmi2FMUstate *FMUstate) +{ + CALL_ARGS(GetFMUstate, "FMUstate=0x%p", FMUstate); +} + +FMIStatus FMI2SetFMUstate(FMIInstance *instance, fmi2FMUstate FMUstate) +{ + CALL_ARGS(SetFMUstate, "FMUstate=0x%p", FMUstate); +} + +FMIStatus FMI2FreeFMUstate(FMIInstance *instance, fmi2FMUstate *FMUstate) +{ + CALL_ARGS(FreeFMUstate, "FMUstate=0x%p", FMUstate); +} + +FMIStatus FMI2SerializedFMUstateSize(FMIInstance *instance, fmi2FMUstate FMUstate, size_t *size) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2SerializedFMUstateSize(instance->component, FMUstate, size); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2SerializedFMUstateSize(FMUstate=0x%p, size=%zu)", FMUstate, *size); + } + return status; +} + +FMIStatus FMI2SerializeFMUstate(FMIInstance *instance, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size) +{ + CALL_ARGS(SerializeFMUstate, "FMUstate=0x%p, serializedState=0x%p, size=%zu", FMUstate, serializedState, size); +} + +FMIStatus FMI2DeSerializeFMUstate(FMIInstance *instance, const fmi2Byte serializedState[], size_t size, fmi2FMUstate *FMUstate) +{ + CALL_ARGS(DeSerializeFMUstate, "serializedState=0x%p, size=%zu, FMUstate=0x%p", serializedState, size, FMUstate); +} + +/* Getting partial derivatives */ +FMIStatus FMI2GetDirectionalDerivative(FMIInstance *instance, + const fmi2ValueReference vUnknown_ref[], size_t nUnknown, + const fmi2ValueReference vKnown_ref[], size_t nKnown, + const fmi2Real dvKnown[], + fmi2Real dvUnknown[]) +{ + CALL_ARGS(GetDirectionalDerivative, "vUnknown_ref=0x%p, nUnknown=%zu, vKnown_ref=0x%p, nKnown=%zu, dvKnown=0x%p, dvUnknown=0x%p", + vUnknown_ref, nUnknown, vKnown_ref, nKnown, dvKnown, dvUnknown); +} + +/*************************************************** +Model Exchange +****************************************************/ + +/* Enter and exit the different modes */ +FMIStatus FMI2EnterEventMode(FMIInstance *instance) +{ + instance->state = FMI2EventModeState; + CALL(EnterEventMode); +} + +FMIStatus FMI2NewDiscreteStates(FMIInstance *instance, fmi2EventInfo *eventInfo) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2NewDiscreteStates(instance->component, eventInfo); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, + "fmi2NewDiscreteStates(eventInfo={newDiscreteStatesNeeded=%d, terminateSimulation=%d, nominalsOfContinuousStatesChanged=%d, valuesOfContinuousStatesChanged=%d, nextEventTimeDefined=%d, nextEventTime=%.16g})", + eventInfo->newDiscreteStatesNeeded, eventInfo->terminateSimulation, eventInfo->nominalsOfContinuousStatesChanged, eventInfo->valuesOfContinuousStatesChanged, eventInfo->nextEventTimeDefined, eventInfo->nextEventTime); + } + return status; +} + +FMIStatus FMI2EnterContinuousTimeMode(FMIInstance *instance) +{ + instance->state = FMI2ContinuousTimeModeState; + CALL(EnterContinuousTimeMode); +} + +FMIStatus FMI2CompletedIntegratorStep(FMIInstance *instance, + fmi2Boolean noSetFMUStatePriorToCurrentPoint, + fmi2Boolean *enterEventMode, + fmi2Boolean *terminateSimulation) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2CompletedIntegratorStep(instance->component, noSetFMUStatePriorToCurrentPoint, enterEventMode, terminateSimulation); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2CompletedIntegratorStep(noSetFMUStatePriorToCurrentPoint=%d, enterEventMode=%d, terminateSimulation=%d)", noSetFMUStatePriorToCurrentPoint, *enterEventMode, *terminateSimulation); + } + return status; +} + +/* Providing independent variables and re-initialization of caching */ +FMIStatus FMI2SetTime(FMIInstance *instance, fmi2Real time) +{ + instance->time = time; + CALL_ARGS(SetTime, "time=%.16g", time); +} + +FMIStatus FMI2SetContinuousStates(FMIInstance *instance, const fmi2Real x[], size_t nx) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2SetContinuousStates(instance->component, x, nx); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nx, NULL, x, FMIRealType); + instance->logFunctionCall(instance, status, "fmi2SetContinuousStates(x=%s, nx=%zu)", instance->buf2, nx); + } + return status; +} + +/* Evaluation of the model equations */ +FMIStatus FMI2GetDerivatives(FMIInstance *instance, fmi2Real derivatives[], size_t nx) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetDerivatives(instance->component, derivatives, nx); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nx, NULL, derivatives, FMIRealType); + instance->logFunctionCall(instance, status, "fmi2GetDerivatives(derivatives=%s, nx=%zu)", instance->buf2, nx); + } + return status; +} + +FMIStatus FMI2GetEventIndicators(FMIInstance *instance, fmi2Real eventIndicators[], size_t ni) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetEventIndicators(instance->component, eventIndicators, ni); + if (instance->logFunctionCall) { + FMIValuesToString(instance, ni, NULL, eventIndicators, FMIRealType); + instance->logFunctionCall(instance, status, "fmi2GetEventIndicators(eventIndicators=%s, ni=%zu)", instance->buf2, ni); + } + return status; +} + +FMIStatus FMI2GetContinuousStates(FMIInstance *instance, fmi2Real x[], size_t nx) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetContinuousStates(instance->component, x, nx); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nx, NULL, x, FMIRealType); + instance->logFunctionCall(instance, status, "fmi2GetContinuousStates(x=%s, nx=%zu)", instance->buf2, nx); + } + return status; +} + +FMIStatus FMI2GetNominalsOfContinuousStates(FMIInstance *instance, fmi2Real x_nominal[], size_t nx) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetNominalsOfContinuousStates(instance->component, x_nominal, nx); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nx, NULL, x_nominal, FMIRealType); + instance->logFunctionCall(instance, status, "fmi2GetNominalsOfContinuousStates(x_nominal=%s, nx=%zu)", instance->buf2, nx); + } + return status; +} + +/*************************************************** +Co-Simulation +****************************************************/ + +/* Simulating the slave */ +FMIStatus FMI2SetRealInputDerivatives(FMIInstance *instance, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + const fmi2Real value[]) +{ + CALL_ARGS(SetRealInputDerivatives, "vr=0x%p, nvr=%zu, order=0x%p, value=0x%p", vr, nvr, order, value); +} + +FMIStatus FMI2GetRealOutputDerivatives(FMIInstance *instance, + const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], + fmi2Real value[]) +{ + CALL_ARGS(GetRealOutputDerivatives, "vr=0x%p, nvr=%zu, order=0x%p, value=0x%p", vr, nvr, order, value); +} + +FMIStatus FMI2DoStep(FMIInstance *instance, + fmi2Real currentCommunicationPoint, + fmi2Real communicationStepSize, + fmi2Boolean noSetFMUStatePriorToCurrentPoint) +{ + + instance->time = currentCommunicationPoint + communicationStepSize; + + CALL_ARGS(DoStep, "currentCommunicationPoint=%.16g, communicationStepSize=%.16g, noSetFMUStatePriorToCurrentPoint=%d", + currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint); +} + +FMIStatus FMI2CancelStep(FMIInstance *instance) +{ + CALL(CancelStep); +} + +/* Inquire slave status */ +FMIStatus FMI2GetStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Status *value) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetStatus(instance->component, s, value); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2GetStatus(s=%d, value=%d)", s, *value); + } + return status; +} + +FMIStatus FMI2GetRealStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Real *value) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetRealStatus(instance->component, s, value); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2GetRealStatus(s=%d, value=%.16g)", s, *value); + } + return status; +} + +FMIStatus FMI2GetIntegerStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Integer *value) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetIntegerStatus(instance->component, s, value); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2GetIntegerStatus(s=%d, value=%d)", s, *value); + } + return status; +} + +FMIStatus FMI2GetBooleanStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2Boolean *value) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetBooleanStatus(instance->component, s, value); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2GetBooleanStatus(s=%d, value=%d)", s, *value); + } + return status; +} + +FMIStatus FMI2GetStringStatus(FMIInstance *instance, const fmi2StatusKind s, fmi2String *value) +{ + FMIStatus status = (FMIStatus) instance->fmi2Functions->fmi2GetStringStatus(instance->component, s, value); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi2GetStringStatus(s=%d, value=%s)", s, *value); + } + return status; +} + +#undef LOAD_SYMBOL +#undef CALL +#undef CALL_ARGS +#undef CALL_ARRAY diff --git a/oscillator/solver-fmi/fmu/src/FMI3.c b/oscillator/solver-fmi/fmu/src/FMI3.c new file mode 100644 index 000000000..3b13c02bd --- /dev/null +++ b/oscillator/solver-fmi/fmu/src/FMI3.c @@ -0,0 +1,1186 @@ +#ifdef _WIN32 +#include +#include "Shlwapi.h" +#pragma comment(lib, "shlwapi.lib") +#else +#include +#include +#endif + +#include +#include +#include + +#include "FMI3.h" + +static void cb_logMessage3(fmi3InstanceEnvironment instanceEnvironment, + fmi3Status status, + fmi3String category, + fmi3String message) +{ + + if (!instanceEnvironment) + return; + + FMIInstance *instance = instanceEnvironment; + + if (!instance->logMessage) + return; + + instance->logMessage(instance, (FMIStatus) status, category, message); +} + +#if defined(FMI2_FUNCTION_PREFIX) +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi3Functions->fmi3##f = fmi3##f; \ + } while (0) +#elif defined(_WIN32) +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi3Functions->fmi3##f = (fmi3##f##TYPE *) GetProcAddress(instance->libraryHandle, "fmi3" #f); \ + if (!instance->fmi3Functions->fmi3##f) { \ + instance->logMessage(instance, FMIFatal, "fatal", "Symbol fmi3" #f " is missing in shared library."); \ + return fmi3Fatal; \ + } \ + } while (0) +#else +#define LOAD_SYMBOL(f) \ + do { \ + instance->fmi3Functions->fmi3##f = (fmi3##f##TYPE *) dlsym(instance->libraryHandle, "fmi3" #f); \ + if (!instance->fmi3Functions->fmi3##f) { \ + instance->logMessage(instance, FMIFatal, "fatal", "Symbol fmi3" #f " is missing in shared library."); \ + return FMIFatal; \ + } \ + } while (0) +#endif + +#define CALL(f) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3##f(instance->component); \ + if (instance->logFunctionCall) { \ + instance->logFunctionCall(instance, status, "fmi3" #f "()"); \ + } \ + instance->status = status > instance->status ? status : instance->status; \ + return status; \ + } while (0) + +#define CALL_ARGS(f, m, ...) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3##f(instance->component, __VA_ARGS__); \ + if (instance->logFunctionCall) { \ + instance->logFunctionCall(instance, status, "fmi3" #f "(" m ")", __VA_ARGS__); \ + } \ + instance->status = status > instance->status ? status : instance->status; \ + return status; \ + } while (0) + +#define CALL_ARRAY(s, t) \ + do { \ + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3##s##t(instance->component, valueReferences, nValueReferences, values, nValues); \ + if (instance->logFunctionCall) { \ + FMIValueReferencesToString(instance, valueReferences, nValueReferences); \ + FMIValuesToString(instance, nValues, NULL, values, FMI##t##Type); \ + instance->logFunctionCall(instance, status, "fmi3" #s #t "(valueReferences=%s, nValueReferences=%zu, values=%s, nValues=%zu)", instance->buf1, nValueReferences, instance->buf2, nValues); \ + } \ + instance->status = status > instance->status ? status : instance->status; \ + return status; \ + } while (0) + +/*************************************************** +Types for Common Functions +****************************************************/ + +/* Inquire version numbers and setting logging status */ +const char *FMI3GetVersion(FMIInstance *instance) +{ + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, FMIOK, "fmi3GetVersion()"); + } + return instance->fmi3Functions->fmi3GetVersion(); +} + +FMIStatus FMI3SetDebugLogging(FMIInstance *instance, + fmi3Boolean loggingOn, + size_t nCategories, + const fmi3String categories[]) +{ + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3SetDebugLogging(instance->component, loggingOn, nCategories, categories); + if (instance->logFunctionCall) { + FMIValuesToString(instance, nCategories, NULL, categories, FMIStringType); + instance->logFunctionCall(instance, status, "fmi3SetDebugLogging(loggingOn=%d, nCategories=%zu, categories=%s)", + loggingOn, nCategories, instance->buf2); + } + return status; +} + +static FMIStatus loadSymbols3(FMIInstance *instance) +{ + +#if !defined(FMI_VERSION) || FMI_VERSION == 3 + + instance->fmi3Functions = calloc(1, sizeof(FMI3Functions)); + + if (!instance->fmi3Functions) { + return FMIError; + } + + instance->fmiVersion = FMIVersion3; + + /*************************************************** + Common Functions + ****************************************************/ + + /* Inquire version numbers and set debug logging */ + LOAD_SYMBOL(GetVersion); + LOAD_SYMBOL(SetDebugLogging); + + /* Creation and destruction of FMU instances */ + LOAD_SYMBOL(InstantiateModelExchange); + LOAD_SYMBOL(InstantiateCoSimulation); + LOAD_SYMBOL(InstantiateScheduledExecution); + LOAD_SYMBOL(FreeInstance); + + /* Enter and exit initialization mode, terminate and reset */ + LOAD_SYMBOL(EnterInitializationMode); + LOAD_SYMBOL(ExitInitializationMode); + LOAD_SYMBOL(EnterEventMode); + LOAD_SYMBOL(Terminate); + LOAD_SYMBOL(Reset); + + /* Getting and setting variable values */ + LOAD_SYMBOL(GetFloat32); + LOAD_SYMBOL(GetFloat64); + LOAD_SYMBOL(GetInt8); + LOAD_SYMBOL(GetUInt8); + LOAD_SYMBOL(GetInt16); + LOAD_SYMBOL(GetUInt16); + LOAD_SYMBOL(GetInt32); + LOAD_SYMBOL(GetUInt32); + LOAD_SYMBOL(GetInt64); + LOAD_SYMBOL(GetUInt64); + LOAD_SYMBOL(GetBoolean); + LOAD_SYMBOL(GetString); + LOAD_SYMBOL(GetBinary); + LOAD_SYMBOL(GetClock); + LOAD_SYMBOL(SetFloat32); + LOAD_SYMBOL(SetFloat64); + LOAD_SYMBOL(SetInt8); + LOAD_SYMBOL(SetUInt8); + LOAD_SYMBOL(SetInt16); + LOAD_SYMBOL(SetUInt16); + LOAD_SYMBOL(SetInt32); + LOAD_SYMBOL(SetUInt32); + LOAD_SYMBOL(SetInt64); + LOAD_SYMBOL(SetUInt64); + LOAD_SYMBOL(SetBoolean); + LOAD_SYMBOL(SetString); + LOAD_SYMBOL(SetBinary); + LOAD_SYMBOL(SetClock); + + /* Getting Variable Dependency Information */ + LOAD_SYMBOL(GetNumberOfVariableDependencies); + LOAD_SYMBOL(GetVariableDependencies); + + /* Getting and setting the internal FMU state */ + LOAD_SYMBOL(GetFMUState); + LOAD_SYMBOL(SetFMUState); + LOAD_SYMBOL(FreeFMUState); + LOAD_SYMBOL(SerializedFMUStateSize); + LOAD_SYMBOL(SerializeFMUState); + LOAD_SYMBOL(DeserializeFMUState); + + /* Getting partial derivatives */ + LOAD_SYMBOL(GetDirectionalDerivative); + LOAD_SYMBOL(GetAdjointDerivative); + + /* Entering and exiting the Configuration or Reconfiguration Mode */ + LOAD_SYMBOL(EnterConfigurationMode); + LOAD_SYMBOL(ExitConfigurationMode); + + /* Clock related functions */ + LOAD_SYMBOL(GetIntervalDecimal); + LOAD_SYMBOL(GetIntervalFraction); + LOAD_SYMBOL(GetShiftDecimal); + LOAD_SYMBOL(GetShiftFraction); + LOAD_SYMBOL(SetIntervalDecimal); + LOAD_SYMBOL(SetIntervalFraction); + LOAD_SYMBOL(EvaluateDiscreteStates); + LOAD_SYMBOL(UpdateDiscreteStates); + + /*************************************************** + Functions for Model Exchange + ****************************************************/ + + LOAD_SYMBOL(EnterContinuousTimeMode); + LOAD_SYMBOL(CompletedIntegratorStep); + + /* Providing independent variables and re-initialization of caching */ + LOAD_SYMBOL(SetTime); + LOAD_SYMBOL(SetContinuousStates); + + /* Evaluation of the model equations */ + LOAD_SYMBOL(GetContinuousStateDerivatives); + LOAD_SYMBOL(GetEventIndicators); + LOAD_SYMBOL(GetContinuousStates); + LOAD_SYMBOL(GetNominalsOfContinuousStates); + LOAD_SYMBOL(GetNumberOfEventIndicators); + LOAD_SYMBOL(GetNumberOfContinuousStates); + + /*************************************************** + Functions for Co-Simulation + ****************************************************/ + + /* Simulating the FMU */ + LOAD_SYMBOL(EnterStepMode); + LOAD_SYMBOL(GetOutputDerivatives); + LOAD_SYMBOL(DoStep); + LOAD_SYMBOL(ActivateModelPartition); + + instance->state = FMI2StartAndEndState; + + return FMIOK; + +#else + + return FMIError; + +#endif +} + +/* Creation and destruction of FMU instances and setting debug status */ +FMIStatus FMI3InstantiateModelExchange( + FMIInstance *instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn) +{ + + FMIStatus status = loadSymbols3(instance); + + fmi3LogMessageCallback logMessage = instance->logMessage ? cb_logMessage3 : NULL; + + instance->component = instance->fmi3Functions->fmi3InstantiateModelExchange(instance->name, instantiationToken, resourcePath, visible, loggingOn, instance, logMessage); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, instance->component ? FMIOK : FMIError, + "fmi3InstantiateModelExchange(" + "instanceName=\"%s\", " + "instantiationToken=\"%s\", " + "resourcePath=\"%s\", " + "visible=%d, " + "loggingOn=%d, " + "instanceEnvironment=0x%p, " + "logMessage=0x%p)", + instance->name, + instantiationToken, + resourcePath, + visible, + loggingOn, + instance, + logMessage); + } + + if (!instance->component) { + return FMIError; + } + + instance->interfaceType = FMIModelExchange; + instance->state = FMI2InstantiatedState; + + return status; +} + +FMIStatus FMI3InstantiateCoSimulation( + FMIInstance *instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3Boolean eventModeUsed, + fmi3Boolean earlyReturnAllowed, + const fmi3ValueReference requiredIntermediateVariables[], + size_t nRequiredIntermediateVariables, + fmi3IntermediateUpdateCallback intermediateUpdate) +{ + + if (loadSymbols3(instance) != FMIOK) { + return FMIFatal; + } + + fmi3LogMessageCallback logMessage = instance->logMessage ? cb_logMessage3 : NULL; + + instance->component = instance->fmi3Functions->fmi3InstantiateCoSimulation( + instance->name, + instantiationToken, + resourcePath, + visible, + loggingOn, + eventModeUsed, + earlyReturnAllowed, + requiredIntermediateVariables, + nRequiredIntermediateVariables, + instance, + logMessage, + intermediateUpdate); + + instance->fmi3Functions->eventModeUsed = eventModeUsed; + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, instance->component ? FMIOK : FMIError, + "fmi3InstantiateCoSimulation(" + "instanceName=\"%s\", " + "instantiationToken=\"%s\", " + "resourcePath=\"%s\", " + "visible=%d, " + "loggingOn=%d, " + "eventModeUsed=%d, " + "earlyReturnAllowed=%d, " + "requiredIntermediateVariables=0x%p, " + "nRequiredIntermediateVariables=%zu, " + "instanceEnvironment=0x%p, " + "logMessage=0x%p, " + "intermediateUpdate=0x%p)", + instance->name, + instantiationToken, + resourcePath, + visible, + loggingOn, + eventModeUsed, + earlyReturnAllowed, + requiredIntermediateVariables, + nRequiredIntermediateVariables, + instance, + logMessage, + intermediateUpdate); + } + + if (!instance->component) { + return FMIError; + } + + instance->interfaceType = FMICoSimulation; + instance->state = FMI2InstantiatedState; + + return FMIOK; +} + +FMIStatus FMI3InstantiateScheduledExecution( + FMIInstance *instance, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3ClockUpdateCallback clockUpdate, + fmi3LockPreemptionCallback lockPreemption, + fmi3UnlockPreemptionCallback unlockPreemption) +{ + + if (loadSymbols3(instance) != FMIOK) { + return FMIError; + } + + fmi3LogMessageCallback _logMessage = instance->logMessage ? cb_logMessage3 : NULL; + + instance->component = instance->fmi3Functions->fmi3InstantiateScheduledExecution( + instance->name, + instantiationToken, + resourcePath, + visible, + loggingOn, + instance, + _logMessage, + clockUpdate, + lockPreemption, + unlockPreemption); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, instance->component ? FMIOK : FMIError, + "fmi3InstantiateScheduledExecution(" + "instanceName=\"%s\", " + "instantiationToken=\"%s\", " + "resourcePath=\"%s\", " + "visible=%d, " + "loggingOn=%d, " + "instanceEnvironment=0x%p, " + "logMessage=0x%p, " + "clockUpdate=0x%p, " + "lockPreemption=0x%p, " + "unlockPreemption=0x%p)", + instance->name, + instantiationToken, + resourcePath, + visible, + loggingOn, + instance, + _logMessage, + clockUpdate, + lockPreemption, + unlockPreemption); + } + + if (!instance->component) { + return FMIError; + } + + instance->interfaceType = FMIScheduledExecution; + instance->state = FMI2InstantiatedState; + + return FMIOK; +} + +FMIStatus FMI3FreeInstance(FMIInstance *instance) +{ + + if (!instance) { + return FMIError; + } + + instance->fmi3Functions->fmi3FreeInstance(instance->component); + + instance->component = NULL; + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, FMIOK, "fmi3FreeInstance()"); + } + + return FMIOK; +} + +/* Enter and exit initialization mode, enter event mode, terminate and reset */ +FMIStatus FMI3EnterInitializationMode(FMIInstance *instance, + fmi3Boolean toleranceDefined, + fmi3Float64 tolerance, + fmi3Float64 startTime, + fmi3Boolean stopTimeDefined, + fmi3Float64 stopTime) +{ + + instance->state = FMI2InitializationModeState; + + CALL_ARGS(EnterInitializationMode, + "fmi3EnterInitializationMode(toleranceDefined=%d, tolerance=%.16g, startTime=%.16g, stopTimeDefined=%d, stopTime=%.16g)", + toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); +} + +FMIStatus FMI3ExitInitializationMode(FMIInstance *instance) +{ + + if (instance->interfaceType == FMIModelExchange || (instance->fmiVersion == FMIVersion3 && instance->interfaceType == FMICoSimulation && instance->fmi3Functions->eventModeUsed)) { + instance->state = FMI2EventModeState; + } else { + instance->state = FMI2StepCompleteState; + } + + CALL(ExitInitializationMode); +} + +FMIStatus FMI3EnterEventMode(FMIInstance *instance) +{ + instance->state = FMI2EventModeState; + CALL(EnterEventMode); +} + +FMIStatus FMI3Terminate(FMIInstance *instance) +{ + instance->state = FMI2TerminatedState; + CALL(Terminate); +} + +FMIStatus FMI3Reset(FMIInstance *instance) +{ + instance->state = FMI2InstantiatedState; + CALL(Reset); +} + +/* Getting and setting variable values */ +FMIStatus FMI3GetFloat32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float32 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Float32); +} + +FMIStatus FMI3GetFloat64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Float64); +} + +FMIStatus FMI3GetInt8(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int8 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Int8); +} + +FMIStatus FMI3GetUInt8(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt8 values[], + size_t nValues) +{ + CALL_ARRAY(Get, UInt8); +} + +FMIStatus FMI3GetInt16(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int16 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Int16); +} + +FMIStatus FMI3GetUInt16(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt16 values[], + size_t nValues) +{ + CALL_ARRAY(Get, UInt16); +} + +FMIStatus FMI3GetInt32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int32 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Int32); +} + +FMIStatus FMI3GetUInt32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt32 values[], + size_t nValues) +{ + CALL_ARRAY(Get, UInt32); +} + +FMIStatus FMI3GetInt64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int64 values[], + size_t nValues) +{ + CALL_ARRAY(Get, Int64); +} + +FMIStatus FMI3GetUInt64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 values[], + size_t nValues) +{ + CALL_ARRAY(Get, UInt64); +} + +FMIStatus FMI3GetBoolean(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Boolean values[], + size_t nValues) +{ + CALL_ARRAY(Get, Boolean); +} + +FMIStatus FMI3GetString(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3String values[], + size_t nValues) +{ + CALL_ARRAY(Get, String); +} + +FMIStatus FMI3GetBinary(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + size_t sizes[], + fmi3Binary values[], + size_t nValues) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3GetBinary(instance->component, valueReferences, nValueReferences, sizes, values, nValues); + + if (instance->logFunctionCall) { + FMIValueReferencesToString(instance, valueReferences, nValueReferences); + FMIValuesToString(instance, nValues, sizes, values, FMIBinaryType); + instance->logFunctionCall(instance, status, "fmi3GetBinary(valueReferences=%s, nValueReferences=%zu, sizes=%p, values=%s, nValues=%zu)", instance->buf1, nValueReferences, sizes, instance->buf2, nValues); + } + + return status; +} + +FMIStatus FMI3GetClock(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Clock values[]) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3GetClock(instance->component, valueReferences, nValueReferences, values); + + if (instance->logFunctionCall) { + FMIValueReferencesToString(instance, valueReferences, nValueReferences); + FMIValuesToString(instance, nValueReferences, NULL, values, FMIClockType); + instance->logFunctionCall(instance, status, "fmi3GetClock(valueReferences=%s, nValueReferences=%zu, values=%s)", instance->buf1, nValueReferences, instance->buf2); + } + + return status; +} + +FMIStatus FMI3SetFloat32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float32 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Float32); +} + +FMIStatus FMI3SetFloat64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Float64); +} + +FMIStatus FMI3SetInt8(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int8 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Int8); +} + +FMIStatus FMI3SetUInt8(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt8 values[], + size_t nValues) +{ + CALL_ARRAY(Set, UInt8); +} + +FMIStatus FMI3SetInt16(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int16 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Int16); +} + +FMIStatus FMI3SetUInt16(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt16 values[], + size_t nValues) +{ + CALL_ARRAY(Set, UInt16); +} + +FMIStatus FMI3SetInt32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Int32); +} + +FMIStatus FMI3SetUInt32(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt32 values[], + size_t nValues) +{ + CALL_ARRAY(Set, UInt32); +} + +FMIStatus FMI3SetInt64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int64 values[], + size_t nValues) +{ + CALL_ARRAY(Set, Int64); +} + +FMIStatus FMI3SetUInt64(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 values[], + size_t nValues) +{ + CALL_ARRAY(Set, UInt64); +} + +FMIStatus FMI3SetBoolean(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Boolean values[], + size_t nValues) +{ + CALL_ARRAY(Set, Boolean); +} + +FMIStatus FMI3SetString(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3String values[], + size_t nValues) +{ + CALL_ARRAY(Set, String); +} + +FMIStatus FMI3SetBinary(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const size_t sizes[], + const fmi3Binary values[], + size_t nValues) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3SetBinary(instance->component, valueReferences, nValueReferences, sizes, values, nValues); + + if (instance->logFunctionCall) { + FMIValueReferencesToString(instance, valueReferences, nValueReferences); + FMIValuesToString(instance, nValues, sizes, values, FMIBinaryType); + instance->logFunctionCall(instance, status, "fmi3SetBinary(valueReferences=%s, nValueReferences=%zu, sizes=0x%p, values=%s, nValues=%zu", instance->buf1, nValueReferences, sizes, instance->buf2, nValues); + } + + return status; +} + +FMIStatus FMI3SetClock(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Clock values[]) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3SetClock(instance->component, valueReferences, nValueReferences, values); + + if (instance->logFunctionCall) { + FMIValueReferencesToString(instance, valueReferences, nValueReferences); + FMIValuesToString(instance, nValueReferences, NULL, values, FMIClockType); + instance->logFunctionCall(instance, status, "fmi3SetClock(valueReferences=%s, nValueReferences=%zu, values=%s)", instance->buf1, nValueReferences, instance->buf2); + } + + return status; +} + +/* Getting Variable Dependency Information */ +FMIStatus FMI3GetNumberOfVariableDependencies(FMIInstance *instance, + fmi3ValueReference valueReference, + size_t *nDependencies) +{ + CALL_ARGS(GetNumberOfVariableDependencies, "valueReference=%u, nDependencies=0x%p", valueReference, nDependencies); +} + +FMIStatus FMI3GetVariableDependencies(FMIInstance *instance, + fmi3ValueReference dependent, + size_t elementIndicesOfDependent[], + fmi3ValueReference independents[], + size_t elementIndicesOfIndependents[], + fmi3DependencyKind dependencyKinds[], + size_t nDependencies) +{ + CALL_ARGS(GetVariableDependencies, "dependent=%u, elementIndicesOfDependent=0x%p, independents=0x%p, elementIndicesOfIndependents=0x%p, dependencyKinds=0x%p, nDependencies=%zu", + dependent, elementIndicesOfDependent, independents, elementIndicesOfIndependents, dependencyKinds, nDependencies); +} + +/* Getting and setting the internal FMU state */ +FMIStatus FMI3GetFMUState(FMIInstance *instance, fmi3FMUState *FMUState) +{ + CALL_ARGS(GetFMUState, "FMUState=0x%p", FMUState); +} + +FMIStatus FMI3SetFMUState(FMIInstance *instance, fmi3FMUState FMUState) +{ + CALL_ARGS(SetFMUState, "FMUState=0x%p", FMUState); +} + +FMIStatus FMI3FreeFMUState(FMIInstance *instance, fmi3FMUState *FMUState) +{ + CALL_ARGS(FreeFMUState, "FMUState=0x%p", FMUState); +} + +FMIStatus FMI3SerializedFMUStateSize(FMIInstance *instance, + fmi3FMUState FMUState, + size_t *size) +{ + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3SerializedFMUStateSize(instance->component, FMUState, size); + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, "fmi3SerializedFMUStateSize(FMUState=0x%p, size=%zu)", FMUState, *size); + } + return status; +} + +FMIStatus FMI3SerializeFMUState(FMIInstance *instance, + fmi3FMUState FMUState, + fmi3Byte serializedState[], + size_t size) +{ + CALL_ARGS(SerializeFMUState, "FMUstate=0x%p, serializedState=0x%p, size=%zu", FMUState, serializedState, size); +} + +FMIStatus FMI3DeserializeFMUState(FMIInstance *instance, + const fmi3Byte serializedState[], + size_t size, + fmi3FMUState *FMUState) +{ + CALL_ARGS(DeserializeFMUState, "serializedState=0x%p, size=%zu, FMUState=0x%p", serializedState, size, FMUState); +} + +/* Getting partial derivatives */ +FMIStatus FMI3GetDirectionalDerivative(FMIInstance *instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity) +{ + CALL_ARGS(GetDirectionalDerivative, + "unknowns=0x%p, nUnknowns=%zu, knowns=0x%p, nKnowns=%zu, seed=0x%p, nSeed=%zu, sensitivity=0x%p, nSensitivity=%zu", + unknowns, nUnknowns, knowns, nKnowns, seed, nSeed, sensitivity, nSensitivity); +} + +FMIStatus FMI3GetAdjointDerivative(FMIInstance *instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity) +{ + CALL_ARGS(GetAdjointDerivative, + "unknowns=0x%p, nUnknowns=%zu, knowns=0x%p, nKnowns=%zu, seed=0x%p, nSeed=%zu, sensitivity=0x%p, nSensitivity=%zu", + unknowns, nUnknowns, knowns, nKnowns, seed, nSeed, sensitivity, nSensitivity); +} + +/* Entering and exiting the Configuration or Reconfiguration Mode */ +FMIStatus FMI3EnterConfigurationMode(FMIInstance *instance) +{ + CALL(EnterConfigurationMode); +} + +FMIStatus FMI3ExitConfigurationMode(FMIInstance *instance) +{ + CALL(ExitConfigurationMode); +} + +/* Clock related functions */ + +FMI_STATIC FMIStatus FMI3GetIntervalDecimal(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 intervals[], + fmi3IntervalQualifier qualifiers[]) +{ + CALL_ARGS(GetIntervalDecimal, + "valueReferences=0x%p, nValueReferences=%zu, intervals=0x%p, qualifiers=0x%p", + valueReferences, nValueReferences, intervals, qualifiers); +} + +FMIStatus FMI3GetIntervalFraction(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 intervalCounters[], + fmi3UInt64 resolutions[], + fmi3IntervalQualifier qualifiers[]) +{ + CALL_ARGS(GetIntervalFraction, + "valueReferences=0x%p, nValueReferences=%zu, intervalCounters=0x%p, resolutions=0x%p, qualifiers=%d", + valueReferences, nValueReferences, intervalCounters, resolutions, qualifiers); +} + +FMIStatus FMI3GetShiftDecimal(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 shifts[]) +{ + CALL_ARGS(GetShiftDecimal, + "valueReferences=0x%p, nValueReferences=%zu, shifts=0x%p", + valueReferences, nValueReferences, shifts); +} + +FMIStatus FMI3GetShiftFraction(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 shiftCounters[], + fmi3UInt64 resolutions[]) +{ + CALL_ARGS(GetShiftFraction, + "valueReferences=0x%p, nValueReferences=%zu, shiftCounters=0x%p, resolutions=0x%p", + valueReferences, nValueReferences, shiftCounters, resolutions); +} + +FMIStatus FMI3SetIntervalDecimal(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 intervals[]) +{ + CALL_ARGS(SetIntervalDecimal, + "valueReferences=0x%p, nValueReferences=%zu, intervals=0x%p", + valueReferences, nValueReferences, intervals); +} + +FMIStatus FMI3SetIntervalFraction(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 intervalCounters[], + const fmi3UInt64 resolutions[]) +{ + CALL_ARGS(SetIntervalFraction, + "valueReferences=0x%p, nValueReferences=%zu, intervalCounters=0x%p, resolutions=0x%p", + valueReferences, nValueReferences, intervalCounters, resolutions); +} + +FMIStatus FMI3SetShiftDecimal(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 shifts[]) +{ + CALL_ARGS(SetShiftDecimal, + "valueReferences=0x%p, nValueReferences=%zu, shifts=0x%p", + valueReferences, nValueReferences, shifts); +} + +FMIStatus FMI3SetShiftFraction(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 shiftCounters[], + const fmi3UInt64 resolutions[]) +{ + CALL_ARGS(SetShiftFraction, + "valueReferences=0x%p, nValueReferences=%zu, shiftCounters=0x%p, resolutions=0x%p", + valueReferences, nValueReferences, shiftCounters, resolutions); +} + +FMIStatus FMI3EvaluateDiscreteStates(FMIInstance *instance) +{ + CALL(EvaluateDiscreteStates); +} + +FMIStatus FMI3UpdateDiscreteStates(FMIInstance *instance, + fmi3Boolean *discreteStatesNeedUpdate, + fmi3Boolean *terminateSimulation, + fmi3Boolean *nominalsOfContinuousStatesChanged, + fmi3Boolean *valuesOfContinuousStatesChanged, + fmi3Boolean *nextEventTimeDefined, + fmi3Float64 *nextEventTime) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3UpdateDiscreteStates(instance->component, discreteStatesNeedUpdate, terminateSimulation, nominalsOfContinuousStatesChanged, valuesOfContinuousStatesChanged, nextEventTimeDefined, nextEventTime); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, + "fmi3UpdateDiscreteStates(discreteStatesNeedUpdate=%d, terminateSimulation=%d, nominalsOfContinuousStatesChanged=%d, valuesOfContinuousStatesChanged=%d, nextEventTimeDefined=%d, nextEventTime=%.16g)", + *discreteStatesNeedUpdate, *terminateSimulation, *nominalsOfContinuousStatesChanged, *valuesOfContinuousStatesChanged, *nextEventTimeDefined, *nextEventTime); + } + + return status; +} + +/*************************************************** +Types for Functions for Model Exchange +****************************************************/ + +FMIStatus FMI3EnterContinuousTimeMode(FMIInstance *instance) +{ + instance->state = FMI2ContinuousTimeModeState; + CALL(EnterContinuousTimeMode); +} + +FMIStatus FMI3CompletedIntegratorStep(FMIInstance *instance, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *enterEventMode, + fmi3Boolean *terminateSimulation) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3CompletedIntegratorStep(instance->component, noSetFMUStatePriorToCurrentPoint, enterEventMode, terminateSimulation); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, + "fmi3CompletedIntegratorStep(noSetFMUStatePriorToCurrentPoint=%d, enterEventMode=%d, terminateSimulation=%d)", + noSetFMUStatePriorToCurrentPoint, *enterEventMode, *terminateSimulation); + } + + return status; +} + +/* Providing independent variables and re-initialization of caching */ +FMIStatus FMI3SetTime(FMIInstance *instance, fmi3Float64 time) +{ + instance->time = time; + CALL_ARGS(SetTime, "time=%.16g", time); +} + +FMIStatus FMI3SetContinuousStates(FMIInstance *instance, + const fmi3Float64 continuousStates[], + size_t nContinuousStates) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3SetContinuousStates(instance->component, continuousStates, nContinuousStates); + + if (instance->logFunctionCall) { + FMIValuesToString(instance, nContinuousStates, NULL, continuousStates, FMIFloat64Type); + instance->logFunctionCall(instance, status, + "fmi3SetContinuousStates(continuousStates=%s, nContinuousStates=%zu)", + instance->buf2, nContinuousStates); + } + + return status; +} + +/* Evaluation of the model equations */ +FMIStatus FMI3GetContinuousStateDerivatives(FMIInstance *instance, + fmi3Float64 derivatives[], + size_t nContinuousStates) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3GetContinuousStateDerivatives(instance->component, derivatives, nContinuousStates); + + if (instance->logFunctionCall) { + FMIValuesToString(instance, nContinuousStates, NULL, derivatives, FMIFloat64Type); + instance->logFunctionCall(instance, status, + "fmi3GetDerivatives(derivatives=%s, nContinuousStates=%zu)", + instance->buf2, nContinuousStates); + } + + return status; +} + +FMIStatus FMI3GetEventIndicators(FMIInstance *instance, + fmi3Float64 eventIndicators[], + size_t nEventIndicators) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3GetEventIndicators(instance->component, eventIndicators, nEventIndicators); + + if (instance->logFunctionCall) { + FMIValuesToString(instance, nEventIndicators, NULL, eventIndicators, FMIFloat64Type); + instance->logFunctionCall(instance, status, + "fmi3GetEventIndicators(eventIndicators=%s, nEventIndicators=%zu)", + instance->buf2, nEventIndicators); + } + + return status; +} + +FMIStatus FMI3GetContinuousStates(FMIInstance *instance, + fmi3Float64 continuousStates[], + size_t nContinuousStates) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3GetContinuousStates(instance->component, continuousStates, nContinuousStates); + + if (instance->logFunctionCall) { + FMIValuesToString(instance, nContinuousStates, NULL, continuousStates, FMIFloat64Type); + instance->logFunctionCall(instance, status, + "fmi3GetContinuousStates(continuousStates=%s, nContinuousStates=%zu)", + instance->buf2, nContinuousStates); + } + + return status; +} + +FMIStatus FMI3GetNominalsOfContinuousStates(FMIInstance *instance, + fmi3Float64 nominals[], + size_t nContinuousStates) +{ + CALL_ARGS(GetNominalsOfContinuousStates, "nominals=0x%p, nContinuousStates=%zu", nominals, nContinuousStates); +} + +FMIStatus FMI3GetNumberOfEventIndicators(FMIInstance *instance, + size_t *nEventIndicators) +{ + CALL_ARGS(GetNumberOfEventIndicators, "nEventIndicators=0x%p", nEventIndicators); +} + +FMIStatus FMI3GetNumberOfContinuousStates(FMIInstance *instance, + size_t *nContinuousStates) +{ + CALL_ARGS(GetNumberOfContinuousStates, "nContinuousStates=0x%p", nContinuousStates); +} + +/*************************************************** +Types for Functions for Co-Simulation +****************************************************/ + +/* Simulating the FMU */ + +FMIStatus FMI3EnterStepMode(FMIInstance *instance) +{ + CALL(EnterStepMode); +} + +FMIStatus FMI3GetOutputDerivatives(FMIInstance *instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 orders[], + fmi3Float64 values[], + size_t nValues) +{ + CALL_ARGS(GetOutputDerivatives, + "valueReferences=0x%p, nValueReferences=%zu, orders=0x%p, values=0x%p, nValues=%zu", + valueReferences, nValueReferences, orders, values, nValues); +} + +FMIStatus FMI3DoStep(FMIInstance *instance, + fmi3Float64 currentCommunicationPoint, + fmi3Float64 communicationStepSize, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *eventEncountered, + fmi3Boolean *terminate, + fmi3Boolean *earlyReturn, + fmi3Float64 *lastSuccessfulTime) +{ + + FMIStatus status = (FMIStatus) instance->fmi3Functions->fmi3DoStep(instance->component, currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint, eventEncountered, terminate, earlyReturn, lastSuccessfulTime); + + if (instance->logFunctionCall) { + instance->logFunctionCall(instance, status, + "fmi3DoStep(currentCommunicationPoint=%.16g, communicationStepSize=%.16g, noSetFMUStatePriorToCurrentPoint=%d, eventEncountered=%d, terminate=%d, earlyReturn=%d, lastSuccessfulTime=%.16g)", + currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint, *eventEncountered, *terminate, *earlyReturn, *lastSuccessfulTime); + } + + instance->time = *lastSuccessfulTime; + + return status; +} + +FMIStatus FMI3ActivateModelPartition(FMIInstance *instance, + fmi3ValueReference clockReference, + fmi3Float64 activationTime) +{ + CALL_ARGS(ActivateModelPartition, + "clockReference=%u, activationTime=%.16g", + clockReference, activationTime); +} + +#undef LOAD_SYMBOL +#undef CALL +#undef CALL_ARGS +#undef CALL_ARRAY diff --git a/oscillator/solver-fmi/fmu/src/cosimulation.c b/oscillator/solver-fmi/fmu/src/cosimulation.c new file mode 100644 index 000000000..514521f06 --- /dev/null +++ b/oscillator/solver-fmi/fmu/src/cosimulation.c @@ -0,0 +1,620 @@ +#include "cosimulation.h" +#include // for DBL_EPSILON +#include // for fabs() +#include +#include +#include // for calloc(), free() +#include +#include "config.h" + +#if FMI_VERSION == 3 +#include "fmi3Functions.h" +#endif + +#ifdef _MSC_VER +#define strdup _strdup +#endif + +ModelInstance *createModelInstance( + loggerType cbLogger, + intermediateUpdateType intermediateUpdate, + void *componentEnvironment, + const char *instanceName, + const char *instantiationToken, + const char *resourceLocation, + bool loggingOn, + InterfaceType interfaceType) +{ + + ModelInstance *comp = NULL; + + if (!instanceName || strlen(instanceName) == 0) { + if (cbLogger) { +#if FMI_VERSION < 3 + cbLogger(componentEnvironment, "?", Error, "error", "Missing instance name."); +#else + cbLogger(componentEnvironment, Error, "error", "Missing instance name."); +#endif + } + return NULL; + } + + if (!instantiationToken || strlen(instantiationToken) == 0) { + if (cbLogger) { +#if FMI_VERSION < 3 + cbLogger(componentEnvironment, instanceName, Error, "error", "Missing GUID."); +#else + cbLogger(componentEnvironment, Error, "error", "Missing instantiationToken."); +#endif + } + return NULL; + } + + if (strcmp(instantiationToken, INSTANTIATION_TOKEN)) { + if (cbLogger) { +#if FMI_VERSION < 3 + cbLogger(componentEnvironment, instanceName, Error, "error", "Wrong GUID."); +#else + cbLogger(componentEnvironment, Error, "error", "Wrong instantiationToken."); +#endif + } + return NULL; + } + + comp = (ModelInstance *) calloc(1, sizeof(ModelInstance)); + + if (comp) { + comp->componentEnvironment = componentEnvironment; + comp->logger = cbLogger; + comp->intermediateUpdate = intermediateUpdate; + comp->lockPreemtion = NULL; + comp->unlockPreemtion = NULL; + comp->instanceName = strdup(instanceName); + comp->resourceLocation = resourceLocation ? strdup(resourceLocation) : NULL; + comp->status = OK; + comp->logEvents = loggingOn; + comp->logErrors = true; // always log errors + comp->nSteps = 0; + comp->solverStepSize = 1e-3; + comp->earlyReturnAllowed = false; + comp->eventModeUsed = false; + } + + if (!comp || !comp->instanceName) { + logError(comp, "Out of memory."); + return NULL; + } + + comp->time = 0.0; // overwrite in fmi*SetupExperiment, fmi*SetTime + comp->type = interfaceType; + + comp->state = Instantiated; + + comp->newDiscreteStatesNeeded = false; + comp->terminateSimulation = false; + comp->nominalsOfContinuousStatesChanged = false; + comp->valuesOfContinuousStatesChanged = false; + comp->nextEventTimeDefined = false; + comp->nextEventTime = 0; + + setStartValues(comp); + + comp->isDirtyValues = true; + + return comp; +} + +void freeModelInstance(ModelInstance *comp) +{ + free((void *) comp->instanceName); + free(comp); +} + +void reset(ModelInstance *comp) +{ + comp->state = Instantiated; + comp->startTime = 0.0; + comp->time = 0.0; + comp->nSteps = 0; + comp->solverStepSize = 1e-3; + comp->status = OK; + setStartValues(comp); + comp->isDirtyValues = true; +} + +bool invalidNumber(ModelInstance *comp, const char *f, const char *arg, size_t actual, size_t expected) +{ + + if (actual != expected) { + comp->state = modelError; + logError(comp, "%s: Invalid argument %s = %d. Expected %d.", f, arg, actual, expected); + return true; + } + + return false; +} + +bool invalidState(ModelInstance *comp, const char *f, int statesExpected) +{ + + UNUSED(f); + UNUSED(statesExpected); + + if (!comp) { + return true; + } + + // TODO: add missing states and check state + return false; + + // if (!(comp->state & statesExpected)) { + // comp->state = modelError; + // logError(comp, "%s: Illegal call sequence.", f); + // return true; + // } + // + // return false; +} + +bool nullPointer(ModelInstance *comp, const char *f, const char *arg, const void *p) +{ + + if (!p) { + comp->state = modelError; + logError(comp, "%s: Invalid argument %s = NULL.", f, arg); + return true; + } + + return false; +} + +Status setDebugLogging(ModelInstance *comp, bool loggingOn, size_t nCategories, const char *const categories[]) +{ + + if (loggingOn) { + for (size_t i = 0; i < nCategories; i++) { + if (categories[i] == NULL) { + logError(comp, "Log category[%d] must not be NULL", i); + return Error; + } else if (strcmp(categories[i], "logEvents") == 0) { + comp->logEvents = true; + } else if (strcmp(categories[i], "logStatusError") == 0) { + comp->logErrors = true; + } else { + logError(comp, "Log category[%d] must be one of logEvents or logStatusError but was %s", i, categories[i]); + return Error; + } + } + } else { + // disable logging + comp->logEvents = false; + comp->logErrors = false; + } + + return OK; +} + +static void logMessage(ModelInstance *comp, int status, const char *category, const char *message, va_list args) +{ + + if (!comp->logger) { + return; + } + + va_list args1; + size_t len = 0; + char *buf = ""; + + va_copy(args1, args); + len = vsnprintf(buf, len, message, args1); + va_end(args1); + + va_copy(args1, args); + buf = (char *) calloc(len + 1, sizeof(char)); + vsnprintf(buf, len + 1, message, args); + va_end(args1); + + // no need to distinguish between FMI versions since we're not using variadic arguments +#if FMI_VERSION < 3 + comp->logger(comp->componentEnvironment, comp->instanceName, status, category, buf); +#else + comp->logger(comp->componentEnvironment, status, category, buf); +#endif + + free(buf); +} + +void logEvent(ModelInstance *comp, const char *message, ...) +{ + + if (!comp || !comp->logEvents) + return; + + va_list args; + va_start(args, message); + logMessage(comp, OK, "logEvents", message, args); + va_end(args); +} + +void logError(ModelInstance *comp, const char *message, ...) +{ + + if (!comp || !comp->logErrors) + return; + + va_list args; + va_start(args, message); + logMessage(comp, Error, "logStatusError", message, args); + va_end(args); +} + +// default implementations +#if NZ < 1 +void getEventIndicators(ModelInstance *comp, double z[], size_t nz) +{ + UNUSED(comp); + UNUSED(z); + UNUSED(nz); + // do nothing +} +#endif + +#define GET_NOT_ALLOWED(t) \ + do { \ + UNUSED(vr); \ + UNUSED(value); \ + UNUSED(index); \ + logError(comp, "Getting " t " is not allowed."); \ + return Error; \ + } while (false) + +#ifndef GET_FLOAT32 +Status getFloat32(ModelInstance *comp, ValueReference vr, float value[], size_t *index) +{ + GET_NOT_ALLOWED("Float32"); +} +#endif + +#ifndef GET_INT8 +Status getInt8(ModelInstance *comp, ValueReference vr, int8_t value[], size_t *index) +{ + GET_NOT_ALLOWED("Int8"); +} +#endif + +#ifndef GET_UINT8 +Status getUInt8(ModelInstance *comp, ValueReference vr, uint8_t value[], size_t *index) +{ + GET_NOT_ALLOWED("UInt8"); +} +#endif + +#ifndef GET_INT16 +Status getInt16(ModelInstance *comp, ValueReference vr, int16_t value[], size_t *index) +{ + GET_NOT_ALLOWED("Int16"); +} +#endif + +#ifndef GET_UINT16 +Status getUInt16(ModelInstance *comp, ValueReference vr, uint16_t value[], size_t *index) +{ + GET_NOT_ALLOWED("UInt16"); +} +#endif + +#ifndef GET_INT32 +Status getInt32(ModelInstance *comp, ValueReference vr, int32_t value[], size_t *index) +{ + GET_NOT_ALLOWED("Int32"); +} +#endif + +#ifndef GET_UINT32 +Status getUInt32(ModelInstance *comp, ValueReference vr, uint32_t value[], size_t *index) +{ + GET_NOT_ALLOWED("UInt32"); +} +#endif + +#ifndef GET_INT64 +Status getInt64(ModelInstance *comp, ValueReference vr, int64_t value[], size_t *index) +{ + GET_NOT_ALLOWED("Int64"); +} +#endif + +#ifndef GET_UINT64 +Status getUInt64(ModelInstance *comp, ValueReference vr, uint64_t value[], size_t *index) +{ + GET_NOT_ALLOWED("UInt64"); +} +#endif + +#ifndef GET_BOOLEAN +Status getBoolean(ModelInstance *comp, ValueReference vr, bool value[], size_t *index) +{ + GET_NOT_ALLOWED("Boolean"); +} +#endif + +#ifndef GET_STRING +Status getString(ModelInstance *comp, ValueReference vr, const char *value[], size_t *index) +{ + GET_NOT_ALLOWED("String"); +} +#endif + +#ifndef GET_BINARY +Status getBinary(ModelInstance *comp, ValueReference vr, size_t size[], const char *value[], size_t *index) +{ + UNUSED(size); + GET_NOT_ALLOWED("Binary"); +} +#endif + +#define SET_NOT_ALLOWED(t) \ + do { \ + UNUSED(vr); \ + UNUSED(value); \ + UNUSED(index); \ + logError(comp, "Setting " t " is not allowed."); \ + return Error; \ + } while (false) + +#ifndef SET_FLOAT32 +Status setFloat32(ModelInstance *comp, ValueReference vr, const float value[], size_t *index) +{ + SET_NOT_ALLOWED("Float32"); +} +#endif + +#ifndef SET_FLOAT64 +Status setFloat64(ModelInstance *comp, ValueReference vr, const double value[], size_t *index) +{ + SET_NOT_ALLOWED("Float64"); +} +#endif + +#ifndef SET_INT8 +Status setInt8(ModelInstance *comp, ValueReference vr, const int8_t value[], size_t *index) +{ + SET_NOT_ALLOWED("Int8"); +} +#endif + +#ifndef SET_UINT8 +Status setUInt8(ModelInstance *comp, ValueReference vr, const uint8_t value[], size_t *index) +{ + SET_NOT_ALLOWED("UInt8"); +} +#endif + +#ifndef SET_INT16 +Status setInt16(ModelInstance *comp, ValueReference vr, const int16_t value[], size_t *index) +{ + SET_NOT_ALLOWED("Int16"); +} +#endif + +#ifndef SET_UINT16 +Status setUInt16(ModelInstance *comp, ValueReference vr, const uint16_t value[], size_t *index) +{ + SET_NOT_ALLOWED("UInt16"); +} +#endif + +#ifndef SET_INT32 +Status setInt32(ModelInstance *comp, ValueReference vr, const int32_t value[], size_t *index) +{ + SET_NOT_ALLOWED("Int32"); +} +#endif + +#ifndef SET_UINT32 +Status setUInt32(ModelInstance *comp, ValueReference vr, const uint32_t value[], size_t *index) +{ + SET_NOT_ALLOWED("UInt32"); +} +#endif + +#ifndef SET_INT64 +Status setInt64(ModelInstance *comp, ValueReference vr, const int64_t value[], size_t *index) +{ + SET_NOT_ALLOWED("Int64"); +} +#endif + +#ifndef SET_UINT64 +Status setUInt64(ModelInstance *comp, ValueReference vr, const uint64_t value[], size_t *index) +{ + SET_NOT_ALLOWED("UInt64"); +} +#endif + +#ifndef SET_BOOLEAN +Status setBoolean(ModelInstance *comp, ValueReference vr, const bool value[], size_t *index) +{ + SET_NOT_ALLOWED("Boolean"); +} +#endif + +#ifndef SET_STRING +Status setString(ModelInstance *comp, ValueReference vr, const char *const value[], size_t *index) +{ + SET_NOT_ALLOWED("String"); +} +#endif + +#ifndef SET_BINARY +Status setBinary(ModelInstance *comp, ValueReference vr, const size_t size[], const char *const value[], size_t *index) +{ + UNUSED(size); + SET_NOT_ALLOWED("Binary"); +} +#endif + +#ifndef ACTIVATE_CLOCK +Status activateClock(ModelInstance *comp, ValueReference vr) +{ + UNUSED(comp); + UNUSED(vr); + return Error; +} +#endif + +#ifndef GET_CLOCK +Status getClock(ModelInstance *comp, ValueReference vr, bool *value) +{ + UNUSED(comp); + UNUSED(vr); + UNUSED(value); + return Error; +} +#endif + +#ifndef GET_INTERVAL +Status getInterval(ModelInstance *comp, ValueReference vr, double *interval, int *qualifier) +{ + UNUSED(comp); + UNUSED(vr); + UNUSED(interval); + UNUSED(qualifier); + return Error; +} +#endif + +#ifndef ACTIVATE_MODEL_PARTITION +Status activateModelPartition(ModelInstance *comp, ValueReference vr, double activationTime) +{ + UNUSED(comp); + UNUSED(vr); + UNUSED(activationTime); + return Error; +} +#endif + +#if NX < 1 +void getContinuousStates(ModelInstance *comp, double x[], size_t nx) +{ + UNUSED(comp); + UNUSED(x); + UNUSED(nx); +} + +void setContinuousStates(ModelInstance *comp, const double x[], size_t nx) +{ + UNUSED(comp); + UNUSED(x); + UNUSED(nx); +} + +void getDerivatives(ModelInstance *comp, double dx[], size_t nx) +{ + UNUSED(comp); + UNUSED(dx); + UNUSED(nx); +} +#endif + +#ifndef GET_PARTIAL_DERIVATIVE +Status getPartialDerivative(ModelInstance *comp, ValueReference unknown, ValueReference known, double *partialDerivative) +{ + UNUSED(comp); + UNUSED(unknown); + UNUSED(known); + UNUSED(partialDerivative); + return Error; +} +#endif + +void *getFMUState(ModelInstance *comp) +{ + + ModelInstance *fmuState = (ModelInstance *) calloc(1, sizeof(ModelInstance)); + + memcpy(fmuState, comp, sizeof(ModelInstance)); + + return fmuState; +} + +void setFMUState(ModelInstance *comp, void *FMUState) +{ + + ModelInstance *s = (ModelInstance *) FMUState; + + comp->startTime = s->startTime; + comp->time = s->time; + comp->solverStepSize = s->solverStepSize; + comp->status = s->status; + comp->state = s->state; + comp->newDiscreteStatesNeeded = s->newDiscreteStatesNeeded; + comp->terminateSimulation = s->terminateSimulation; + comp->nominalsOfContinuousStatesChanged = s->nominalsOfContinuousStatesChanged; + comp->valuesOfContinuousStatesChanged = s->valuesOfContinuousStatesChanged; + comp->nextEventTimeDefined = s->nextEventTimeDefined; + comp->nextEventTime = s->nextEventTime; + comp->clocksTicked = s->clocksTicked; + comp->isDirtyValues = s->isDirtyValues; + comp->modelData = s->modelData; +#if NZ > 0 + memcpy(comp->z, s->z, NZ * sizeof(double)); +#endif + comp->nSteps = s->nSteps; +} + +void doFixedStep(ModelInstance *comp, bool *stateEvent, bool *timeEvent) +{ + + UNUSED(comp); + UNUSED(stateEvent); + UNUSED(timeEvent); + logError(comp, "Fixed step not yet implemented. Please use doAlphaStep or implement method."); +} + +void doAlphaStep(ModelInstance *comp, bool *stateEvent, bool *timeEvent) +{ + + // get current time step size + double dt = comp->solverStepSize; + + // create local variables + double t = comp->time; + double m[3] = {0}; + double force_in = M(force_in); + double force_out = 0; + double gamma = 0.5 - M(alpha_m) + M(alpha_f); + double beta = 0.25 * (gamma + 0.5); + double u_new = 0; + double v_new = 0; + double a_new = 0; + double k_bar = 0; + double stiffness = M(spring_fixed_c) + M(spring_middle_c); + + // do generalized alpha step + m[0] = (1 - M(alpha_m)) / (beta * dt * dt); + m[1] = (1 - M(alpha_m)) / (beta * dt); + m[2] = (1 - M(alpha_m) - 2 * beta) / (2 * beta); + + k_bar = stiffness * (1 - M(alpha_f)) + m[0] * M(mass_m); + u_new = (force_in - M(alpha_f) * stiffness * M(mass_u) + M(mass_m) * (m[0] * M(mass_u) + m[1] * M(mass_v) + m[2] * M(mass_a))) / k_bar; + a_new = 1.0 / (beta * dt * dt) * (u_new - M(mass_u) - dt * M(mass_v)) - (1 - 2 * beta) / (2 * beta) * M(mass_a); + v_new = M(mass_v) + dt * ((1 - gamma) * M(mass_a) + gamma * a_new); + + // compute force + force_out = M(spring_middle_c) * u_new; + + // store new values + M(mass_u) = u_new; + M(mass_v) = v_new; + M(mass_a) = a_new; + M(force_out) = force_out; + + // advance time + comp->nSteps++; + comp->time = t + comp->solverStepSize; + + // state event + *stateEvent = false; + UNUSED(timeEvent); +} diff --git a/oscillator/solver-fmi/fmu/src/fmi2Functions.c b/oscillator/solver-fmi/fmu/src/fmi2Functions.c new file mode 100644 index 000000000..c493ef6fb --- /dev/null +++ b/oscillator/solver-fmi/fmu/src/fmi2Functions.c @@ -0,0 +1,923 @@ +#if FMI_VERSION != 2 +#error FMI_VERSION must be 2 +#endif + +#include +#include +#include +#include + +#include "config.h" +#include "cosimulation.h" +#include "model.h" + +// C-code FMUs have functions names prefixed with MODEL_IDENTIFIER_. +// Define DISABLE_PREFIX to build a binary FMU. +#ifndef DISABLE_PREFIX +#define pasteA(a, b) a##b +#define pasteB(a, b) pasteA(a, b) +#define FMI2_FUNCTION_PREFIX pasteB(MODEL_IDENTIFIER, _) +#endif +#include "fmi2Functions.h" + +#define ASSERT_NOT_NULL(p) \ + do { \ + if (!p) { \ + logError(S, "Argument %s must not be NULL.", xstr(p)); \ + S->state = modelError; \ + return (fmi2Status) Error; \ + } \ + } while (0) + +#define GET_VARIABLES(T) \ + do { \ + Status status = OK; \ + if (nvr == 0) \ + return (fmi2Status) status; \ + ASSERT_NOT_NULL(vr); \ + ASSERT_NOT_NULL(value); \ + size_t index = 0; \ + if (S->isDirtyValues) { \ + Status s = calculateValues(S); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi2Status) status; \ + S->isDirtyValues = false; \ + } \ + for (size_t i = 0; i < nvr; i++) { \ + Status s = get##T(S, vr[i], value, &index); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi2Status) status; \ + } \ + return (fmi2Status) status; \ + } while (0) + +#define SET_VARIABLES(T) \ + do { \ + Status status = OK; \ + if (nvr == 0) \ + return (fmi2Status) status; \ + ASSERT_NOT_NULL(vr); \ + ASSERT_NOT_NULL(value); \ + size_t index = 0; \ + for (size_t i = 0; i < nvr; i++) { \ + Status s = set##T(S, vr[i], value, &index); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi2Status) status; \ + } \ + if (nvr > 0) \ + S->isDirtyValues = true; \ + return (fmi2Status) status; \ + } while (0) + +#define GET_BOOLEAN_VARIABLES \ + do { \ + Status status = OK; \ + for (size_t i = 0; i < nvr; i++) { \ + bool v = false; \ + size_t index = 0; \ + Status s = getBoolean(S, vr[i], &v, &index); \ + value[i] = v; \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi2Status) status; \ + } \ + return (fmi2Status) status; \ + } while (0) + +#define SET_BOOLEAN_VARIABLES \ + do { \ + Status status = OK; \ + for (size_t i = 0; i < nvr; i++) { \ + bool v = value[i]; \ + size_t index = 0; \ + Status s = setBoolean(S, vr[i], &v, &index); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi2Status) status; \ + } \ + return (fmi2Status) status; \ + } while (0) + +#ifndef max +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef DT_EVENT_DETECT +#define DT_EVENT_DETECT 1e-10 +#endif + +// --------------------------------------------------------------------------- +// Function calls allowed state masks for both Model-exchange and Co-simulation +// --------------------------------------------------------------------------- +#define MASK_fmi2GetTypesPlatform (StartAndEnd | Instantiated | InitializationMode | EventMode | ContinuousTimeMode | StepComplete | StepInProgress | StepFailed | StepCanceled | Terminated | Error) +#define MASK_fmi2GetVersion MASK_fmi2GetTypesPlatform +#define MASK_fmi2SetDebugLogging (Instantiated | InitializationMode | EventMode | ContinuousTimeMode | StepComplete | StepInProgress | StepFailed | StepCanceled | Terminated | Error) +#define MASK_fmi2Instantiate (StartAndEnd) +#define MASK_fmi2FreeInstance (Instantiated | InitializationMode | EventMode | ContinuousTimeMode | StepComplete | StepFailed | StepCanceled | Terminated | Error) +#define MASK_fmi2SetupExperiment Instantiated +#define MASK_fmi2EnterInitializationMode Instantiated +#define MASK_fmi2ExitInitializationMode InitializationMode +#define MASK_fmi2Terminate (EventMode | ContinuousTimeMode | StepComplete | StepFailed) +#define MASK_fmi2Reset MASK_fmi2FreeInstance +#define MASK_fmi2GetReal (InitializationMode | EventMode | ContinuousTimeMode | StepComplete | StepFailed | StepCanceled | Terminated | Error) +#define MASK_fmi2GetInteger MASK_fmi2GetReal +#define MASK_fmi2GetBoolean MASK_fmi2GetReal +#define MASK_fmi2GetString MASK_fmi2GetReal +#define MASK_fmi2SetReal (Instantiated | InitializationMode | EventMode | ContinuousTimeMode | StepComplete) +#define MASK_fmi2SetInteger (Instantiated | InitializationMode | EventMode | StepComplete) +#define MASK_fmi2SetBoolean MASK_fmi2SetInteger +#define MASK_fmi2SetString MASK_fmi2SetInteger +#define MASK_fmi2GetFMUstate MASK_fmi2FreeInstance +#define MASK_fmi2SetFMUstate MASK_fmi2FreeInstance +#define MASK_fmi2FreeFMUstate MASK_fmi2FreeInstance +#define MASK_fmi2SerializedFMUstateSize MASK_fmi2FreeInstance +#define MASK_fmi2SerializeFMUstate MASK_fmi2FreeInstance +#define MASK_fmi2DeSerializeFMUstate MASK_fmi2FreeInstance +#define MASK_fmi2GetDirectionalDerivative (InitializationMode | EventMode | ContinuousTimeMode | StepComplete | StepFailed | StepCanceled | Terminated | Error) + +// --------------------------------------------------------------------------- +// Function calls allowed state masks for Model-exchange +// --------------------------------------------------------------------------- +#define MASK_fmi2EnterEventMode (EventMode | ContinuousTimeMode) +#define MASK_fmi2NewDiscreteStates EventMode +#define MASK_fmi2EnterContinuousTimeMode EventMode +#define MASK_fmi2CompletedIntegratorStep ContinuousTimeMode +#define MASK_fmi2SetTime (EventMode | ContinuousTimeMode) +#define MASK_fmi2SetContinuousStates ContinuousTimeMode +#define MASK_fmi2GetEventIndicators (InitializationMode | EventMode | ContinuousTimeMode | Terminated | Error) +#define MASK_fmi2GetContinuousStates MASK_fmi2GetEventIndicators +#define MASK_fmi2GetDerivatives (EventMode | ContinuousTimeMode | Terminated | Error) +#define MASK_fmi2GetNominalsOfContinuousStates (Instantiated | EventMode | ContinuousTimeMode | Terminated | Error) + +// --------------------------------------------------------------------------- +// Function calls allowed state masks for Co-simulation +// --------------------------------------------------------------------------- +#define MASK_fmi2SetRealInputDerivatives (Instantiated | InitializationMode | StepComplete) +#define MASK_fmi2GetRealOutputDerivatives (StepComplete | StepFailed | StepCanceled | Terminated | Error) +#define MASK_fmi2DoStep StepComplete +#define MASK_fmi2CancelStep StepInProgress +#define MASK_fmi2GetStatus (StepComplete | StepInProgress | StepFailed | Terminated) +#define MASK_fmi2GetRealStatus MASK_fmi2GetStatus +#define MASK_fmi2GetIntegerStatus MASK_fmi2GetStatus +#define MASK_fmi2GetBooleanStatus MASK_fmi2GetStatus +#define MASK_fmi2GetStringStatus MASK_fmi2GetStatus + +// shorthand to access the instance +#define S ((ModelInstance *) c) + +#define ASSERT_STATE(S) \ + if (!allowedState(c, MASK_fmi2##S, #S)) \ + return fmi2Error; + +static bool allowedState(ModelInstance *instance, int statesExpected, char *name) +{ + + if (!instance) { + return false; + } + + if (!(instance->state & statesExpected)) { + logError(instance, "fmi2%s: Illegal call sequence.", name); + return false; + } + + return true; +} + +// --------------------------------------------------------------------------- +// FMI functions +// --------------------------------------------------------------------------- + +fmi2Component fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID, + fmi2String fmuResourceLocation, const fmi2CallbackFunctions *functions, + fmi2Boolean visible, fmi2Boolean loggingOn) +{ + + UNUSED(visible); + + if (!functions || !functions->logger) { + return NULL; + } + + return createModelInstance( + (loggerType) functions->logger, + NULL, + functions->componentEnvironment, + instanceName, + fmuGUID, + fmuResourceLocation, + loggingOn, + (InterfaceType) fmuType); +} + +fmi2Status fmi2SetupExperiment(fmi2Component c, fmi2Boolean toleranceDefined, fmi2Real tolerance, + fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime) +{ + + UNUSED(toleranceDefined); + UNUSED(tolerance); + UNUSED(stopTimeDefined); + UNUSED(stopTime); + + ASSERT_STATE(SetupExperiment) + + S->startTime = startTime; + S->time = startTime; + + return fmi2OK; +} + +fmi2Status fmi2EnterInitializationMode(fmi2Component c) +{ + + ASSERT_STATE(EnterInitializationMode) + + S->state = InitializationMode; + + return fmi2OK; +} + +fmi2Status fmi2ExitInitializationMode(fmi2Component c) +{ + + ASSERT_STATE(ExitInitializationMode); + + fmi2Status status = fmi2OK; + + // if values were set and no fmi2GetXXX triggered update before, + // ensure calculated values are updated now + if (S->isDirtyValues) { + status = (fmi2Status) calculateValues(S); + S->isDirtyValues = false; + } + + if (S->type == ModelExchange) { + S->state = EventMode; + } else { + S->state = StepComplete; + } + + return status; +} + +fmi2Status fmi2Terminate(fmi2Component c) +{ + + ASSERT_STATE(Terminate) + + S->state = Terminated; + + return fmi2OK; +} + +fmi2Status fmi2Reset(fmi2Component c) +{ + + ASSERT_STATE(Reset); + + reset(S); + + return fmi2OK; +} + +void fmi2FreeInstance(fmi2Component c) +{ + + if (S) { + freeModelInstance(S); + } +} + +// --------------------------------------------------------------------------- +// FMI functions: class methods not depending of a specific model instance +// --------------------------------------------------------------------------- + +const char *fmi2GetVersion() +{ + return fmi2Version; +} + +const char *fmi2GetTypesPlatform() +{ + return fmi2TypesPlatform; +} + +// --------------------------------------------------------------------------- +// FMI functions: logging control, setters and getters for Real, Integer, +// Boolean, String +// --------------------------------------------------------------------------- + +fmi2Status fmi2SetDebugLogging(fmi2Component c, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[]) +{ + + ASSERT_STATE(SetDebugLogging) + + return (fmi2Status) setDebugLogging(S, loggingOn, nCategories, categories); +} + +fmi2Status fmi2GetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[]) +{ + + ASSERT_STATE(GetReal) + + if (nvr > 0 && nullPointer(S, "fmi2GetReal", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2GetReal", "value[]", value)) + return fmi2Error; + + if (nvr > 0 && S->isDirtyValues) { + calculateValues(S); + S->isDirtyValues = false; + } + + GET_VARIABLES(Float64); +} + +fmi2Status fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[]) +{ + + ASSERT_STATE(GetInteger) + + if (nvr > 0 && nullPointer(S, "fmi2GetInteger", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2GetInteger", "value[]", value)) + return fmi2Error; + + if (nvr > 0 && S->isDirtyValues) { + calculateValues(S); + S->isDirtyValues = false; + } + + GET_VARIABLES(Int32); +} + +fmi2Status fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[]) +{ + + ASSERT_STATE(GetBoolean) + + if (nvr > 0 && nullPointer(S, "fmi2GetBoolean", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2GetBoolean", "value[]", value)) + return fmi2Error; + + if (nvr > 0 && S->isDirtyValues) { + calculateValues(S); + S->isDirtyValues = false; + } + + GET_BOOLEAN_VARIABLES; +} + +fmi2Status fmi2GetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[]) +{ + + ASSERT_STATE(GetString) + + if (nvr > 0 && nullPointer(S, "fmi2GetString", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2GetString", "value[]", value)) + return fmi2Error; + + if (nvr > 0 && S->isDirtyValues) { + calculateValues(S); + S->isDirtyValues = false; + } + + GET_VARIABLES(String); +} + +fmi2Status fmi2SetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[]) +{ + + ASSERT_STATE(SetReal) + + if (invalidState(S, "fmi2SetReal", MASK_fmi2SetReal)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2SetReal", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2SetReal", "value[]", value)) + return fmi2Error; + + SET_VARIABLES(Float64); +} + +fmi2Status fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[]) +{ + + ASSERT_STATE(SetInteger) + + if (nvr > 0 && nullPointer(S, "fmi2SetInteger", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2SetInteger", "value[]", value)) + return fmi2Error; + + SET_VARIABLES(Int32); +} + +fmi2Status fmi2SetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[]) +{ + + ASSERT_STATE(SetBoolean) + + if (nvr > 0 && nullPointer(S, "fmi2SetBoolean", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2SetBoolean", "value[]", value)) + return fmi2Error; + + SET_BOOLEAN_VARIABLES; +} + +fmi2Status fmi2SetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[]) +{ + + ASSERT_STATE(SetString); + + if (nvr > 0 && nullPointer(S, "fmi2SetString", "vr[]", vr)) + return fmi2Error; + + if (nvr > 0 && nullPointer(S, "fmi2SetString", "value[]", value)) + return fmi2Error; + + SET_VARIABLES(String); +} + +fmi2Status fmi2GetFMUstate(fmi2Component c, fmi2FMUstate *FMUstate) +{ + + ASSERT_STATE(GetFMUstate); + + *FMUstate = getFMUState(S); + + return fmi2OK; +} + +fmi2Status fmi2SetFMUstate(fmi2Component c, fmi2FMUstate FMUstate) +{ + + ASSERT_STATE(SetFMUstate); + + if (nullPointer(S, "fmi2SetFMUstate", "FMUstate", FMUstate)) { + return fmi2Error; + } + + setFMUState(S, FMUstate); + + return fmi2OK; +} + +fmi2Status fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate *FMUstate) +{ + + ASSERT_STATE(FreeFMUstate); + + free(*FMUstate); + + *FMUstate = NULL; + + return fmi2OK; +} + +fmi2Status fmi2SerializedFMUstateSize(fmi2Component c, fmi2FMUstate FMUstate, size_t *size) +{ + + UNUSED(c); + UNUSED(FMUstate); + + ASSERT_STATE(SerializedFMUstateSize); + + *size = sizeof(ModelInstance); + + return fmi2OK; +} + +fmi2Status fmi2SerializeFMUstate(fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size) +{ + + ASSERT_STATE(SerializeFMUstate); + + if (nullPointer(S, "fmi2SerializeFMUstate", "FMUstate", FMUstate)) { + return fmi2Error; + } + + if (invalidNumber(S, "fmi2SerializeFMUstate", "size", size, sizeof(ModelInstance))) { + return fmi2Error; + } + + memcpy(serializedState, FMUstate, sizeof(ModelInstance)); + + return fmi2OK; +} + +fmi2Status fmi2DeSerializeFMUstate(fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate *FMUstate) +{ + + ASSERT_STATE(DeSerializeFMUstate); + + if (invalidNumber(S, "fmi2DeSerializeFMUstate", "size", size, sizeof(ModelInstance))) { + return fmi2Error; + } + + if (*FMUstate == NULL) { + *FMUstate = calloc(1, sizeof(ModelInstance)); + } + + memcpy(*FMUstate, serializedState, sizeof(ModelInstance)); + + return fmi2OK; +} + +fmi2Status fmi2GetDirectionalDerivative(fmi2Component c, const fmi2ValueReference vUnknown_ref[], size_t nUnknown, + const fmi2ValueReference vKnown_ref[], size_t nKnown, + const fmi2Real dvKnown[], fmi2Real dvUnknown[]) +{ + + ASSERT_STATE(GetDirectionalDerivative); + + // TODO: check value references + // TODO: assert nUnknowns == nDeltaOfUnknowns + // TODO: assert nKnowns == nDeltaKnowns + + Status status = OK; + + for (size_t i = 0; i < nUnknown; i++) { + dvUnknown[i] = 0; + for (size_t j = 0; j < nKnown; j++) { + double partialDerivative = 0; + Status s = getPartialDerivative(S, vUnknown_ref[i], vKnown_ref[j], &partialDerivative); + status = max(status, s); + if (status > Warning) { + return (fmi2Status) status; + } + dvUnknown[i] += partialDerivative * dvKnown[j]; + } + } + + return fmi2OK; +} + +// --------------------------------------------------------------------------- +// Functions for FMI for Co-Simulation +// --------------------------------------------------------------------------- +/* Simulating the slave */ +fmi2Status fmi2SetRealInputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], const fmi2Real value[]) +{ + + UNUSED(vr); + UNUSED(nvr); + UNUSED(order); + UNUSED(value); + + ASSERT_STATE(SetRealInputDerivatives); + + logError(S, "fmi2SetRealInputDerivatives: ignoring function call." + " This model cannot interpolate inputs: canInterpolateInputs=\"fmi2False\""); + + return fmi2Error; +} + +fmi2Status fmi2GetRealOutputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, + const fmi2Integer order[], fmi2Real value[]) +{ + + ASSERT_STATE(GetRealOutputDerivatives); + +#ifdef GET_OUTPUT_DERIVATIVE + Status status = OK; + + for (size_t i = 0; i < nvr; i++) { + const Status s = getOutputDerivative(S, vr[i], order[i], &value[i]); + status = max(status, s); + if (status > Warning) { + return (fmi2Status) status; + } + } + + return (fmi2Status) status; +#else + UNUSED(vr); + UNUSED(nvr); + UNUSED(order); + UNUSED(value); + + logError(S, "fmi2GetRealOutputDerivatives: ignoring function call." + " This model cannot compute derivatives of outputs: MaxOutputDerivativeOrder=\"0\""); + + return fmi2Error; +#endif +} + +fmi2Status fmi2CancelStep(fmi2Component c) +{ + + ASSERT_STATE(CancelStep); + + logError(S, "fmi2CancelStep: Can be called when fmi2DoStep returned fmi2Pending." + " This is not the case."); + + return fmi2Error; +} + +fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, + fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPoint) +{ + + UNUSED(noSetFMUStatePriorToCurrentPoint); + + ASSERT_STATE(DoStep); + + if (communicationStepSize <= 0) { + logError(S, "fmi2DoStep: communication step size must be > 0 but was %g.", communicationStepSize); + S->state = modelError; + return fmi2Error; + } + + const fmi2Real nextCommunicationPoint = currentCommunicationPoint + communicationStepSize + EPSILON; + + S->solverStepSize = communicationStepSize; + + fmi2Boolean nextCommunicationPointReached; + + while (true) { + + nextCommunicationPointReached = S->time + S->solverStepSize > nextCommunicationPoint; + + if (nextCommunicationPointReached) { + break; // next communcation point reached + } + + bool stateEvent, timeEvent; + + doAlphaStep(S, &stateEvent, &timeEvent); + +#ifdef EVENT_UPDATE + if (stateEvent || timeEvent) { + eventUpdate(S); + } +#endif + } + + return S->terminateSimulation ? fmi2Discard : fmi2OK; +} + +/* Inquire slave status */ +static fmi2Status getStatus(char *fname, fmi2Component c, const fmi2StatusKind s) +{ + + if (invalidState(S, fname, MASK_fmi2GetStatus)) // all get status have the same MASK_fmi2GetStatus + return fmi2Error; + + switch (s) { + case fmi2DoStepStatus: + logError(S, + "%s: Can be called with fmi2DoStepStatus when fmi2DoStep returned fmi2Pending." + " This is not the case.", + fname); + break; + case fmi2PendingStatus: + logError(S, + "%s: Can be called with fmi2PendingStatus when fmi2DoStep returned fmi2Pending." + " This is not the case.", + fname); + break; + case fmi2LastSuccessfulTime: + logError(S, + "%s: Can be called with fmi2LastSuccessfulTime when fmi2DoStep returned fmi2Discard." + " This is not the case.", + fname); + break; + case fmi2Terminated: + logError(S, + "%s: Can be called with fmi2Terminated when fmi2DoStep returned fmi2Discard." + " This is not the case.", + fname); + break; + } + + return fmi2Discard; +} + +fmi2Status fmi2GetStatus(fmi2Component c, const fmi2StatusKind s, fmi2Status *value) +{ + + UNUSED(value); + + ASSERT_STATE(GetStatus); + + return getStatus("fmi2GetStatus", c, s); +} + +fmi2Status fmi2GetRealStatus(fmi2Component c, const fmi2StatusKind s, fmi2Real *value) +{ + + ASSERT_STATE(GetRealStatus); + + if (s == fmi2LastSuccessfulTime) { + *value = S->time; + return fmi2OK; + } + + return getStatus("fmi2GetRealStatus", c, s); +} + +fmi2Status fmi2GetIntegerStatus(fmi2Component c, const fmi2StatusKind s, fmi2Integer *value) +{ + + UNUSED(value); + + ASSERT_STATE(GetIntegerStatus); + + return getStatus("fmi2GetIntegerStatus", c, s); +} + +fmi2Status fmi2GetBooleanStatus(fmi2Component c, const fmi2StatusKind s, fmi2Boolean *value) +{ + + ASSERT_STATE(GetBooleanStatus); + + if (s == fmi2Terminated) { + *value = S->terminateSimulation; + return fmi2OK; + } + + return getStatus("fmi2GetBooleanStatus", c, s); +} + +fmi2Status fmi2GetStringStatus(fmi2Component c, const fmi2StatusKind s, fmi2String *value) +{ + UNUSED(value); + ASSERT_STATE(GetStringStatus); + return getStatus("fmi2GetStringStatus", c, s); +} + +// --------------------------------------------------------------------------- +// Functions for FMI2 for Model Exchange +// --------------------------------------------------------------------------- +/* Enter and exit the different modes */ +fmi2Status fmi2EnterEventMode(fmi2Component c) +{ + + ASSERT_STATE(EnterEventMode); + + S->state = EventMode; + + return fmi2OK; +} + +fmi2Status fmi2NewDiscreteStates(fmi2Component c, fmi2EventInfo *eventInfo) +{ + + ASSERT_STATE(NewDiscreteStates); + +#ifdef EVENT_UPDATE + eventUpdate(S); +#endif + + eventInfo->newDiscreteStatesNeeded = S->newDiscreteStatesNeeded; + eventInfo->terminateSimulation = S->terminateSimulation; + eventInfo->nominalsOfContinuousStatesChanged = S->nominalsOfContinuousStatesChanged; + eventInfo->valuesOfContinuousStatesChanged = S->valuesOfContinuousStatesChanged; + eventInfo->nextEventTimeDefined = S->nextEventTimeDefined; + eventInfo->nextEventTime = S->nextEventTime; + + return fmi2OK; +} + +fmi2Status fmi2EnterContinuousTimeMode(fmi2Component c) +{ + + ASSERT_STATE(EnterContinuousTimeMode); + + S->state = ContinuousTimeMode; + + return fmi2OK; +} + +fmi2Status fmi2CompletedIntegratorStep(fmi2Component c, fmi2Boolean noSetFMUStatePriorToCurrentPoint, + fmi2Boolean *enterEventMode, fmi2Boolean *terminateSimulation) +{ + + UNUSED(noSetFMUStatePriorToCurrentPoint); + + ASSERT_STATE(CompletedIntegratorStep); + + if (nullPointer(S, "fmi2CompletedIntegratorStep", "enterEventMode", enterEventMode)) + return fmi2Error; + + if (nullPointer(S, "fmi2CompletedIntegratorStep", "terminateSimulation", terminateSimulation)) + return fmi2Error; + + *enterEventMode = fmi2False; + *terminateSimulation = fmi2False; + + return fmi2OK; +} + +/* Providing independent variables and re-initialization of caching */ +fmi2Status fmi2SetTime(fmi2Component c, fmi2Real time) +{ + + ASSERT_STATE(SetTime); + + S->time = time; + + return fmi2OK; +} + +fmi2Status fmi2SetContinuousStates(fmi2Component c, const fmi2Real x[], size_t nx) +{ + + ASSERT_STATE(SetContinuousStates); + + if (invalidNumber(S, "fmi2SetContinuousStates", "nx", nx, NX)) + return fmi2Error; + + if (nullPointer(S, "fmi2SetContinuousStates", "x[]", x)) + return fmi2Error; + + setContinuousStates(S, x, nx); + + return fmi2OK; +} + +/* Evaluation of the model equations */ +fmi2Status fmi2GetDerivatives(fmi2Component c, fmi2Real derivatives[], size_t nx) +{ + + ASSERT_STATE(GetDerivatives); + + if (invalidNumber(S, "fmi2GetDerivatives", "nx", nx, NX)) + return fmi2Error; + + if (nullPointer(S, "fmi2GetDerivatives", "derivatives[]", derivatives)) + return fmi2Error; + + getDerivatives(S, derivatives, nx); + + return fmi2OK; +} + +fmi2Status fmi2GetEventIndicators(fmi2Component c, fmi2Real eventIndicators[], size_t ni) +{ + + ASSERT_STATE(GetEventIndicators); + +#if NZ > 0 + + if (invalidNumber(S, "fmi2GetEventIndicators", "ni", ni, NZ)) + return fmi2Error; + + getEventIndicators(S, eventIndicators, ni); +#else + UNUSED(c); + UNUSED(eventIndicators); + if (ni > 0) + return fmi2Error; +#endif + return fmi2OK; +} + +fmi2Status fmi2GetContinuousStates(fmi2Component c, fmi2Real states[], size_t nx) +{ + + ASSERT_STATE(GetContinuousStates); + + if (invalidNumber(S, "fmi2GetContinuousStates", "nx", nx, NX)) + return fmi2Error; + + if (nullPointer(S, "fmi2GetContinuousStates", "states[]", states)) + return fmi2Error; + + getContinuousStates(S, states, nx); + + return fmi2OK; +} + +fmi2Status fmi2GetNominalsOfContinuousStates(fmi2Component c, fmi2Real x_nominal[], size_t nx) +{ + + ASSERT_STATE(GetNominalsOfContinuousStates); + + if (invalidNumber(S, "fmi2GetNominalContinuousStates", "nx", nx, NX)) + return fmi2Error; + + if (nullPointer(S, "fmi2GetNominalContinuousStates", "x_nominal[]", x_nominal)) + return fmi2Error; + + for (size_t i = 0; i < nx; i++) + x_nominal[i] = 1; + + return fmi2OK; +} diff --git a/oscillator/solver-fmi/fmu/src/fmi3Functions.c b/oscillator/solver-fmi/fmu/src/fmi3Functions.c new file mode 100644 index 000000000..701476f6c --- /dev/null +++ b/oscillator/solver-fmi/fmu/src/fmi3Functions.c @@ -0,0 +1,1544 @@ +#if FMI_VERSION != 3 +#error FMI_VERSION must be 3 +#endif + +#include +#include +#include +#include + +#include "config.h" +#include "cosimulation.h" +#include "model.h" + +// C-code FMUs have functions names prefixed with MODEL_IDENTIFIER_. +// Define DISABLE_PREFIX to build a binary FMU. +#if !defined(DISABLE_PREFIX) && !defined(FMI3_FUNCTION_PREFIX) +#define pasteA(a, b) a##b +#define pasteB(a, b) pasteA(a, b) +#define FMI3_FUNCTION_PREFIX pasteB(MODEL_IDENTIFIER, _) +#endif +#include "fmi3Functions.h" + +#define ASSERT_NOT_NULL(p) \ + do { \ + if (!p) { \ + logError(S, "Argument %s must not be NULL.", xstr(p)); \ + S->state = modelError; \ + return (fmi3Status) Error; \ + } \ + } while (0) + +#define GET_VARIABLES(T) \ + do { \ + Status status = OK; \ + if (nValueReferences == 0) \ + return (fmi3Status) status; \ + ASSERT_NOT_NULL(valueReferences); \ + ASSERT_NOT_NULL(values); \ + size_t index = 0; \ + if (nValueReferences == 0) \ + return (fmi3Status) status; \ + if (S->isDirtyValues) { \ + Status s = calculateValues(S); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi3Status) status; \ + S->isDirtyValues = false; \ + } \ + for (size_t i = 0; i < nValueReferences; i++) { \ + Status s = get##T(S, (ValueReference) valueReferences[i], values, &index); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi3Status) status; \ + } \ + return (fmi3Status) status; \ + } while (0) + +#define SET_VARIABLES(T) \ + do { \ + Status status = OK; \ + if (nValueReferences == 0) \ + return (fmi3Status) status; \ + ASSERT_NOT_NULL(valueReferences); \ + ASSERT_NOT_NULL(values); \ + size_t index = 0; \ + for (size_t i = 0; i < nValueReferences; i++) { \ + Status s = set##T(S, (ValueReference) valueReferences[i], values, &index); \ + status = max(status, s); \ + if (status > Warning) \ + return (fmi3Status) status; \ + } \ + if (nValueReferences > 0) \ + S->isDirtyValues = true; \ + return (fmi3Status) status; \ + } while (0) + +#ifndef max +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef DT_EVENT_DETECT +#define DT_EVENT_DETECT 1e-10 +#endif + +// --------------------------------------------------------------------------- +// Function calls allowed state masks for both Model-exchange and Co-simulation +// --------------------------------------------------------------------------- +#define MASK_AnyState (~0) + +/* Inquire version numbers and set debug logging */ +#define MASK_fmi3GetVersion MASK_AnyState +#define MASK_fmi3SetDebugLogging MASK_AnyState + +/* Creation and destruction of FMU instances */ +#define MASK_fmi3InstantiateInstantiateModelExchange MASK_AnyState +#define MASK_fmi3InstantiateCoSimulation MASK_AnyState +#define MASK_fmi3InstantiateScheduledExectuion MASK_AnyState +#define MASK_fmi3FreeInstance MASK_AnyState + +/* Enter and exit initialization mode, terminate and reset */ +#define MASK_fmi3EnterInitializationMode Instantiated +#define MASK_fmi3ExitInitializationMode InitializationMode +#define MASK_fmi3EnterEventMode (ContinuousTimeMode | StepMode) +#define MASK_fmi3Terminate (ContinuousTimeMode | StepMode | StepDiscarded | EventMode | ClockActivationMode | ReconfigurationMode) +#define MASK_fmi3Reset MASK_AnyState + +/* Common Functions */ + +/* Getting and setting variable values */ +#define MASK_fmi3GetFloat32 (InitializationMode | ConfigurationMode | ReconfigurationMode | EventMode | ContinuousTimeMode | StepMode | ClockActivationMode | IntermediateUpdateMode | Terminated) +#define MASK_fmi3GetFloat64 MASK_fmi3GetFloat32 +#define MASK_fmi3GetInt8 MASK_fmi3GetFloat32 +#define MASK_fmi3GetUInt8 MASK_fmi3GetFloat32 +#define MASK_fmi3GetInt16 MASK_fmi3GetFloat32 +#define MASK_fmi3GetUInt16 MASK_fmi3GetFloat32 +#define MASK_fmi3GetInt32 MASK_fmi3GetFloat32 +#define MASK_fmi3GetUInt32 MASK_fmi3GetFloat32 +#define MASK_fmi3GetInt64 MASK_fmi3GetFloat32 +#define MASK_fmi3GetUInt64 MASK_fmi3GetFloat32 +#define MASK_fmi3GetBoolean MASK_fmi3GetFloat32 +#define MASK_fmi3GetString MASK_fmi3GetFloat32 +#define MASK_fmi3GetBinary MASK_fmi3GetFloat32 +#define MASK_fmi3GetClock MASK_AnyState + +#define MASK_fmi3SetFloat32 (Instantiated | InitializationMode | ConfigurationMode | ReconfigurationMode | EventMode | ContinuousTimeMode | StepMode | ClockActivationMode | IntermediateUpdateMode | Terminated) +#define MASK_fmi3SetFloat64 MASK_fmi3SetFloat32 +#define MASK_fmi3SetInt8 (Instantiated | ConfigurationMode | ReconfigurationMode | InitializationMode | EventMode | StepMode | ClockActivationMode | Terminated) +#define MASK_fmi3SetUInt8 MASK_fmi3SetInt8 +#define MASK_fmi3SetInt16 MASK_fmi3SetInt8 +#define MASK_fmi3SetUInt16 MASK_fmi3SetInt8 +#define MASK_fmi3SetInt32 MASK_fmi3SetInt8 +#define MASK_fmi3SetUInt32 MASK_fmi3SetInt8 +#define MASK_fmi3SetInt64 MASK_fmi3SetInt8 +#define MASK_fmi3SetUInt64 MASK_fmi3SetInt8 +#define MASK_fmi3SetBoolean MASK_fmi3SetInt8 +#define MASK_fmi3SetString MASK_fmi3SetInt8 +#define MASK_fmi3SetBinary MASK_fmi3SetInt8 +#define MASK_fmi3SetClock MASK_AnyState + +/* Getting Variable Dependency Information */ +#define MASK_fmi3GetNumberOfVariableDependencies MASK_AnyState +#define MASK_fmi3GetVariableDependencies MASK_AnyState + +/* Getting and setting the internal FMU state */ +#define MASK_fmi3GetFMUState MASK_AnyState +#define MASK_fmi3SetFMUState MASK_AnyState +#define MASK_fmi3FreeFMUState MASK_AnyState +#define MASK_fmi3SerializedFMUStateSize MASK_AnyState +#define MASK_fmi3SerializeFMUState MASK_AnyState +#define MASK_fmi3DeserializeFMUState MASK_AnyState + +/* Getting partial derivatives */ +#define MASK_fmi3GetDirectionalDerivative (InitializationMode | StepMode | EventMode | ContinuousTimeMode | Terminated) +#define MASK_fmi3GetAdjointDerivative MASK_fmi3GetDirectionalDerivative + +/* Entering and exiting the Configuration or Reconfiguration Mode */ +#define MASK_fmi3EnterConfigurationMode (Instantiated | StepMode | EventMode | ClockActivationMode) +#define MASK_fmi3ExitConfigurationMode (ConfigurationMode | ReconfigurationMode) + +/* Clock related functions */ +// TODO: fix masks +#define MASK_fmi3GetIntervalDecimal MASK_AnyState +#define MASK_fmi3GetIntervalFraction MASK_AnyState +#define MASK_fmi3SetIntervalDecimal MASK_AnyState +#define MASK_fmi3SetIntervalFraction MASK_AnyState +#define MASK_fmi3NewDiscreteStates MASK_AnyState + +/* Functions for Model Exchange */ + +#define MASK_fmi3EnterContinuousTimeMode EventMode +#define MASK_fmi3CompletedIntegratorStep ContinuousTimeMode + +/* Providing independent variables and re-initialization of caching */ +#define MASK_fmi3SetTime (EventMode | ContinuousTimeMode) +#define MASK_fmi3SetContinuousStates ContinuousTimeMode + +/* Evaluation of the model equations */ +#define MASK_fmi3GetContinuousStateDerivatives (InitializationMode | EventMode | ContinuousTimeMode | Terminated) +#define MASK_fmi3GetEventIndicators MASK_fmi3GetContinuousStateDerivatives +#define MASK_fmi3GetContinuousStates MASK_fmi3GetContinuousStateDerivatives +#define MASK_fmi3GetNominalsOfContinuousStates MASK_fmi3GetContinuousStateDerivatives + +#define MASK_fmi3GetNumberOfContinuousStates MASK_AnyState +#define MASK_fmi3GetNumberOfEventIndicators MASK_AnyState + +/* Functions for Co-Simulation */ + +#define MASK_fmi3EnterStepMode (InitializationMode | EventMode) +#define MASK_fmi3SetInputDerivatives (Instantiated | InitializationMode | StepMode) +#define MASK_fmi3GetOutputDerivatives (StepMode | StepDiscarded | Terminated | Error) +#define MASK_fmi3DoStep StepMode +#define MASK_fmi3ActivateModelPartition ClockActivationMode +#define MASK_fmi3DoEarlyReturn IntermediateUpdateMode +#define MASK_fmi3GetDoStepDiscardedStatus StepMode + +// --------------------------------------------------------------------------- +// Private helpers used below to validate function arguments +// --------------------------------------------------------------------------- + +#define NOT_IMPLEMENTED \ + do { \ + ModelInstance *comp = (ModelInstance *) instance; \ + logError(comp, "Function is not implemented."); \ + return fmi3Error; \ + } while (0) + +#define ASSERT_STATE(F) \ + if (!instance) \ + return fmi3Error; \ + ModelInstance *S = (ModelInstance *) instance; \ + if (!allowedState(S, MASK_fmi3##F, #F)) \ + return fmi3Error; + +static bool allowedState(ModelInstance *instance, int statesExpected, char *name) +{ + + if (!instance) { + return false; + } + + if (!(instance->state & statesExpected)) { + logError(instance, "fmi3%s: Illegal call sequence.", name); + return false; + } + + return true; +} + +/*************************************************** + Common Functions + ****************************************************/ + +const char *fmi3GetVersion() +{ + return fmi3Version; +} + +fmi3Status fmi3SetDebugLogging(fmi3Instance instance, + fmi3Boolean loggingOn, + size_t nCategories, + const fmi3String categories[]) +{ + + ASSERT_STATE(SetDebugLogging) + + return (fmi3Status) setDebugLogging(S, loggingOn, nCategories, categories); +} + +fmi3Instance fmi3InstantiateModelExchange( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage) +{ + + UNUSED(visible); + +#ifndef MODEL_EXCHANGE + UNUSED(instanceName); + UNUSED(instantiationToken); + UNUSED(resourcePath); + UNUSED(loggingOn); + UNUSED(instanceEnvironment); + UNUSED(logMessage); + + return NULL; +#else + return createModelInstance( + (loggerType) logMessage, + NULL, + instanceEnvironment, + instanceName, + instantiationToken, + resourcePath, + loggingOn, + ModelExchange); +#endif +} + +fmi3Instance fmi3InstantiateCoSimulation( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3Boolean eventModeUsed, + fmi3Boolean earlyReturnAllowed, + const fmi3ValueReference requiredIntermediateVariables[], + size_t nRequiredIntermediateVariables, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3IntermediateUpdateCallback intermediateUpdate) +{ + + UNUSED(visible); + UNUSED(requiredIntermediateVariables); + UNUSED(nRequiredIntermediateVariables); + +#ifndef EVENT_UPDATE + if (eventModeUsed) { + if (logMessage) { + logMessage(instanceEnvironment, fmi3Error, "error", "Event Mode is not supported."); + } + return NULL; + } +#endif + + ModelInstance *instance = createModelInstance( + (loggerType) logMessage, + (intermediateUpdateType) intermediateUpdate, + instanceEnvironment, + instanceName, + instantiationToken, + resourcePath, + loggingOn, + CoSimulation); + + if (instance) { + instance->earlyReturnAllowed = earlyReturnAllowed; + instance->eventModeUsed = eventModeUsed; + instance->state = Instantiated; + } + + return instance; +} + +fmi3Instance fmi3InstantiateScheduledExecution( + fmi3String instanceName, + fmi3String instantiationToken, + fmi3String resourcePath, + fmi3Boolean visible, + fmi3Boolean loggingOn, + fmi3InstanceEnvironment instanceEnvironment, + fmi3LogMessageCallback logMessage, + fmi3ClockUpdateCallback clockUpdate, + fmi3LockPreemptionCallback lockPreemption, + fmi3UnlockPreemptionCallback unlockPreemption) +{ + + UNUSED(visible); + +#ifndef SCHEDULED_CO_SIMULATION + + UNUSED(instanceName); + UNUSED(instantiationToken); + UNUSED(resourcePath); + UNUSED(loggingOn); + UNUSED(instanceEnvironment); + UNUSED(logMessage); + UNUSED(clockUpdate); + UNUSED(lockPreemption); + UNUSED(unlockPreemption); + + return NULL; +#else + ModelInstance *instance = createModelInstance( + (loggerType) logMessage, + NULL, + instanceEnvironment, + instanceName, + instantiationToken, + resourcePath, + loggingOn, + ScheduledExecution); + + if (instance) { + instance->state = Instantiated; + instance->clockUpdate = clockUpdate; + instance->lockPreemtion = lockPreemption; + instance->unlockPreemtion = unlockPreemption; + } + + return instance; +#endif +} + +void fmi3FreeInstance(fmi3Instance instance) +{ + + if (!instance) + return; + + freeModelInstance((ModelInstance *) instance); +} + +fmi3Status fmi3EnterInitializationMode(fmi3Instance instance, + fmi3Boolean toleranceDefined, + fmi3Float64 tolerance, + fmi3Float64 startTime, + fmi3Boolean stopTimeDefined, + fmi3Float64 stopTime) +{ + + UNUSED(toleranceDefined); + UNUSED(tolerance); + UNUSED(stopTimeDefined); + UNUSED(stopTime); + + ASSERT_STATE(EnterInitializationMode); + + S->startTime = startTime; + S->time = startTime; + S->state = InitializationMode; + + return fmi3OK; +} + +fmi3Status fmi3ExitInitializationMode(fmi3Instance instance) +{ + + ASSERT_STATE(ExitInitializationMode); + + fmi3Status status = fmi3OK; + + // if values were set and no fmi3GetXXX triggered update before, + // ensure calculated values are updated now + if (S->isDirtyValues) { + + status = (fmi3Status) calculateValues(S); + + if (status > fmi3Warning) { + return status; + } + + S->isDirtyValues = false; + } + + switch (S->type) { + case ModelExchange: + S->state = EventMode; + break; + case CoSimulation: + S->state = S->eventModeUsed ? EventMode : StepMode; + break; + case ScheduledExecution: + S->state = ClockActivationMode; + break; + } + +#if NZ > 0 + // initialize event indicators + getEventIndicators(S, S->z, NZ); +#endif + + return status; +} + +fmi3Status fmi3EnterEventMode(fmi3Instance instance) +{ + + ASSERT_STATE(EnterEventMode); + + S->state = EventMode; + + return fmi3OK; +} + +fmi3Status fmi3Terminate(fmi3Instance instance) +{ + + ASSERT_STATE(Terminate); + + S->state = Terminated; + + return fmi3OK; +} + +fmi3Status fmi3Reset(fmi3Instance instance) +{ + + ASSERT_STATE(Reset); + + reset(S); + + return fmi3OK; +} + +fmi3Status fmi3GetFloat32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetFloat32); + GET_VARIABLES(Float32); +} + +fmi3Status fmi3GetFloat64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetFloat64); + GET_VARIABLES(Float64); +} + +fmi3Status fmi3GetInt8(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int8 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetInt8); + GET_VARIABLES(Int8); +} + +fmi3Status fmi3GetUInt8(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt8 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetUInt8); + GET_VARIABLES(UInt8); +} + +fmi3Status fmi3GetInt16(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int16 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetInt16); + GET_VARIABLES(Int16); +} + +fmi3Status fmi3GetUInt16(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt16 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetUInt16); + GET_VARIABLES(UInt16); +} + +fmi3Status fmi3GetInt32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetInt32); + GET_VARIABLES(Int32); +} + +fmi3Status fmi3GetUInt32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetUInt32); + GET_VARIABLES(UInt32); +} + +fmi3Status fmi3GetInt64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Int64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetInt64); + GET_VARIABLES(Int64); +} + +fmi3Status fmi3GetUInt64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetUInt64); + GET_VARIABLES(UInt64); +} + +fmi3Status fmi3GetBoolean(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Boolean values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetBoolean); + GET_VARIABLES(Boolean); +} + +fmi3Status fmi3GetString(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3String values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(GetString); + GET_VARIABLES(String); +} + +fmi3Status fmi3GetBinary(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + size_t valueSizes[], + fmi3Binary values[], + size_t nValues) +{ + + UNUSED(nValues); + + ASSERT_STATE(GetBinary); + + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + size_t index = 0; + Status s = getBinary(S, (ValueReference) valueReferences[i], valueSizes, (const char **) values, &index); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + } + + return (fmi3Status) status; +} + +fmi3Status fmi3GetClock(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Clock values[]) +{ + + ASSERT_STATE(GetClock); + + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + Status s = getClock(instance, (ValueReference) valueReferences[i], &values[i]); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + } + + return (fmi3Status) status; +} + +fmi3Status fmi3SetFloat32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetFloat32); + SET_VARIABLES(Float32); +} + +fmi3Status fmi3SetFloat64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetFloat64); + SET_VARIABLES(Float64); +} + +fmi3Status fmi3SetInt8(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int8 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetInt8); + SET_VARIABLES(Int8); +} + +fmi3Status fmi3SetUInt8(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt8 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetUInt8); + SET_VARIABLES(UInt8); +} + +fmi3Status fmi3SetInt16(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int16 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetInt16); + SET_VARIABLES(Int16); +} + +fmi3Status fmi3SetUInt16(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt16 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetUInt16); + SET_VARIABLES(UInt16); +} + +fmi3Status fmi3SetInt32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetInt32); + SET_VARIABLES(Int32); +} + +fmi3Status fmi3SetUInt32(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt32 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetUInt32); + SET_VARIABLES(UInt32); +} + +fmi3Status fmi3SetInt64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetInt64); + SET_VARIABLES(Int64); +} + +fmi3Status fmi3SetUInt64(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetUInt64); + SET_VARIABLES(UInt64); +} + +fmi3Status fmi3SetBoolean(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Boolean values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetBoolean); + SET_VARIABLES(Boolean); +} + +fmi3Status fmi3SetString(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3String values[], + size_t nValues) +{ + + UNUSED(nValues); + ASSERT_STATE(SetString); + SET_VARIABLES(String); +} + +fmi3Status fmi3SetBinary(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const size_t valueSizes[], + const fmi3Binary values[], + size_t nValues) +{ + + UNUSED(nValues); + + ASSERT_STATE(SetBinary); + + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + size_t index = 0; + Status s = setBinary(S, (ValueReference) valueReferences[i], valueSizes, (const char *const *) values, &index); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + } + + return (fmi3Status) status; +} + +fmi3Status fmi3SetClock(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Clock values[]) +{ + + ASSERT_STATE(SetClock); + + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + if (values[i]) { + Status s = activateClock(instance, (ValueReference) valueReferences[i]); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + } + } + + return (fmi3Status) status; +} + +fmi3Status fmi3GetNumberOfVariableDependencies(fmi3Instance instance, + fmi3ValueReference valueReference, + size_t *nDependencies) +{ + UNUSED(valueReference); + UNUSED(nDependencies); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3GetVariableDependencies(fmi3Instance instance, + fmi3ValueReference dependent, + size_t elementIndicesOfDependent[], + fmi3ValueReference independents[], + size_t elementIndicesOfIndependents[], + fmi3DependencyKind dependencyKinds[], + size_t nDependencies) +{ + + UNUSED(dependent); + UNUSED(elementIndicesOfDependent); + UNUSED(independents); + UNUSED(elementIndicesOfIndependents); + UNUSED(dependencyKinds); + UNUSED(nDependencies); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3GetFMUState(fmi3Instance instance, fmi3FMUState *FMUState) +{ + + ASSERT_STATE(GetFMUState); + + *FMUState = getFMUState(S); + + return fmi3OK; +} + +fmi3Status fmi3SetFMUState(fmi3Instance instance, fmi3FMUState FMUState) +{ + + ASSERT_STATE(SetFMUState); + + if (nullPointer(S, "fmi3SetFMUState", "FMUState", FMUState)) { + return fmi3Error; + } + + setFMUState(S, FMUState); + + return fmi3OK; +} + +fmi3Status fmi3FreeFMUState(fmi3Instance instance, fmi3FMUState *FMUState) +{ + + ASSERT_STATE(FreeFMUState); + + free(*FMUState); + + *FMUState = NULL; + + return fmi3OK; +} + +fmi3Status fmi3SerializedFMUStateSize(fmi3Instance instance, + fmi3FMUState FMUState, + size_t *size) +{ + + UNUSED(instance); + UNUSED(FMUState); + + ASSERT_STATE(SerializedFMUStateSize); + + *size = sizeof(ModelInstance); + + return fmi3OK; +} + +fmi3Status fmi3SerializeFMUState(fmi3Instance instance, + fmi3FMUState FMUState, + fmi3Byte serializedState[], + size_t size) +{ + + ASSERT_STATE(SerializeFMUState); + + if (nullPointer(S, "fmi3SerializeFMUState", "FMUstate", FMUState)) { + return fmi3Error; + } + + if (invalidNumber(S, "fmi3SerializeFMUState", "size", size, sizeof(ModelInstance))) { + return fmi3Error; + } + + memcpy(serializedState, FMUState, sizeof(ModelInstance)); + + return fmi3OK; +} + +fmi3Status fmi3DeserializeFMUState(fmi3Instance instance, + const fmi3Byte serializedState[], + size_t size, + fmi3FMUState *FMUState) +{ + + ASSERT_STATE(DeserializeFMUState); + + if (invalidNumber(S, "fmi3DeserializeFMUState", "size", size, sizeof(ModelInstance))) { + return fmi3Error; + } + + if (*FMUState == NULL) { + *FMUState = calloc(1, sizeof(ModelInstance)); + } + + memcpy(*FMUState, serializedState, sizeof(ModelInstance)); + + return fmi3OK; +} + +fmi3Status fmi3GetDirectionalDerivative(fmi3Instance instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity) +{ + + UNUSED(nSeed); + UNUSED(nSensitivity); + + ASSERT_STATE(GetDirectionalDerivative); + + // TODO: check value references + // TODO: assert nUnknowns == nDeltaOfUnknowns + // TODO: assert nKnowns == nDeltaKnowns + + Status status = OK; + + for (size_t i = 0; i < nUnknowns; i++) { + sensitivity[i] = 0; + for (size_t j = 0; j < nKnowns; j++) { + double partialDerivative = 0; + Status s = getPartialDerivative(S, (ValueReference) unknowns[i], (ValueReference) knowns[j], &partialDerivative); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + sensitivity[i] += partialDerivative * seed[j]; + } + } + + return fmi3OK; +} + +fmi3Status fmi3GetAdjointDerivative(fmi3Instance instance, + const fmi3ValueReference unknowns[], + size_t nUnknowns, + const fmi3ValueReference knowns[], + size_t nKnowns, + const fmi3Float64 seed[], + size_t nSeed, + fmi3Float64 sensitivity[], + size_t nSensitivity) +{ + + UNUSED(nSeed); + UNUSED(nSensitivity); + + ASSERT_STATE(GetAdjointDerivative); + + // TODO: check value references + + Status status = OK; + + for (size_t i = 0; i < nKnowns; i++) { + sensitivity[i] = 0; + for (size_t j = 0; j < nUnknowns; j++) { + double partialDerivative = 0; + Status s = getPartialDerivative(S, (ValueReference) unknowns[j], (ValueReference) knowns[i], &partialDerivative); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + sensitivity[i] += partialDerivative * seed[j]; + } + } + + return fmi3OK; +} + +fmi3Status fmi3EnterConfigurationMode(fmi3Instance instance) +{ + + ASSERT_STATE(EnterConfigurationMode); + + S->state = (S->state == Instantiated) ? ConfigurationMode : ReconfigurationMode; + + return fmi3OK; +} + +fmi3Status fmi3ExitConfigurationMode(fmi3Instance instance) +{ + + ASSERT_STATE(ExitConfigurationMode); + + if (S->state == ConfigurationMode) { + S->state = Instantiated; + } else { + switch (S->type) { + case ModelExchange: + S->state = EventMode; + break; + case CoSimulation: + S->state = StepMode; + break; + case ScheduledExecution: + S->state = ClockActivationMode; + break; + } + } + + return fmi3OK; +} + +fmi3Status fmi3GetIntervalDecimal(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 intervals[], + fmi3IntervalQualifier qualifiers[]) +{ + + ASSERT_STATE(GetIntervalDecimal); + + // ? Check nValueReferences != nValues + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + Status s = getInterval(instance, (ValueReference) valueReferences[i], &intervals[i], (int *) &qualifiers[i]); + status = max(status, s); + if (status > Warning) + return (fmi3Status) status; + } + + return (fmi3Status) status; +} + +fmi3Status fmi3GetIntervalFraction(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 intervalCounters[], + fmi3UInt64 resolutions[], + fmi3IntervalQualifier qualifiers[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(intervalCounters); + UNUSED(resolutions); + UNUSED(qualifiers); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3GetShiftDecimal(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3Float64 shifts[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(shifts); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3GetShiftFraction(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + fmi3UInt64 shiftCounters[], + fmi3UInt64 resolutions[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(shiftCounters); + UNUSED(resolutions); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3SetIntervalDecimal(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 intervals[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(intervals); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3SetIntervalFraction(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 intervalCounters[], + const fmi3UInt64 resolutions[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(intervalCounters); + UNUSED(resolutions); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3SetShiftDecimal(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Float64 shifts[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(shifts); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3SetShiftFraction(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3UInt64 shiftCounters[], + const fmi3UInt64 resolutions[]) +{ + + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(shiftCounters); + UNUSED(resolutions); + + NOT_IMPLEMENTED; +} + +fmi3Status fmi3EvaluateDiscreteStates(fmi3Instance instance) +{ + NOT_IMPLEMENTED; +} + +fmi3Status fmi3UpdateDiscreteStates(fmi3Instance instance, + fmi3Boolean *discreteStatesNeedUpdate, + fmi3Boolean *terminateSimulation, + fmi3Boolean *nominalsOfContinuousStatesChanged, + fmi3Boolean *valuesOfContinuousStatesChanged, + fmi3Boolean *nextEventTimeDefined, + fmi3Float64 *nextEventTime) +{ + + ASSERT_STATE(NewDiscreteStates); + +#ifdef EVENT_UPDATE + eventUpdate(S); +#endif + + // copy internal eventInfo of component to output arguments + if (discreteStatesNeedUpdate) + *discreteStatesNeedUpdate = S->newDiscreteStatesNeeded; + if (terminateSimulation) + *terminateSimulation = S->terminateSimulation; + if (nominalsOfContinuousStatesChanged) + *nominalsOfContinuousStatesChanged = S->nominalsOfContinuousStatesChanged; + if (valuesOfContinuousStatesChanged) + *valuesOfContinuousStatesChanged = S->valuesOfContinuousStatesChanged; + if (nextEventTimeDefined) + *nextEventTimeDefined = S->nextEventTimeDefined; + if (nextEventTime) + *nextEventTime = S->nextEventTime; + + return fmi3OK; +} + +/*************************************************** + Functions for Model Exchange + ****************************************************/ + +fmi3Status fmi3EnterContinuousTimeMode(fmi3Instance instance) +{ + + ASSERT_STATE(EnterContinuousTimeMode); + + S->state = ContinuousTimeMode; + + return fmi3OK; +} + +fmi3Status fmi3CompletedIntegratorStep(fmi3Instance instance, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *enterEventMode, + fmi3Boolean *terminateSimulation) +{ + + UNUSED(noSetFMUStatePriorToCurrentPoint); + + ASSERT_STATE(CompletedIntegratorStep); + + ASSERT_NOT_NULL(enterEventMode); + ASSERT_NOT_NULL(terminateSimulation); + + *enterEventMode = fmi3False; + *terminateSimulation = fmi3False; + + return fmi3OK; +} + +/* Providing independent variables and re-initialization of caching */ +fmi3Status fmi3SetTime(fmi3Instance instance, fmi3Float64 time) +{ + + ASSERT_STATE(SetTime); + + S->time = time; + + return fmi3OK; +} + +fmi3Status fmi3SetContinuousStates(fmi3Instance instance, + const fmi3Float64 continuousStates[], + size_t nContinuousStates) +{ + + ASSERT_STATE(SetContinuousStates); + + if (invalidNumber(S, "fmi3SetContinuousStates", "nContinuousStates", nContinuousStates, NX)) + return fmi3Error; + + ASSERT_NOT_NULL(continuousStates); + + setContinuousStates(S, continuousStates, nContinuousStates); + + return fmi3OK; +} + +/* Evaluation of the model equations */ +fmi3Status fmi3GetContinuousStateDerivatives(fmi3Instance instance, + fmi3Float64 derivatives[], + size_t nContinuousStates) +{ + + ASSERT_STATE(GetContinuousStateDerivatives); + + if (invalidNumber(S, "fmi3GetContinuousStateDerivatives", "nContinuousStates", nContinuousStates, NX)) + return fmi3Error; + + if (nullPointer(S, "fmi3GetContinuousStateDerivatives", "derivatives[]", derivatives)) + return fmi3Error; + + getDerivatives(S, derivatives, nContinuousStates); + + return fmi3OK; +} + +fmi3Status fmi3GetEventIndicators(fmi3Instance instance, + fmi3Float64 eventIndicators[], + size_t nEventIndicators) +{ + + ASSERT_STATE(GetEventIndicators); + +#if NZ > 0 + if (invalidNumber(S, "fmi3GetEventIndicators", "nEventIndicators", nEventIndicators, NZ)) { + return fmi3Error; + } + + getEventIndicators(S, eventIndicators, nEventIndicators); +#else + + UNUSED(eventIndicators); + + if (nEventIndicators > 0) { + // TODO: log error + return fmi3Error; + } +#endif + + return fmi3OK; +} + +fmi3Status fmi3GetContinuousStates(fmi3Instance instance, + fmi3Float64 continuousStates[], + size_t nContinuousStates) +{ + + ASSERT_STATE(GetContinuousStates); + + if (invalidNumber(S, "fmi3GetContinuousStates", "nContinuousStates", nContinuousStates, NX)) + return fmi3Error; + + if (nullPointer(S, "fmi3GetContinuousStates", "continuousStates[]", continuousStates)) + return fmi3Error; + + getContinuousStates(S, continuousStates, nContinuousStates); + + return fmi3OK; +} + +fmi3Status fmi3GetNominalsOfContinuousStates(fmi3Instance instance, + fmi3Float64 nominals[], + size_t nContinuousStates) +{ + + ASSERT_STATE(GetNominalsOfContinuousStates); + + if (invalidNumber(S, "fmi3GetNominalContinuousStates", "nContinuousStates", nContinuousStates, NX)) + return fmi3Error; + + if (nullPointer(S, "fmi3GetNominalContinuousStates", "nominals[]", nominals)) + return fmi3Error; + + for (size_t i = 0; i < nContinuousStates; i++) { + nominals[i] = 1; + } + + return fmi3OK; +} + +fmi3Status fmi3GetNumberOfEventIndicators(fmi3Instance instance, + size_t *nEventIndicators) +{ + + ASSERT_STATE(GetNumberOfEventIndicators); + + ASSERT_NOT_NULL(nEventIndicators); + + *nEventIndicators = NZ; + + return fmi3OK; +} + +fmi3Status fmi3GetNumberOfContinuousStates(fmi3Instance instance, + size_t *nContinuousStates) +{ + + ASSERT_STATE(GetNumberOfContinuousStates); + + ASSERT_NOT_NULL(nContinuousStates); + + *nContinuousStates = NX; + + return fmi3OK; +} + +/*************************************************** + Functions for Co-Simulation + ****************************************************/ + +fmi3Status fmi3EnterStepMode(fmi3Instance instance) +{ + + ASSERT_STATE(EnterStepMode); + + S->state = StepMode; + + return fmi3OK; +} + +fmi3Status fmi3GetOutputDerivatives(fmi3Instance instance, + const fmi3ValueReference valueReferences[], + size_t nValueReferences, + const fmi3Int32 orders[], + fmi3Float64 values[], + size_t nValues) +{ + + UNUSED(nValues); + + ASSERT_STATE(GetOutputDerivatives); + +#ifdef GET_OUTPUT_DERIVATIVE + + Status status = OK; + + for (size_t i = 0; i < nValueReferences; i++) { + const Status s = getOutputDerivative(S, (ValueReference) valueReferences[i], orders[i], &values[i]); + status = max(status, s); + if (status > Warning) { + return (fmi3Status) status; + } + } + + return (fmi3Status) status; + +#else + UNUSED(valueReferences); + UNUSED(nValueReferences); + UNUSED(orders); + UNUSED(values); + + NOT_IMPLEMENTED; +#endif +} + +fmi3Status fmi3DoStep(fmi3Instance instance, + fmi3Float64 currentCommunicationPoint, + fmi3Float64 communicationStepSize, + fmi3Boolean noSetFMUStatePriorToCurrentPoint, + fmi3Boolean *eventHandlingNeeded, + fmi3Boolean *terminateSimulation, + fmi3Boolean *earlyReturn, + fmi3Float64 *lastSuccessfulTime) +{ + + UNUSED(noSetFMUStatePriorToCurrentPoint); + + ASSERT_STATE(DoStep); + + if (communicationStepSize <= 0) { + logError(S, "fmi3DoStep: communication step size must be > 0 but was %g.", communicationStepSize); + S->state = modelError; + return fmi3Error; + } + + const fmi3Float64 nextCommunicationPoint = currentCommunicationPoint + communicationStepSize + EPSILON; + + S->solverStepSize = communicationStepSize; + + fmi3Boolean nextCommunicationPointReached; + + *eventHandlingNeeded = fmi3False; + + while (true) { + + nextCommunicationPointReached = S->time + S->solverStepSize > nextCommunicationPoint; + + if (nextCommunicationPointReached) { + break; + } + + bool stateEvent, timeEvent; + + doAlphaStep(S, &stateEvent, &timeEvent); + +#ifdef EVENT_UPDATE + if (stateEvent || timeEvent) { + + *eventHandlingNeeded = fmi3True; + + if (S->eventModeUsed) { + break; + } + + eventUpdate(S); + + if (S->earlyReturnAllowed) { + break; + } + } +#endif + } + + *earlyReturn = !nextCommunicationPointReached; + + *terminateSimulation = fmi3False; + + *lastSuccessfulTime = S->time; + + return fmi3OK; +} + +fmi3Status fmi3ActivateModelPartition(fmi3Instance instance, + fmi3ValueReference clockReference, + fmi3Float64 activationTime) +{ + + ASSERT_STATE(ActivateModelPartition); + + return (fmi3Status) activateModelPartition(S, (ValueReference) clockReference, activationTime); +} diff --git a/oscillator/solver-fmi/fmu/thirdparty/LICENSE.txt b/oscillator/solver-fmi/fmu/thirdparty/LICENSE.txt new file mode 100644 index 000000000..d2ff5fb89 --- /dev/null +++ b/oscillator/solver-fmi/fmu/thirdparty/LICENSE.txt @@ -0,0 +1,148 @@ +Copyright (c) 2022, Modelica Association Project "FMI". +All rights reserved. + +The Reference FMUs and FMUSim are released under the 2-Clause BSD license: + +-------------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIEDi +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- + +The Reference FMUs are a fork of the Test FMUs (https://github.com/CATIA-Systems/Test-FMUs) +by Dassault Systemes, which are a fork of the FMU SDK (https://github.com/qtronic/fmusdk) +by QTronic, both released under the 2-Clause BSD License. + +FMUSim uses the following third party libraries. + +================================================================================ + +Libxml2 (https://gitlab.gnome.org/GNOME/libxml2) released under the MIT license: + +Except where otherwise noted in the source code (e.g. the files hash.c, +list.c and the trio files, which are covered by a similar licence but +with different Copyright notices) all the files are: + + Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is fur- +nished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- +NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +================================================================================ + +Zlib (http://zlib.net/) release under the zlib license: + +Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +Jean-loup Gailly Mark Adler +jloup@gzip.org madler@alumni.caltech.edu + +================================================================================ + +CSV-fast-reader (https://github.com/jandoczy/csv-fast-reader) release under the +MIT license: + +Copyright (c) 2019 Jan Doczy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +================================================================================ + +SUNDIALS: SUite of Nonlinear and DIfferential/ALgebraic equation Solvers +(https://computing.llnl.gov/projects/sundials) release under the BSD 3-Clause license: + +Copyright (c) 2002-2022, Lawrence Livermore National Security and Southern Methodist University. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +The FMI header files are copyright (c) 2008-2011 MODELISAR consortium, 2012-2022 +the Modelica Association Project "FMI" and released under the 2-Clause BSD License. diff --git a/oscillator/solver-python/oscillator.py b/oscillator/solver-python/oscillator.py new file mode 100644 index 000000000..bf1d6be08 --- /dev/null +++ b/oscillator/solver-python/oscillator.py @@ -0,0 +1,200 @@ +from __future__ import division + +import argparse +import numpy as np +from numpy.linalg import eig +import precice +from enum import Enum +import csv +import os + +import problemDefinition +import timeSteppers + + +class Participant(Enum): + MASS_LEFT = "Mass-Left" + MASS_RIGHT = "Mass-Right" + + +parser = argparse.ArgumentParser() +parser.add_argument("participantName", help="Name of the solver.", type=str, choices=[p.value for p in Participant]) +parser.add_argument( + "-ts", + "--time-stepping", + help="Time stepping scheme being used.", + type=str, + choices=[ + s.value for s in timeSteppers.TimeSteppingSchemes], + default=timeSteppers.TimeSteppingSchemes.NEWMARK_BETA.value) +args = parser.parse_args() + +participant_name = args.participantName + +if participant_name == Participant.MASS_LEFT.value: + write_data_name = 'Force-Left' + read_data_name = 'Force-Right' + mesh_name = 'Mass-Left-Mesh' + + this_mass = problemDefinition.MassLeft + this_spring = problemDefinition.SpringLeft + connecting_spring = problemDefinition.SpringMiddle + other_mass = problemDefinition.MassRight + +elif participant_name == Participant.MASS_RIGHT.value: + read_data_name = 'Force-Left' + write_data_name = 'Force-Right' + mesh_name = 'Mass-Right-Mesh' + + this_mass = problemDefinition.MassRight + this_spring = problemDefinition.SpringRight + connecting_spring = problemDefinition.SpringMiddle + other_mass = problemDefinition.MassLeft + +else: + raise Exception(f"wrong participant name: {participant_name}") + +mass = this_mass.m +stiffness = this_spring.k + connecting_spring.k +u0, v0, f0, d_dt_f0 = this_mass.u0, this_mass.v0, connecting_spring.k * other_mass.u0, connecting_spring.k * other_mass.v0 + +num_vertices = 1 # Number of vertices + +solver_process_index = 0 +solver_process_size = 1 + +configuration_file_name = "../precice-config.xml" + +participant = precice.Participant(participant_name, configuration_file_name, solver_process_index, solver_process_size) + +dimensions = participant.get_mesh_dimensions(mesh_name) + +vertex = np.zeros(dimensions) +read_data = np.zeros(num_vertices) +write_data = connecting_spring.k * u0 * np.ones(num_vertices) + +vertex_ids = [participant.set_mesh_vertex(mesh_name, vertex)] + +if participant.requires_initial_data(): + participant.write_data(mesh_name, write_data_name, vertex_ids, write_data) + +participant.initialize() +precice_dt = participant.get_max_time_step_size() +my_dt = precice_dt / 4 # use my_dt < precice_dt for subcycling + +# Initial Conditions +a0 = (f0 - stiffness * u0) / mass +u = u0 +v = v0 +a = a0 +t = 0 + +if args.time_stepping == timeSteppers.TimeSteppingSchemes.GENERALIZED_ALPHA.value: + time_stepper = timeSteppers.GeneralizedAlpha(stiffness=stiffness, mass=mass, alpha_f=0.4, alpha_m=0.2) +elif args.time_stepping == timeSteppers.TimeSteppingSchemes.NEWMARK_BETA.value: + time_stepper = timeSteppers.GeneralizedAlpha(stiffness=stiffness, mass=mass, alpha_f=0.0, alpha_m=0.0) +elif args.time_stepping == timeSteppers.TimeSteppingSchemes.RUNGE_KUTTA_4.value: + ode_system = np.array([ + [0, 1], # du + [-stiffness / mass, 0], # dv + ]) + time_stepper = timeSteppers.RungeKutta4(ode_system=ode_system) +elif args.time_stepping == timeSteppers.TimeSteppingSchemes.Radau_IIA.value: + ode_system = np.array([ + [0, 1], # du + [-stiffness / mass, 0], # dv + ]) + time_stepper = timeSteppers.RadauIIA(ode_system=ode_system) +else: + raise Exception( + f"Invalid time stepping scheme {args.time_stepping}. Please use one of {[ts.value for ts in timeSteppers.TimeSteppingSchemes]}") + + +positions = [] +velocities = [] +times = [] + +u_write = [u] +v_write = [v] +t_write = [t] + +while participant.is_coupling_ongoing(): + if participant.requires_writing_checkpoint(): + u_cp = u + v_cp = v + a_cp = a + t_cp = t + # store data for plotting and postprocessing + positions += u_write + velocities += v_write + times += t_write + + # compute time step size for this time step + precice_dt = participant.get_max_time_step_size() + dt = np.min([precice_dt, my_dt]) + + read_times = time_stepper.rhs_eval_points(dt) + f = len(read_times) * [None] + + for i in range(len(read_times)): + read_data = participant.read_data(mesh_name, read_data_name, vertex_ids, read_times[i]) + f[i] = read_data[0] + + # do generalized alpha step + u_new, v_new, a_new = time_stepper.do_step(u, v, a, f, dt) + t_new = t + dt + + write_data = [connecting_spring.k * u_new] + + participant.write_data(mesh_name, write_data_name, vertex_ids, write_data) + + participant.advance(dt) + + if participant.requires_reading_checkpoint(): + u = u_cp + v = v_cp + a = a_cp + t = t_cp + # empty buffers for next window + u_write = [] + v_write = [] + t_write = [] + + else: + u = u_new + v = v_new + a = a_new + t = t_new + + # write data to buffers + u_write.append(u) + v_write.append(v) + t_write.append(t) + +# store final result +u = u_new +v = v_new +a = a_new +u_write.append(u) +v_write.append(v) +t_write.append(t) +positions += u_write +velocities += v_write +times += t_write + +participant.finalize() + +# print errors +error = np.max(abs(this_mass.u_analytical(np.array(times)) - np.array(positions))) +print("Error w.r.t analytical solution:") +print(f"{my_dt},{error}") + +# output trajectory +if not os.path.exists("output"): + os.makedirs("output") + +with open(f'output/trajectory-{participant_name}.csv', 'w') as file: + csv_write = csv.writer(file, delimiter=';') + csv_write.writerow(['time', 'position', 'velocity']) + for t, u, v in zip(times, positions, velocities): + csv_write.writerow([t, u, v]) diff --git a/oscillator/solver-python/problemDefinition.py b/oscillator/solver-python/problemDefinition.py new file mode 100644 index 000000000..b0ac2aea3 --- /dev/null +++ b/oscillator/solver-python/problemDefinition.py @@ -0,0 +1,68 @@ +import numpy as np +from numpy.linalg import eig + + +class SpringLeft: + k = 4 * np.pi**2 + + +class SpringMiddle: + k = 16 * (np.pi**2) + + +class SpringRight: + k = 4 * np.pi**2 + + +class MassLeft: + # mass + m = 1 + + # initial conditions (the way how we currently compute the analytical + # solution allows arbitrary u0, but requires v0 = 0) + u0 = 1.0 + v0 = 0.0 + + u_analytical, v_analytical = None, None # will be defined below + + +class MassRight: + # mass + m = 1 + + # initial conditions (the way how we currently compute the analytical + # solution allows arbitrary u0, but requires v0 = 0) + u0 = 0.0 + v0 = 0.0 + + u_analytical, v_analytical = None, None # will be defined below + + +# Mass matrix +M = np.array([ + [MassLeft.m, 0], + [0, MassRight.m] +]) +# Stiffness matrix +K = np.array([ + [SpringLeft.k + SpringMiddle.k, -SpringMiddle.k], + [-SpringMiddle.k, SpringRight.k + SpringMiddle.k] +]) + +# system: +# m ddu + k u = f +# compute analytical solution from eigenvalue ansatz + +eigenvalues, eigenvectors = eig(K) +omega = np.sqrt(eigenvalues) +A, B = eigenvectors + +c = np.linalg.solve(eigenvectors, [MassLeft.u0, MassRight.u0]) + +MassLeft.u_analytical = lambda t: c[0] * A[0] * np.cos(omega[0] * t) + c[1] * A[1] * np.cos(omega[1] * t) +MassLeft.v_analytical = lambda t: -c[0] * A[0] * omega[0] * \ + np.sin(omega[0] * t) - c[1] * A[1] * omega[1] * np.sin(omega[1] * t) + +MassRight.u_analytical = lambda t: c[0] * B[0] * np.cos(omega[0] * t) + c[1] * B[1] * np.cos(omega[1] * t) +MassRight.v_analytical = lambda t: -c[0] * B[0] * omega[0] * \ + np.sin(omega[0] * t) - c[1] * B[1] * omega[1] * np.sin(omega[1] * t) diff --git a/oscillator/solver-python/timeSteppers.py b/oscillator/solver-python/timeSteppers.py new file mode 100644 index 000000000..b82f3bc78 --- /dev/null +++ b/oscillator/solver-python/timeSteppers.py @@ -0,0 +1,159 @@ +from typing import Tuple, List +import numpy as np +import numbers +import scipy as sp +from enum import Enum + + +class TimeSteppingSchemes(Enum): + NEWMARK_BETA = "Newmark_beta" + GENERALIZED_ALPHA = "generalized_alpha" + RUNGE_KUTTA_4 = "runge_kutta_4" + Radau_IIA = "radauIIA" # 5th order implicit + + +class GeneralizedAlpha(): + alpha_f = None + alpha_m = None + gamma = None + beta = None + mass = None + stiffness = None + + def __init__(self, stiffness, mass, alpha_f=0.4, alpha_m=0.2) -> None: + self.alpha_f = alpha_f + self.alpha_m = alpha_m + + self.gamma = 0.5 - self.alpha_m + self.alpha_f + self.beta = 0.25 * (self.gamma + 0.5) + + self.stiffness = stiffness + self.mass = mass + + def rhs_eval_points(self, dt) -> List[float]: + return [(1 - self.alpha_f) * dt] + + def do_step(self, u, v, a, f, dt) -> Tuple[float, float, float]: + if isinstance(f, list): # if f is list, turn it into a number + f = f[0] + + m = 3 * [None] + m[0] = (1 - self.alpha_m) / (self.beta * dt**2) + m[1] = (1 - self.alpha_m) / (self.beta * dt) + m[2] = (1 - self.alpha_m - 2 * self.beta) / (2 * self.beta) + + k_bar = self.stiffness * (1 - self.alpha_f) + m[0] * self.mass + + # do generalized alpha step + if (type(self.stiffness)) is np.ndarray: + u_new = np.linalg.solve( + k_bar, + (f - self.alpha_f * self.stiffness.dot(u) + self.mass.dot((m[0] * u + m[1] * v + m[2] * a))) + ) + else: + u_new = (f - self.alpha_f * self.stiffness * u + self.mass * (m[0] * u + m[1] * v + m[2] * a)) / k_bar + + a_new = 1.0 / (self.beta * dt**2) * (u_new - u - dt * v) - (1 - 2 * self.beta) / (2 * self.beta) * a + v_new = v + dt * ((1 - self.gamma) * a + self.gamma * a_new) + + return u_new, v_new, a_new + + +class RungeKutta4(): + a = np.array([[0, 0, 0, 0], + [0.5, 0, 0, 0], + [0, 0.5, 0, 0], + [0, 0, 1.0, 0]]) + b = np.array([1 / 6, 1 / 3, 1 / 3, 1 / 6]) + c = np.array([0, 0.5, 0.5, 1]) + + def __init__(self, ode_system) -> None: + self.ode_system = ode_system + pass + + def rhs_eval_points(self, dt) -> List[float]: + return [self.c[0] * dt, self.c[1] * dt, self.c[2] * dt, self.c[3] * dt] + + def do_step(self, u, v, a, f, dt) -> Tuple[float, float, float]: + assert (isinstance(u, type(v))) + + n_stages = 4 + + if isinstance(f, numbers.Number): # if f is number, assume constant f + f = n_stages * [f] + + if isinstance(u, np.ndarray): + x = np.concatenate([u, v]) + rhs = [np.concatenate([np.array([0, 0]), f[i]]) for i in range(n_stages)] + elif isinstance(u, numbers.Number): + x = np.array([u, v]) + rhs = [np.array([0, f[i]]) for i in range(n_stages)] + else: + raise Exception(f"Cannot handle input type {type(u)} of u and v") + + s = n_stages * [None] + s[0] = self.ode_system.dot(x) + rhs[0] + s[1] = self.ode_system.dot(x + self.a[1, 0] * s[0] * dt) + rhs[1] + s[2] = self.ode_system.dot(x + self.a[2, 1] * s[1] * dt) + rhs[2] + s[3] = self.ode_system.dot(x + self.a[3, 2] * s[2] * dt) + rhs[3] + + x_new = x + + for i in range(n_stages): + x_new += dt * self.b[i] * s[i] + + if isinstance(u, np.ndarray): + u_new = x_new[0:2] + v_new = x_new[2:4] + elif isinstance(u, numbers.Number): + u_new = x_new[0] + v_new = x_new[1] + + a_new = None + + return u_new, v_new, a_new + + +class RadauIIA(): + def __init__(self, ode_system) -> None: + self.ode_system = ode_system + pass + + def rhs_eval_points(self, dt) -> List[float]: + return np.linspace(0, dt, 5) # will create an interpolant from this later + + def do_step(self, u, v, a, f, dt) -> Tuple[float, float, float]: + from brot.interpolation import do_lagrange_interpolation + + ts = self.rhs_eval_points(dt) + + t0 = 0 + + assert (isinstance(u, type(v))) + + if isinstance(u, np.ndarray): + x0 = np.concatenate([u, v]) + f = np.array(f) + assert (u.shape[0] == f.shape[1]) + def rhs_fun(t, x): return np.concatenate([np.array([np.zeros_like(t), np.zeros_like(t)]), [ + do_lagrange_interpolation(t, ts, f[:, i]) for i in range(u.shape[0])]]) + elif isinstance(u, numbers.Number): + x0 = np.array([u, v]) + def rhs_fun(t, x): return np.array([np.zeros_like(t), do_lagrange_interpolation(t, ts, f)]) + else: + raise Exception(f"Cannot handle input type {type(u)} of u and v") + + def fun(t, x): + return self.ode_system.dot(x) + rhs_fun(t, x) + + # use large rtol and atol to circumvent error control. + ret = sp.integrate.solve_ivp(fun, [t0, t0 + dt], x0, method="Radau", + first_step=dt, max_step=dt, rtol=10e10, atol=10e10) + + a_new = None + if isinstance(u, np.ndarray): + u_new, v_new = ret.y[0:2, -1], ret.y[2:4, -1] + elif isinstance(u, numbers.Number): + u_new, v_new = ret.y[:, -1] + + return u_new, v_new, a_new diff --git a/partitioned-backwards-facing-step/README.md b/partitioned-backwards-facing-step/README.md new file mode 100644 index 000000000..05e035732 --- /dev/null +++ b/partitioned-backwards-facing-step/README.md @@ -0,0 +1,60 @@ +--- +title: Partitioned flow over a backwards facing step +permalink: tutorials-partitioned-backwards-facing-step.html +keywords: tutorial, FF, fluid-fluid coupling, OpenFOAM, pimpleFoam, inlet-outlet +summary: This tutorial describes how to run a partitioned fluid simulation using the preCICE OpenFOAM adapter with its custom boundary conditions. +--- + +{% note %} +Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/partitioned-backwards-facing-step). Read how in the [tutorials introduction](https://www.precice.org/tutorials.html). +{% endnote %} + +## Setup + +This scenario consists of two incompressible fluid solvers in series. The case is a two-dimensional flow over a backwards facing step. Fluid1 consists of an incoming channel that opens into a bigger one over a sudden step. Fluid2 is the remaining part of the bigger channel, where the flow develops behind the step. The fluid will develop a recirculation region behind the step which will also expand across the coupling interface + +The key point of this tutorial is the demonstration of custom inlet-outlet OpenFOAM boundary conditions for velocity and pressure. These can dynamically switch their behavior according to the underlying flow direction. +The boundary conditions `coupledVelocity` and `coupledPressure` come with the preCICE OpenFOAM adapter and can be set in the corresponding start time dictionaries for velocity and pressure. + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-partitioned-backwards-facing-step-precice-config.png) + +## Available solvers + +* OpenFOAM (pimpleFoam) for both participants. For more information, have a look at the [OpenFOAM adapter documentation](https://www.precice.org/adapter-openfoam-overview.html). + +## Running the Simulation + +Open two separate terminals and start the desired fluid1 and fluid2 participants by calling the respective run script. For example: + +```bash +cd fluid1-openfoam +./run.sh +``` + +and + +```bash +cd fluid2-openfoam +./run.sh +``` + +## Post-processing + +The OpenFOAM solvers generate a `.foam` file each. You can open this file in ParaView. +An example of the visualized expected results at $t=3.0s$ looks as follows: + +![result](images/tutorials-partitioned-backwards-facing-step-results.png) + +We observe that the velocity and pressure values are smooth across the interface. Going through different time steps, we can also see how our inlet-outlet boundary conditions accurately changed behavior when the recirculation travelled inside the coupling interface. + +Plotting the velocity in z-direction over the coupling interface at $t=2.5s$ shows a smooth transition from negative to positive values: + +![result](images/tutorials-partitioned-backwards-facing-step-sampled.png) + +{% disclaimer %} +This offering is not approved or endorsed by OpenCFD Limited, producer and distributor of the OpenFOAM software via www.openfoam.com, and owner of the OPENFOAM® and OpenCFD® trade marks. +{% enddisclaimer %} diff --git a/partitioned-backwards-facing-step/clean-tutorial.sh b/partitioned-backwards-facing-step/clean-tutorial.sh new file mode 120000 index 000000000..4713f5092 --- /dev/null +++ b/partitioned-backwards-facing-step/clean-tutorial.sh @@ -0,0 +1 @@ +../tools/clean-tutorial-base.sh \ No newline at end of file diff --git a/partitioned-backwards-facing-step/fluid1-openfoam/0/U b/partitioned-backwards-facing-step/fluid1-openfoam/0/U new file mode 100644 index 000000000..9fb32bfd3 --- /dev/null +++ b/partitioned-backwards-facing-step/fluid1-openfoam/0/U @@ -0,0 +1,37 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0 0 0); + +boundaryField +{ + fixedWalls + { + type fixedValue; + value uniform (0 0 0); + } + + inlet + { + type fixedValue; + value uniform (0 0 0.1); + } + + cplOutlet + { + type coupledVelocity; + refValue uniform (0 0 0); + } + + frontAndBack + { + type empty; + } +} diff --git a/partitioned-backwards-facing-step/fluid1-openfoam/0/p b/partitioned-backwards-facing-step/fluid1-openfoam/0/p new file mode 100644 index 000000000..abaa9dcae --- /dev/null +++ b/partitioned-backwards-facing-step/fluid1-openfoam/0/p @@ -0,0 +1,34 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p; +} + +dimensions [0 2 -2 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + fixedWalls + { + type zeroGradient; + } + inlet + { + type zeroGradient; + } + + cplOutlet + { + type coupledPressure; + refValue uniform 0; + } + + frontAndBack + { + type empty; + } +} diff --git a/partitioned-backwards-facing-step/fluid1-openfoam/clean.sh b/partitioned-backwards-facing-step/fluid1-openfoam/clean.sh new file mode 100755 index 000000000..aa660ccc2 --- /dev/null +++ b/partitioned-backwards-facing-step/fluid1-openfoam/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . \ No newline at end of file diff --git a/partitioned-backwards-facing-step/fluid1-openfoam/constant/transportProperties b/partitioned-backwards-facing-step/fluid1-openfoam/constant/transportProperties new file mode 100644 index 000000000..19a9f0403 --- /dev/null +++ b/partitioned-backwards-facing-step/fluid1-openfoam/constant/transportProperties @@ -0,0 +1,13 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object transportProperties; +} + +transportModel Newtonian; + + +nu nu [ 0 2 -1 0 0 0 0 ] 0.00001; //Re 100 +//nu nu [ 0 2 -1 0 0 0 0 ] 0.0001; //Re 1000 diff --git a/partitioned-backwards-facing-step/fluid1-openfoam/constant/turbulenceProperties b/partitioned-backwards-facing-step/fluid1-openfoam/constant/turbulenceProperties new file mode 100644 index 000000000..cb924ae6d --- /dev/null +++ b/partitioned-backwards-facing-step/fluid1-openfoam/constant/turbulenceProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object turbulenceProperties; +} + +simulationType laminar; diff --git a/partitioned-backwards-facing-step/fluid1-openfoam/run.sh b/partitioned-backwards-facing-step/fluid1-openfoam/run.sh new file mode 100755 index 000000000..da82a9ba2 --- /dev/null +++ b/partitioned-backwards-facing-step/fluid1-openfoam/run.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/partitioned-backwards-facing-step/fluid1-openfoam/system/blockMeshDict b/partitioned-backwards-facing-step/fluid1-openfoam/system/blockMeshDict new file mode 100644 index 000000000..467c5cdc5 --- /dev/null +++ b/partitioned-backwards-facing-step/fluid1-openfoam/system/blockMeshDict @@ -0,0 +1,103 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +scale 0.01; //This is an scaling operation. Done at the end. + +xmin 0; +xmax 1; +ymin 0; +ymid 1; +ymax 2; +zmin 0; +zmid 5; +zmax 7; + +xcells 1; +ycells 20; +zcells 40; + +vertices +( + ($xmin $ymid $zmin) + ($xmax $ymid $zmin) + ($xmax $ymax $zmin) + ($xmin $ymax $zmin) + ($xmin $ymid $zmid) + ($xmax $ymid $zmid) + ($xmax $ymax $zmid) + ($xmin $ymax $zmid) + ($xmin $ymid $zmax) + ($xmax $ymid $zmax) + ($xmax $ymax $zmax) + ($xmin $ymax $zmax) + ($xmin $ymin $zmid) + ($xmax $ymin $zmid) + ($xmin $ymin $zmax) + ($xmax $ymin $zmax) +); + +blocks +( + hex (0 1 2 3 4 5 6 7) ($xcells 16 40) simpleGrading (1 1 1) + hex (4 5 6 7 8 9 10 11) ($xcells 16 16) simpleGrading (1 1 1) + hex (12 13 5 4 14 15 9 8) ($xcells 16 16) simpleGrading (1 1 1) +); + +edges +( +); + +boundary +( + fixedWalls + { + type wall; + faces + ( + (0 4 5 1) + (3 2 6 7) + (7 6 10 11) + (13 12 14 15) + (4 12 13 5) + ); + } + inlet + { + type patch; + faces + ( + (0 1 2 3) + ); + } + cplOutlet + { + type patch; + faces + ( + (11 10 9 8) + (8 9 15 14) + ); + } + frontAndBack + { + type empty; + faces + ( + (0 3 7 4) + (6 2 1 5) + (6 5 9 10) + (5 13 15 9) + (12 4 8 14) + (4 7 11 8) + ); + } +); + +mergePatchPairs +( +); diff --git a/partitioned-backwards-facing-step/fluid1-openfoam/system/controlDict b/partitioned-backwards-facing-step/fluid1-openfoam/system/controlDict new file mode 100644 index 000000000..404ab48bc --- /dev/null +++ b/partitioned-backwards-facing-step/fluid1-openfoam/system/controlDict @@ -0,0 +1,47 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} + +application pimpleFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 2.5; + +deltaT 0.005; + +writeControl runTime; + +writeInterval 0.05; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 8; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable false; + + +libs ("libpreciceAdapterFunctionObject.so"); +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + } +} diff --git a/partitioned-backwards-facing-step/fluid1-openfoam/system/fvSchemes b/partitioned-backwards-facing-step/fluid1-openfoam/system/fvSchemes new file mode 100644 index 000000000..e1a03a881 --- /dev/null +++ b/partitioned-backwards-facing-step/fluid1-openfoam/system/fvSchemes @@ -0,0 +1,39 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; + grad(p) Gauss linear; +} + +divSchemes +{ + default Gauss linear; + div(phi,U) bounded Gauss upwind; +} + +laplacianSchemes +{ + default Gauss linear orthogonal; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default orthogonal; +} diff --git a/partitioned-backwards-facing-step/fluid1-openfoam/system/fvSolution b/partitioned-backwards-facing-step/fluid1-openfoam/system/fvSolution new file mode 100644 index 000000000..353a29774 --- /dev/null +++ b/partitioned-backwards-facing-step/fluid1-openfoam/system/fvSolution @@ -0,0 +1,47 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSolution; +} + +solvers +{ + p + { + solver PCG; + preconditioner DIC; + tolerance 1e-06; + relTol 0; + } + + pFinal + { + $p; + relTol 0; + } + + U + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-6; + relTol 1e-4; + minIter 2; + } + + UFinal + { + $U; + relTol 0; + } +} + +PIMPLE +{ + nCorrectors 2; + nNonOrthogonalCorrectors 0; + momentumPredictor true; + nOuterCorrectors 2; +} diff --git a/partitioned-backwards-facing-step/fluid1-openfoam/system/preciceDict b/partitioned-backwards-facing-step/fluid1-openfoam/system/preciceDict new file mode 100644 index 000000000..86be20602 --- /dev/null +++ b/partitioned-backwards-facing-step/fluid1-openfoam/system/preciceDict @@ -0,0 +1,37 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Fluid1; + +modules (FF); + +interfaces +{ + Interface1 + { + mesh Fluid1-Mesh; + patches (cplOutlet); + + readData + ( + Pressure + VelocityBack + VelocityGradient + ); + + writeData + ( + Velocity + PressureBack + VelocityGradientBack + ); + }; +}; \ No newline at end of file diff --git a/partitioned-backwards-facing-step/fluid2-openfoam/0/U b/partitioned-backwards-facing-step/fluid2-openfoam/0/U new file mode 100644 index 000000000..6a851a314 --- /dev/null +++ b/partitioned-backwards-facing-step/fluid2-openfoam/0/U @@ -0,0 +1,36 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0 0 0); + +boundaryField +{ + fixedWalls + { + type fixedValue; + value uniform (0 0 0); + } + + cplInlet + { + type coupledVelocity; + refValue uniform (0 0 0); + } + + outlet + { + type zeroGradient; + } + + frontAndBack + { + type empty; + } +} diff --git a/partitioned-backwards-facing-step/fluid2-openfoam/0/p b/partitioned-backwards-facing-step/fluid2-openfoam/0/p new file mode 100644 index 000000000..ea4a11441 --- /dev/null +++ b/partitioned-backwards-facing-step/fluid2-openfoam/0/p @@ -0,0 +1,35 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p; +} + +dimensions [0 2 -2 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + fixedWalls + { + type zeroGradient; + } + cplInlet + { + type coupledPressure; + refValue uniform 0; + } + + outlet + { + type fixedValue; + value uniform 0; + } + + frontAndBack + { + type empty; + } +} diff --git a/partitioned-backwards-facing-step/fluid2-openfoam/clean.sh b/partitioned-backwards-facing-step/fluid2-openfoam/clean.sh new file mode 100755 index 000000000..aa660ccc2 --- /dev/null +++ b/partitioned-backwards-facing-step/fluid2-openfoam/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . \ No newline at end of file diff --git a/partitioned-backwards-facing-step/fluid2-openfoam/constant/transportProperties b/partitioned-backwards-facing-step/fluid2-openfoam/constant/transportProperties new file mode 100644 index 000000000..19a9f0403 --- /dev/null +++ b/partitioned-backwards-facing-step/fluid2-openfoam/constant/transportProperties @@ -0,0 +1,13 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object transportProperties; +} + +transportModel Newtonian; + + +nu nu [ 0 2 -1 0 0 0 0 ] 0.00001; //Re 100 +//nu nu [ 0 2 -1 0 0 0 0 ] 0.0001; //Re 1000 diff --git a/partitioned-backwards-facing-step/fluid2-openfoam/constant/turbulenceProperties b/partitioned-backwards-facing-step/fluid2-openfoam/constant/turbulenceProperties new file mode 100644 index 000000000..cb924ae6d --- /dev/null +++ b/partitioned-backwards-facing-step/fluid2-openfoam/constant/turbulenceProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object turbulenceProperties; +} + +simulationType laminar; diff --git a/partitioned-backwards-facing-step/fluid2-openfoam/run.sh b/partitioned-backwards-facing-step/fluid2-openfoam/run.sh new file mode 100755 index 000000000..da82a9ba2 --- /dev/null +++ b/partitioned-backwards-facing-step/fluid2-openfoam/run.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/partitioned-backwards-facing-step/fluid2-openfoam/system/blockMeshDict b/partitioned-backwards-facing-step/fluid2-openfoam/system/blockMeshDict new file mode 100644 index 000000000..a26f5e7c3 --- /dev/null +++ b/partitioned-backwards-facing-step/fluid2-openfoam/system/blockMeshDict @@ -0,0 +1,98 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +scale 0.01; //This is an scaling operation. Done at the end. + +xmin 0; +xmax 1; +ymin 0; +ymid 1; +ymax 2; +zmin 0; +zmid 7; +zmax 15; + +xcells 1; +ycells 20; +zcells 40; + +vertices +( + ($xmin $ymid $zmin) + ($xmax $ymid $zmin) + ($xmax $ymax $zmin) + ($xmin $ymax $zmin) + ($xmin $ymid $zmid) + ($xmax $ymid $zmid) + ($xmax $ymax $zmid) + ($xmin $ymax $zmid) + ($xmin $ymid $zmax) + ($xmax $ymid $zmax) + ($xmax $ymax $zmax) + ($xmin $ymax $zmax) + ($xmin $ymin $zmid) + ($xmax $ymin $zmid) + ($xmin $ymin $zmax) + ($xmax $ymin $zmax) +); + +blocks +( + hex (4 5 6 7 8 9 10 11) ($xcells 16 64) simpleGrading (1 1 1) + hex (12 13 5 4 14 15 9 8) ($xcells 16 64) simpleGrading (1 1 1) +); + +edges +( +); + +boundary +( + fixedWalls + { + type wall; + faces + ( + (7 6 10 11) + (13 12 14 15) + ); + } + cplInlet + { + type patch; + faces + ( + (4 5 6 7) + (4 12 13 5) + ); + } + outlet + { + type patch; + faces + ( + (11 10 9 8) + (8 9 15 14) + ); + } + frontAndBack + { + type empty; + faces + ( + (6 5 9 10) + (5 13 15 9) + (12 4 8 14) + (4 7 11 8) + ); + } +); + +mergePatchPairs +( +); diff --git a/partitioned-backwards-facing-step/fluid2-openfoam/system/controlDict b/partitioned-backwards-facing-step/fluid2-openfoam/system/controlDict new file mode 100644 index 000000000..404ab48bc --- /dev/null +++ b/partitioned-backwards-facing-step/fluid2-openfoam/system/controlDict @@ -0,0 +1,47 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} + +application pimpleFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 2.5; + +deltaT 0.005; + +writeControl runTime; + +writeInterval 0.05; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 8; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable false; + + +libs ("libpreciceAdapterFunctionObject.so"); +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + } +} diff --git a/partitioned-backwards-facing-step/fluid2-openfoam/system/fvSchemes b/partitioned-backwards-facing-step/fluid2-openfoam/system/fvSchemes new file mode 100644 index 000000000..e1a03a881 --- /dev/null +++ b/partitioned-backwards-facing-step/fluid2-openfoam/system/fvSchemes @@ -0,0 +1,39 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; + grad(p) Gauss linear; +} + +divSchemes +{ + default Gauss linear; + div(phi,U) bounded Gauss upwind; +} + +laplacianSchemes +{ + default Gauss linear orthogonal; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default orthogonal; +} diff --git a/partitioned-backwards-facing-step/fluid2-openfoam/system/fvSolution b/partitioned-backwards-facing-step/fluid2-openfoam/system/fvSolution new file mode 100644 index 000000000..353a29774 --- /dev/null +++ b/partitioned-backwards-facing-step/fluid2-openfoam/system/fvSolution @@ -0,0 +1,47 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSolution; +} + +solvers +{ + p + { + solver PCG; + preconditioner DIC; + tolerance 1e-06; + relTol 0; + } + + pFinal + { + $p; + relTol 0; + } + + U + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-6; + relTol 1e-4; + minIter 2; + } + + UFinal + { + $U; + relTol 0; + } +} + +PIMPLE +{ + nCorrectors 2; + nNonOrthogonalCorrectors 0; + momentumPredictor true; + nOuterCorrectors 2; +} diff --git a/partitioned-backwards-facing-step/fluid2-openfoam/system/preciceDict b/partitioned-backwards-facing-step/fluid2-openfoam/system/preciceDict new file mode 100644 index 000000000..2d842df4a --- /dev/null +++ b/partitioned-backwards-facing-step/fluid2-openfoam/system/preciceDict @@ -0,0 +1,37 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Fluid2; + +modules (FF); + +interfaces +{ + Interface1 + { + mesh Fluid2-Mesh; + patches (cplInlet); + + readData + ( + Velocity + PressureBack + VelocityGradientBack + ); + + writeData + ( + Pressure + VelocityBack + VelocityGradient + ); + }; +}; \ No newline at end of file diff --git a/partitioned-backwards-facing-step/images/tutorials-partitioned-backwards-facing-step-precice-config.png b/partitioned-backwards-facing-step/images/tutorials-partitioned-backwards-facing-step-precice-config.png new file mode 100644 index 000000000..77b0ed616 Binary files /dev/null and b/partitioned-backwards-facing-step/images/tutorials-partitioned-backwards-facing-step-precice-config.png differ diff --git a/partitioned-backwards-facing-step/images/tutorials-partitioned-backwards-facing-step-results.png b/partitioned-backwards-facing-step/images/tutorials-partitioned-backwards-facing-step-results.png new file mode 100644 index 000000000..fccffccb9 Binary files /dev/null and b/partitioned-backwards-facing-step/images/tutorials-partitioned-backwards-facing-step-results.png differ diff --git a/partitioned-backwards-facing-step/images/tutorials-partitioned-backwards-facing-step-sampled.png b/partitioned-backwards-facing-step/images/tutorials-partitioned-backwards-facing-step-sampled.png new file mode 100644 index 000000000..55e9e7eb9 Binary files /dev/null and b/partitioned-backwards-facing-step/images/tutorials-partitioned-backwards-facing-step-sampled.png differ diff --git a/partitioned-backwards-facing-step/precice-config.xml b/partitioned-backwards-facing-step/precice-config.xml new file mode 100644 index 000000000..216c9538b --- /dev/null +++ b/partitioned-backwards-facing-step/precice-config.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/partitioned-elastic-beam/README.md b/partitioned-elastic-beam/README.md index aac724ada..8021abc53 100644 --- a/partitioned-elastic-beam/README.md +++ b/partitioned-elastic-beam/README.md @@ -15,6 +15,12 @@ We have a rectangular linear elastic beam of dimensions 1 x 1 x 8 m, divided in ![beam setup](images/tutorials-partitioned-elastic-beam-setup.png) +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-partitioned-elastic-beam-precice-config.png) + ## Available solvers * CalculiX. CalculiX is used for both structural parts. For more information, have a look at the [CalculiX adapter documentation](https://www.precice.org/adapter-calculix-overview.html) for more. diff --git a/partitioned-elastic-beam/dirichlet-calculix/run.sh b/partitioned-elastic-beam/dirichlet-calculix/run.sh index 4e020fcd1..a7266841a 100755 --- a/partitioned-elastic-beam/dirichlet-calculix/run.sh +++ b/partitioned-elastic-beam/dirichlet-calculix/run.sh @@ -1,6 +1,11 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + export OMP_NUM_THREADS=1 export CCX_NPROC_EQUATION_SOLVER=1 ccx_preCICE -i beam1 -precice-participant Calculix1 + +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 new file mode 100644 index 000000000..24c552332 Binary files /dev/null and b/partitioned-elastic-beam/images/tutorials-partitioned-elastic-beam-precice-config.png differ diff --git a/partitioned-elastic-beam/neumann-calculix/run.sh b/partitioned-elastic-beam/neumann-calculix/run.sh index e1730a420..b8dfea3d6 100755 --- a/partitioned-elastic-beam/neumann-calculix/run.sh +++ b/partitioned-elastic-beam/neumann-calculix/run.sh @@ -1,6 +1,11 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + export OMP_NUM_THREADS=1 export CCX_NPROC_EQUATION_SOLVER=1 ccx_preCICE -i beam2 -precice-participant Calculix2 + +close_log diff --git a/partitioned-elastic-beam/precice-config.xml b/partitioned-elastic-beam/precice-config.xml index eea9ea6ac..0eb599a28 100644 --- a/partitioned-elastic-beam/precice-config.xml +++ b/partitioned-elastic-beam/precice-config.xml @@ -7,66 +7,62 @@ enabled="true" /> - - - + + - - - - + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - - + + + + + - + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/partitioned-heat-conduction-complex/README.md b/partitioned-heat-conduction-complex/README.md index a7a181dcd..919d79b72 100644 --- a/partitioned-heat-conduction-complex/README.md +++ b/partitioned-heat-conduction-complex/README.md @@ -20,10 +20,16 @@ This case is an advanced version of `partitioned-heat-conduction`. Some advanced * The exchanged temperature is still scalar valued, but the heat flux is vector valued. * You can decide to use a time dependent heat flux and right-hand side to make the problem more challenging. +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-partitioned-heat-conduction-complex-precice-config.png) + ## Available solvers and dependencies See `partitioned-heat-conduction`, only `fenics` is provided as a solver. ## Running the simulation -See `partitioned-heat-conduction`. The additional featured mentioned above can be activated via command line arguments. Please run `python3 fenics/heat.py --help` for a full list of provided arguments. +See `partitioned-heat-conduction`. The additional featured mentioned above can be activated via command line arguments. Please run `python3 solver-fenics/heat.py --help` for a full list of provided arguments. diff --git a/partitioned-heat-conduction-complex/fenics/clean.sh b/partitioned-heat-conduction-complex/dirichlet-fenics/clean.sh similarity index 100% rename from partitioned-heat-conduction-complex/fenics/clean.sh rename to partitioned-heat-conduction-complex/dirichlet-fenics/clean.sh diff --git a/partitioned-heat-conduction-complex/fenics/precice-adapter-config-D.json b/partitioned-heat-conduction-complex/dirichlet-fenics/precice-adapter-config.json similarity index 83% rename from partitioned-heat-conduction-complex/fenics/precice-adapter-config-D.json rename to partitioned-heat-conduction-complex/dirichlet-fenics/precice-adapter-config.json index 9430d6e1e..2a31d960f 100644 --- a/partitioned-heat-conduction-complex/fenics/precice-adapter-config-D.json +++ b/partitioned-heat-conduction-complex/dirichlet-fenics/precice-adapter-config.json @@ -3,7 +3,7 @@ "config_file_name": "../precice-config.xml", "interface": { "coupling_mesh_name": "Dirichlet-Mesh", - "write_data_name": "Flux", + "write_data_name": "Heat-Flux", "read_data_name": "Temperature" } } diff --git a/partitioned-heat-conduction-complex/dirichlet-fenics/run.sh b/partitioned-heat-conduction-complex/dirichlet-fenics/run.sh new file mode 100755 index 000000000..e4c1a798c --- /dev/null +++ b/partitioned-heat-conduction-complex/dirichlet-fenics/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 ../solver-fenics/heat.py -d -i complex + +close_log diff --git a/partitioned-heat-conduction-complex/fenics/.gitignore b/partitioned-heat-conduction-complex/fenics/.gitignore deleted file mode 100644 index 3cf3e6819..000000000 --- a/partitioned-heat-conduction-complex/fenics/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -*.txt -venv -.idea -*.pyc -out -*.log -*events.json diff --git a/partitioned-heat-conduction-complex/fenics/run.sh b/partitioned-heat-conduction-complex/fenics/run.sh deleted file mode 100755 index 0b375221b..000000000 --- a/partitioned-heat-conduction-complex/fenics/run.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -set -e -u - -while getopts ":dn" opt; do - case ${opt} in - d) - python3 heat.py -d -a - ;; - n) - python3 heat.py -n -a - ;; - \?) - echo "Usage: cmd [-d] [-n]" - ;; - esac -done diff --git a/partitioned-heat-conduction-complex/images/tutorials-partitioned-heat-conduction-complex-precice-config.png b/partitioned-heat-conduction-complex/images/tutorials-partitioned-heat-conduction-complex-precice-config.png new file mode 100644 index 000000000..183c80fe4 Binary files /dev/null and b/partitioned-heat-conduction-complex/images/tutorials-partitioned-heat-conduction-complex-precice-config.png differ diff --git a/partitioned-heat-conduction/fenics/clean.sh b/partitioned-heat-conduction-complex/neumann-fenics/clean.sh similarity index 100% rename from partitioned-heat-conduction/fenics/clean.sh rename to partitioned-heat-conduction-complex/neumann-fenics/clean.sh diff --git a/partitioned-heat-conduction-complex/fenics/precice-adapter-config-N.json b/partitioned-heat-conduction-complex/neumann-fenics/precice-adapter-config.json similarity index 84% rename from partitioned-heat-conduction-complex/fenics/precice-adapter-config-N.json rename to partitioned-heat-conduction-complex/neumann-fenics/precice-adapter-config.json index b21673b23..03d46a541 100644 --- a/partitioned-heat-conduction-complex/fenics/precice-adapter-config-N.json +++ b/partitioned-heat-conduction-complex/neumann-fenics/precice-adapter-config.json @@ -4,6 +4,6 @@ "interface": { "coupling_mesh_name": "Neumann-Mesh", "write_data_name": "Temperature", - "read_data_name": "Flux" + "read_data_name": "Heat-Flux" } } diff --git a/partitioned-heat-conduction-complex/neumann-fenics/run.sh b/partitioned-heat-conduction-complex/neumann-fenics/run.sh new file mode 100755 index 000000000..4f0ae3402 --- /dev/null +++ b/partitioned-heat-conduction-complex/neumann-fenics/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 ../solver-fenics/heat.py -n -i complex + +close_log diff --git a/partitioned-heat-conduction-complex/precice-config.xml b/partitioned-heat-conduction-complex/precice-config.xml index 547a4f207..fb194ab8d 100644 --- a/partitioned-heat-conduction-complex/precice-config.xml +++ b/partitioned-heat-conduction-complex/precice-config.xml @@ -1,61 +1,71 @@ - - + - - + - - - - - - - - - + + - - - - + + + + - - - - - - - + + + + - - - - - - - + + + + + + + - + + + + + + + - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + diff --git a/partitioned-heat-conduction-complex/fenics/errorcomputation.py b/partitioned-heat-conduction-complex/solver-fenics/errorcomputation.py similarity index 100% rename from partitioned-heat-conduction-complex/fenics/errorcomputation.py rename to partitioned-heat-conduction-complex/solver-fenics/errorcomputation.py diff --git a/partitioned-heat-conduction-complex/fenics/heat.py b/partitioned-heat-conduction-complex/solver-fenics/heat.py similarity index 82% rename from partitioned-heat-conduction-complex/fenics/heat.py rename to partitioned-heat-conduction-complex/solver-fenics/heat.py index 9ba1f519c..b18846d0a 100644 --- a/partitioned-heat-conduction-complex/fenics/heat.py +++ b/partitioned-heat-conduction-complex/solver-fenics/heat.py @@ -26,15 +26,14 @@ from __future__ import print_function, division from fenics import Function, FunctionSpace, Expression, Constant, DirichletBC, TrialFunction, TestFunction, \ - File, solve, lhs, rhs, grad, inner, dot, dx, ds, interpolate, VectorFunctionSpace, MeshFunction, MPI + File, solve, lhs, rhs, grad, inner, dot, dx, ds, interpolate, VectorFunctionSpace, FacetNormal, MeshFunction, MPI from fenicsprecice import Adapter from errorcomputation import compute_errors from my_enums import ProblemType, DomainPart import argparse import numpy as np from problem_setup import get_geometry, get_problem_setup -import dolfin -from dolfin import FacetNormal, dot +import sympy as sp def determine_gradient(V_g, u, flux): @@ -59,9 +58,6 @@ def determine_gradient(V_g, u, flux): parser.add_argument("-n", "--neumann", help="create a neumann problem", dest='neumann', action='store_true') parser.add_argument("-g", "--gamma", help="parameter gamma to set temporal dependence of heat flux", default=0.0, type=float) -parser.add_argument("-a", "--arbitrary-coupling-interface", - help="uses more general, but less exact method for interpolation on coupling interface," - "see https://github.com/precice/fenics-adapter/milestone/1", action='store_true') parser.add_argument("-i", "--interface", metavar="interface_type string", type=str, choices=['simple', 'complex'], help="Type of coupling interface case to be solved. Options: simple, complex", default="simple") parser.add_argument("-dom", "--domain", metavar='domain_type string', type=str, @@ -75,7 +71,7 @@ def determine_gradient(V_g, u, flux): # Error is bounded by coupling accuracy. In theory we can obtain the analytical solution. error_tol = 10 ** -6 alpha = 3 # parameter alpha -beta = 1.3 # parameter beta +beta = 1.2 # parameter beta gamma = args.gamma # parameter gamma, dependence of heat flux on time # Create mesh and separate mesh components for grid, boundary and coupling interface @@ -87,11 +83,13 @@ def determine_gradient(V_g, u, flux): V_g = VectorFunctionSpace(mesh, 'P', 1) # Define boundary conditions -u_D = Expression('1 + gamma*t*x[0]*x[0] + (1-gamma)*x[0]*x[0] + alpha*x[1]*x[1] + beta*t', degree=2, alpha=alpha, - beta=beta, gamma=gamma, t=0) +# create sympy expression of manufactured solution +x_sp, y_sp, t_sp = sp.symbols(['x[0]', 'x[1]', 't']) +u_D_sp = 1 + gamma * t_sp * x_sp * x_sp + (1 - gamma) * x_sp * x_sp + alpha * y_sp * y_sp + beta * t_sp +u_D = Expression(sp.ccode(u_D_sp), degree=2, alpha=alpha, beta=beta, gamma=gamma, t=0) u_D_function = interpolate(u_D, V) # Define flux in x direction on coupling interface (grad(u_D) in normal direction) -f_N = Expression(("2 * gamma*t*x[0] + 2 * (1-gamma)*x[0]", "2 * alpha*x[1]"), degree=1, gamma=gamma, alpha=alpha, t=0) +f_N = Expression((sp.ccode(u_D_sp.diff(x_sp)), sp.ccode(u_D_sp.diff(y_sp))), degree=1, gamma=gamma, alpha=alpha, t=0) f_N_function = interpolate(f_N, V_g) # Define initial value @@ -101,23 +99,25 @@ def determine_gradient(V_g, u, flux): precice, precice_dt, initial_data = None, 0.0, None # Initialize the adapter according to the specific participant +precice = Adapter(adapter_config_filename="precice-adapter-config.json") + if problem is ProblemType.DIRICHLET: - precice = Adapter(adapter_config_filename="precice-adapter-config-D.json") - precice_dt = precice.initialize(coupling_boundary, read_function_space=V, write_object=f_N_function) + precice.initialize(coupling_boundary, read_function_space=V, write_object=f_N_function) elif problem is ProblemType.NEUMANN: - precice = Adapter(adapter_config_filename="precice-adapter-config-N.json") - precice_dt = precice.initialize(coupling_boundary, read_function_space=V_g, write_object=u_D_function) + precice.initialize(coupling_boundary, read_function_space=V_g, write_object=u_D_function) boundary_marker = False dt = Constant(0) +precice_dt = precice.get_max_time_step_size() dt.assign(np.min([fenics_dt, precice_dt])) # Define variational problem u = TrialFunction(V) v = TestFunction(V) -f = Expression('beta + gamma*x[0]*x[0] - 2*gamma*t - 2*(1-gamma) - 2*alpha', - degree=2, alpha=alpha, beta=beta, gamma=gamma, t=0) +# du_dt-Laplace(u) = f +f_sp = u_D_sp.diff(t_sp) - u_D_sp.diff(x_sp).diff(x_sp) - u_D_sp.diff(y_sp).diff(y_sp) +f = Expression(sp.ccode(f_sp), degree=2, alpha=alpha, beta=beta, gamma=gamma, t=0) F = u * v / dt * dx + dot(grad(u), grad(v)) * dx - (u_n / dt + f) * v * dx bcs = [DirichletBC(V, u_D, remaining_boundary)] @@ -134,16 +134,16 @@ def determine_gradient(V_g, u, flux): # this term has to be added to weak form to add a Neumann BC (see e.g. p. # 83ff Langtangen, Hans Petter, and Anders Logg. "Solving PDEs in Python # The FEniCS Tutorial Volume I." (2016).) - F += v * coupling_expression * dolfin.ds + F += v * coupling_expression * ds elif coupling_expression.is_vector_valued(): normal = FacetNormal(mesh) - F += -v * dot(normal, coupling_expression) * dolfin.ds + F += -v * dot(normal, coupling_expression) * ds else: raise Exception("invalid!") else: # For multiple Neumann BCs integration should only be performed over the respective domain. # TODO: fix the problem here raise Exception("Boundary markers are not implemented yet") - # return dot(coupling_bc_expression, v) * dolfin.dss(boundary_marker) + # return dot(coupling_bc_expression, v) * dss(boundary_marker) a, L = lhs(F), rhs(F) @@ -173,28 +173,32 @@ def determine_gradient(V_g, u, flux): # output solution and reference solution at t=0, n=0 n = 0 print('output u^%d and u_ref^%d' % (n, n)) -temperature_out << u_n +temperature_out << (u_n, t) ref_out << u_ref ranks << mesh_rank error_total, error_pointwise = compute_errors(u_n, u_ref, V) error_out << error_pointwise -# set t_1 = t_0 + dt, this gives u_D^1 -# call dt(0) to evaluate FEniCS Constant. Todo: is there a better way? -u_D.t = t + dt(0) -f.t = t + dt(0) - flux = Function(V_g) flux.rename("Flux", "") while precice.is_coupling_ongoing(): # write checkpoint - if precice.is_action_required(precice.action_write_iteration_checkpoint()): + if precice.requires_writing_checkpoint(): precice.store_checkpoint(u_n, t, n) - read_data = precice.read_data() + precice_dt = precice.get_max_time_step_size() + dt.assign(np.min([fenics_dt, precice_dt])) + + # Dirichlet BC and RHS need to point to end of current timestep + u_D.t = t + float(dt) + f.t = t + float(dt) + + # Coupling BC needs to point to end of current timestep + read_data = precice.read_data(dt) + if problem is ProblemType.DIRICHLET and (domain_part is DomainPart.CIRCULAR or domain_part is DomainPart.RECTANGLE): # We have to data for an arbitrary point that is not on the circle, to obtain exact solution. # See https://github.com/precice/fenics-adapter/issues/113 for details. @@ -203,8 +207,6 @@ def determine_gradient(V_g, u, flux): # Update the coupling expression with the new read data precice.update_coupling_expression(coupling_expression, read_data) - dt.assign(np.min([fenics_dt, precice_dt])) - # Compute solution u^n+1, use bcs u_D^n+1, u^n and coupling bcs solve(a == L, u_np1, bcs) @@ -217,10 +219,10 @@ def determine_gradient(V_g, u, flux): # Neumann problem reads flux and writes temperature on boundary to Dirichlet problem precice.write_data(u_np1) - precice_dt = precice.advance(dt(0)) + precice.advance(dt(0)) # roll back to checkpoint - if precice.is_action_required(precice.action_read_iteration_checkpoint()): + if precice.requires_reading_checkpoint(): u_cp, t_cp, n_cp = precice.retrieve_checkpoint() u_n.assign(u_cp) t = t_cp @@ -237,13 +239,9 @@ def determine_gradient(V_g, u, flux): print('n = %d, t = %.2f: L2 error on domain = %.3g' % (n, t, error)) # output solution and reference solution at t_n+1 print('output u^%d and u_ref^%d' % (n, n)) - temperature_out << u_n + temperature_out << (u_n, t) ref_out << u_ref error_out << error_pointwise - # Update Dirichlet BC - u_D.t = t + float(dt) - f.t = t + float(dt) - # Hold plot precice.finalize() diff --git a/partitioned-heat-conduction-complex/fenics/my_enums.py b/partitioned-heat-conduction-complex/solver-fenics/my_enums.py similarity index 100% rename from partitioned-heat-conduction-complex/fenics/my_enums.py rename to partitioned-heat-conduction-complex/solver-fenics/my_enums.py diff --git a/partitioned-heat-conduction-complex/fenics/problem_setup.py b/partitioned-heat-conduction-complex/solver-fenics/problem_setup.py similarity index 100% rename from partitioned-heat-conduction-complex/fenics/problem_setup.py rename to partitioned-heat-conduction-complex/solver-fenics/problem_setup.py diff --git a/partitioned-heat-conduction-direct/README.md b/partitioned-heat-conduction-direct/README.md new file mode 100644 index 000000000..88f9aecc2 --- /dev/null +++ b/partitioned-heat-conduction-direct/README.md @@ -0,0 +1,46 @@ +--- +title: Partitioned heat conduction (direct access setup) +permalink: tutorials-partitioned-heat-conduction-direct.html +keywords: Nutils, Heat conduction, Direct mesh access +summary: This tutorial is a modified version of the "partitioned heat conduction" tutorial showcasing direct mesh access. +--- + +{% note %} +Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/partitioned-heat-conduction-direct). Read how in the [tutorials introduction](https://www.precice.org/tutorials.html). +{% endnote %} + +## Setup + +This case is a modified version of the [partitioned heat conduction tutorial](tutorials-partitioned-heat-conduction.html). Main modification is that we here use the [direct mesh access feature](couple-your-code-direct-access.html) to let the solvers compute the data mapping and not preCICE. + +Further minor modifications: + +- We use a parallel coupling scheme instead of a serial one to prevent running into the problem where we are trying to add a zero column to the quasi-Newton matrix. For serial coupling, this happens here because one data field converges much faster than the other. + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-partitioned-heat-conduction-direct-precice-config.png) + +## 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. + +## Running the simulation + +Open two terminals and run: + +```bash +cd neumann-nutils +./run.sh +``` + +and + +```bash +cd dirichlet-nutils +./run.sh +``` + +See the [partitioned heat conduction tutorial](tutorials-partitioned-heat-conduction.html). diff --git a/partitioned-heat-conduction-direct/clean-tutorial.sh b/partitioned-heat-conduction-direct/clean-tutorial.sh new file mode 100755 index 000000000..471f8f887 --- /dev/null +++ b/partitioned-heat-conduction-direct/clean-tutorial.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -e -u + +# shellcheck disable=SC1091 +. ../tools/cleaning-tools.sh + +clean_tutorial . + diff --git a/partitioned-heat-conduction-direct/dirichlet-nutils/clean.sh b/partitioned-heat-conduction-direct/dirichlet-nutils/clean.sh new file mode 100755 index 000000000..6893c1ea5 --- /dev/null +++ b/partitioned-heat-conduction-direct/dirichlet-nutils/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_nutils . diff --git a/partitioned-heat-conduction-direct/dirichlet-nutils/heat.py b/partitioned-heat-conduction-direct/dirichlet-nutils/heat.py new file mode 100644 index 000000000..f8827dbef --- /dev/null +++ b/partitioned-heat-conduction-direct/dirichlet-nutils/heat.py @@ -0,0 +1,151 @@ +#! /usr/bin/env python3 + +from nutils import cli, mesh, function, solver, export +import functools +import treelog +import numpy as np +import precice + + +def main(n=10, degree=1, timestep=.1, alpha=3., beta=1.2): + + x_grid = np.linspace(0, 1, n) + y_grid = np.linspace(0, 1, n) + + # define the Nutils mesh + domain, geom = mesh.rectilinear([x_grid, y_grid]) + coupling_boundary = domain.boundary['right'] + read_sample = coupling_boundary.sample('gauss', degree=degree * 2) + + # Nutils namespace + ns = function.Namespace() + ns.x = geom + ns.basis = domain.basis('std', degree=degree) + ns.alpha = alpha # parameter of problem + ns.beta = beta # parameter of problem + ns.u = 'basis_n ?lhs_n' # solution + ns.dudt = 'basis_n (?lhs_n - ?lhs0_n) / ?dt' # time derivative + ns.flux = 'basis_n ?fluxdofs_n' # heat flux + ns.f = 'beta - 2 - 2 alpha' # rhs + ns.uexact = '1 + x_0 x_0 + alpha x_1 x_1 + beta ?t' # analytical solution + ns.readbasis = read_sample.basis() + ns.readfunc = 'readbasis_n ?readdata_n' + + # define the weak form + res = domain.integral( + '(basis_n dudt - basis_n f + basis_n,i u_,i) d:x' @ ns, degree=degree * 2) + + # set boundary conditions at non-coupling boundaries + # top and bottom boundary are non-coupling for both sides + sqr = domain.boundary['top,bottom,left'].integral( + '(u - uexact)^2 d:x' @ ns, degree=degree * 2) + + sqr += read_sample.integral('(u - readfunc)^2 d:x' @ ns) + + # preCICE setup + participant = precice.Participant( + "Dirichlet", "../precice-config.xml", 0, 1) + + mesh_name_read = "Dirichlet-Mesh" + mesh_name_write = "Neumann-Mesh" + + vertex_ids_read = participant.set_mesh_vertices( + mesh_name_read, read_sample.eval(ns.x)) + participant.set_mesh_access_region(mesh_name_write, [.9, 1.1, -.1, 1.1]) + + participant.initialize() + precice_dt = participant.get_max_time_step_size() + solver_dt = timestep + dt = min(precice_dt, solver_dt) + + vertex_ids_write, coords = participant.get_mesh_vertex_ids_and_coordinates( + mesh_name_write) + write_sample = domain.locate(ns.x, coords, eps=1e-10, tol=1e-10) + + precice_write = functools.partial( + participant.write_data, mesh_name_write, "Heat-Flux", vertex_ids_write) + precice_read = functools.partial( + participant.read_data, mesh_name_read, "Temperature", vertex_ids_read) + + # helper functions to project heat flux to coupling boundary + + # To communicate the flux to the Neumann side we should not simply + # evaluate u_,i n_i as this is an unbounded term leading to suboptimal + # convergence. Instead we project ∀ v: ∫_Γ v flux = ∫_Γ v u_,i n_i and + # evaluate flux. While the right-hand-side contains the same unbounded + # term, we can use the strong identity du/dt - u_,ii = f to rewrite it + # to ∫_Ω [v (du/dt - f) + v_,i u_,i] - ∫_∂Ω\Γ v u_,k n_k, in which we + # recognize the residual and an integral over the exterior boundary. + # While the latter still contains the problematic unbounded term, we + # can use the fact that the flux is a known value at the top and bottom + # via the Dirichlet boundary condition, and impose it as constraints. + right_sqr = domain.boundary['right'].integral( + 'flux^2 d:x' @ ns, degree=degree * 2) + right_cons = solver.optimize('fluxdofs', right_sqr, droptol=1e-10) + # right_cons is NaN in dofs that are NOT supported on the right boundary + flux_sqr = domain.boundary['right'].boundary['top,bottom'].integral( + '(flux - uexact_,0)^2 d:x' @ ns, degree=degree * 2) + flux_cons = solver.optimize('fluxdofs', flux_sqr, droptol=1e-10, + constrain=np.choose(np.isnan(right_cons), [np.nan, 0.])) + # flux_cons is NaN in dofs that are supported on ONLY the right boundary + flux_res = read_sample.integral('basis_n flux d:x' @ ns) - res + + t = 0. + istep = 0 + + # initial condition + sqr0 = domain.integral('(u - uexact)^2' @ ns, degree=degree * 2) + lhs = solver.optimize('lhs', sqr0, arguments=dict(t=t)) + bezier = domain.sample('bezier', degree * 2) + + while participant.is_coupling_ongoing(): + + # save checkpoint + if participant.requires_writing_checkpoint(): + checkpoint = lhs, t, istep + + # prepare next timestep + precice_dt = participant.get_max_time_step_size() + dt = min(precice_dt, solver_dt) + lhs0 = lhs + istep += 1 + t += dt + + # read data from participant + read_data = precice_read(dt) + + # update (time-dependent) boundary condition + cons = solver.optimize('lhs', sqr, droptol=1e-15, + arguments=dict(t=t, readdata=read_data)) + + # solve nutils timestep + lhs = solver.solve_linear('lhs', res, constrain=cons, arguments=dict( + lhs0=lhs0, dt=dt, t=t, readdata=read_data)) + + # write data to participant + fluxdofs = solver.solve_linear( + 'fluxdofs', flux_res, arguments=dict( + lhs0=lhs0, lhs=lhs, dt=dt, t=t), constrain=flux_cons) + write_data = write_sample.eval('flux' @ ns, fluxdofs=fluxdofs) + + precice_write(write_data) + + # do the coupling + participant.advance(dt) + + # read checkpoint if required + if participant.requires_reading_checkpoint(): + lhs, t, istep = checkpoint + else: + # generate output + x, u, uexact = bezier.eval( + ['x_i', 'u', 'uexact'] @ ns, lhs=lhs, t=t) + with treelog.add(treelog.DataLog()): + export.vtk("Dirichlet" + "-" + str(istep), bezier.tri, + x, Temperature=u, reference=uexact) + + participant.finalize() + + +if __name__ == '__main__': + cli.run(main) diff --git a/partitioned-heat-conduction-direct/dirichlet-nutils/requirements.txt b/partitioned-heat-conduction-direct/dirichlet-nutils/requirements.txt new file mode 100644 index 000000000..cfd521c81 --- /dev/null +++ b/partitioned-heat-conduction-direct/dirichlet-nutils/requirements.txt @@ -0,0 +1,2 @@ +nutils==7 +pyprecice==3 diff --git a/partitioned-heat-conduction-direct/dirichlet-nutils/run.sh b/partitioned-heat-conduction-direct/dirichlet-nutils/run.sh new file mode 100755 index 000000000..e5743798a --- /dev/null +++ b/partitioned-heat-conduction-direct/dirichlet-nutils/run.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 -m venv .venv +. .venv/bin/activate +pip install -r requirements.txt + +rm -rf Dirichlet-*.vtk +NUTILS_RICHOUTPUT=no python3 heat.py + +close_log diff --git a/partitioned-heat-conduction-direct/images/tutorials-partitioned-heat-conduction-direct-precice-config.png b/partitioned-heat-conduction-direct/images/tutorials-partitioned-heat-conduction-direct-precice-config.png new file mode 100644 index 000000000..e65640c71 Binary files /dev/null and b/partitioned-heat-conduction-direct/images/tutorials-partitioned-heat-conduction-direct-precice-config.png differ diff --git a/partitioned-heat-conduction-direct/neumann-nutils/clean.sh b/partitioned-heat-conduction-direct/neumann-nutils/clean.sh new file mode 100755 index 000000000..6893c1ea5 --- /dev/null +++ b/partitioned-heat-conduction-direct/neumann-nutils/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_nutils . diff --git a/partitioned-heat-conduction-direct/neumann-nutils/heat.py b/partitioned-heat-conduction-direct/neumann-nutils/heat.py new file mode 100644 index 000000000..6857ddce1 --- /dev/null +++ b/partitioned-heat-conduction-direct/neumann-nutils/heat.py @@ -0,0 +1,123 @@ +#! /usr/bin/env python3 + +from nutils import cli, mesh, function, solver, export +import functools +import treelog +import numpy as np +import precice + + +def main(n=10, degree=1, timestep=.1, alpha=3., beta=1.2): + + x_grid = np.linspace(1, 2, n) + y_grid = np.linspace(0, 1, n) + + # define the Nutils mesh + domain, geom = mesh.rectilinear([x_grid, y_grid]) + coupling_boundary = domain.boundary['left'] + read_sample = coupling_boundary.sample('gauss', degree=degree * 2) + + # Nutils namespace + ns = function.Namespace() + ns.x = geom + ns.basis = domain.basis('std', degree=degree) + ns.alpha = alpha # parameter of problem + ns.beta = beta # parameter of problem + ns.u = 'basis_n ?lhs_n' # solution + ns.dudt = 'basis_n (?lhs_n - ?lhs0_n) / ?dt' # time derivative + ns.flux = 'basis_n ?fluxdofs_n' # heat flux + ns.f = 'beta - 2 - 2 alpha' # rhs + ns.uexact = '1 + x_0 x_0 + alpha x_1 x_1 + beta ?t' # analytical solution + ns.readbasis = read_sample.basis() + ns.readfunc = 'readbasis_n ?readdata_n' + + # define the weak form + res = domain.integral( + '(basis_n dudt - basis_n f + basis_n,i u_,i) d:x' @ ns, degree=degree * 2) + + # set boundary conditions at non-coupling boundaries + # top and bottom boundary are non-coupling for both sides + sqr = domain.boundary['top,bottom,right'].integral( + '(u - uexact)^2 d:x' @ ns, degree=degree * 2) + + res += read_sample.integral('basis_n readfunc d:x' @ ns) + + # preCICE setup + participant = precice.Participant("Neumann", "../precice-config.xml", 0, 1) + + mesh_name_read = "Neumann-Mesh" + mesh_name_write = "Dirichlet-Mesh" + + vertex_ids_read = participant.set_mesh_vertices( + mesh_name_read, read_sample.eval(ns.x)) + participant.set_mesh_access_region(mesh_name_write, [.9, 1.1, -.1, 1.1]) + + participant.initialize() + precice_dt = participant.get_max_time_step_size() + solver_dt = timestep + dt = min(precice_dt, solver_dt) + + vertex_ids_write, coords = participant.get_mesh_vertex_ids_and_coordinates( + mesh_name_write) + write_sample = domain.locate(ns.x, coords, eps=1e-10, tol=1e-10) + + precice_write = functools.partial( + participant.write_data, mesh_name_write, "Temperature", vertex_ids_write) + precice_read = functools.partial( + participant.read_data, mesh_name_read, "Heat-Flux", vertex_ids_read) + + t = 0. + istep = 0 + + # initial condition + sqr0 = domain.integral('(u - uexact)^2' @ ns, degree=degree * 2) + lhs = solver.optimize('lhs', sqr0, arguments=dict(t=t)) + bezier = domain.sample('bezier', degree * 2) + + while participant.is_coupling_ongoing(): + + # save checkpoint + if participant.requires_writing_checkpoint(): + checkpoint = lhs, t, istep + + # prepare next timestep + precice_dt = participant.get_max_time_step_size() + dt = min(precice_dt, solver_dt) + lhs0 = lhs + istep += 1 + t += dt + + # read data from participant + read_data = precice_read(dt) + + # update (time-dependent) boundary condition + cons = solver.optimize('lhs', sqr, droptol=1e-15, + arguments=dict(t=t, readdata=read_data)) + + # solve nutils timestep + lhs = solver.solve_linear('lhs', res, constrain=cons, arguments=dict( + lhs0=lhs0, dt=dt, t=t, readdata=read_data)) + + # write data to participant + write_data = write_sample.eval('u' @ ns, lhs=lhs) + precice_write(write_data) + + # do the coupling + participant.advance(dt) + + # read checkpoint if required + if participant.requires_reading_checkpoint(): + lhs, t, istep = checkpoint + else: + # generate output + x, u, uexact = bezier.eval( + ['x_i', 'u', 'uexact'] @ ns, lhs=lhs, t=t) + with treelog.add(treelog.DataLog()): + export.vtk("Neumann" + "-" + str(istep), bezier.tri, + x, Temperature=u, reference=uexact) + + participant.finalize() + + +if __name__ == '__main__': + cli.run(main) diff --git a/partitioned-heat-conduction-direct/neumann-nutils/requirements.txt b/partitioned-heat-conduction-direct/neumann-nutils/requirements.txt new file mode 100644 index 000000000..cfd521c81 --- /dev/null +++ b/partitioned-heat-conduction-direct/neumann-nutils/requirements.txt @@ -0,0 +1,2 @@ +nutils==7 +pyprecice==3 diff --git a/partitioned-heat-conduction-direct/neumann-nutils/run.sh b/partitioned-heat-conduction-direct/neumann-nutils/run.sh new file mode 100755 index 000000000..021225a41 --- /dev/null +++ b/partitioned-heat-conduction-direct/neumann-nutils/run.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 -m venv .venv +. .venv/bin/activate +pip install -r requirements.txt + +rm -rf Neumann-*.vtk +NUTILS_RICHOUTPUT=no python3 heat.py + +close_log diff --git a/partitioned-heat-conduction-direct/precice-config.xml b/partitioned-heat-conduction-direct/precice-config.xml new file mode 100644 index 000000000..63ab53f06 --- /dev/null +++ b/partitioned-heat-conduction-direct/precice-config.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/partitioned-heat-conduction-overlap/README.md b/partitioned-heat-conduction-overlap/README.md new file mode 100644 index 000000000..bca91a0a7 --- /dev/null +++ b/partitioned-heat-conduction-overlap/README.md @@ -0,0 +1,35 @@ +--- +title: Partitioned heat conduction with overlapping Schwarz-type domain decomposition +permalink: tutorials-partitioned-heat-conduction-overlap.html +keywords: FEniCS, heat conduction, overlap +summary: We solve a simple heat equation. The domain is partitioned and the coupling is established in an overlapping-Schwarz-type domain decomposition. +--- + +{% note %} +Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/partitioned-heat-conduction-overlap). Read how in the [tutorials introduction](https://www.precice.org/tutorials.html). +{% endnote %} + +## Setup + +We solve a partitioned heat equation, but apply an overlapping Schwarz-type domain decomposition method in this tutorial. + +![Case setup of partitioned-heat-conduction case with overlapping Schwarz-type domain decomposition](images/tutorials-partitioned-heat-conduction-overlap-setup.png) + +Note that this case applies an overlapping Schwarz-type coupling method and not (like most other tutorials in this repository) a Dirichlet-Neumann coupling. This results in a symmetric setup of the solvers. + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-partitioned-heat-conduction-overlap-precice-config.png) + +## Running the simulation + +This tutorial is for FEniCS. + +For choosing whether you want to run the left or right participant, please provide the following commandline input: + +* `python3 heat.py left` flag will run the left participant. +* `python3 heat.py right` flag will run the right participant. + +Like for the case `partitioned-heat-conduction` (using Dirichlet-Neumann coupling), we can also expect for the overlapping domain decomposition applied here to recover the analytical solution. `errorcomputation.py` checks this explicitly, by comparing the numerical to the analytical solution and raising an error, if the approximation error is not within a given tolerance. diff --git a/partitioned-heat-conduction-overlap/clean-tutorial.sh b/partitioned-heat-conduction-overlap/clean-tutorial.sh new file mode 120000 index 000000000..4713f5092 --- /dev/null +++ b/partitioned-heat-conduction-overlap/clean-tutorial.sh @@ -0,0 +1 @@ +../tools/clean-tutorial-base.sh \ No newline at end of file diff --git a/partitioned-heat-conduction-overlap/images/tutorials-partitioned-heat-conduction-overlap-precice-config.png b/partitioned-heat-conduction-overlap/images/tutorials-partitioned-heat-conduction-overlap-precice-config.png new file mode 100644 index 000000000..8addcab64 Binary files /dev/null and b/partitioned-heat-conduction-overlap/images/tutorials-partitioned-heat-conduction-overlap-precice-config.png differ diff --git a/partitioned-heat-conduction-overlap/images/tutorials-partitioned-heat-conduction-overlap-setup.pdf b/partitioned-heat-conduction-overlap/images/tutorials-partitioned-heat-conduction-overlap-setup.pdf new file mode 100644 index 000000000..92544f8f9 Binary files /dev/null and b/partitioned-heat-conduction-overlap/images/tutorials-partitioned-heat-conduction-overlap-setup.pdf differ diff --git a/partitioned-heat-conduction-overlap/images/tutorials-partitioned-heat-conduction-overlap-setup.png b/partitioned-heat-conduction-overlap/images/tutorials-partitioned-heat-conduction-overlap-setup.png new file mode 100644 index 000000000..170f70811 Binary files /dev/null and b/partitioned-heat-conduction-overlap/images/tutorials-partitioned-heat-conduction-overlap-setup.png differ diff --git a/partitioned-heat-conduction-overlap/images/tutorials-partitioned-heat-conduction-overlap-setup.tex b/partitioned-heat-conduction-overlap/images/tutorials-partitioned-heat-conduction-overlap-setup.tex new file mode 100644 index 000000000..587471edb --- /dev/null +++ b/partitioned-heat-conduction-overlap/images/tutorials-partitioned-heat-conduction-overlap-setup.tex @@ -0,0 +1,77 @@ +\documentclass{standalone} + +\usepackage{tikz} +\usetikzlibrary{fit,positioning,calc} + +\usepackage{pgfplots} +\pgfplotsset{ + compat=1.16, +} +\usepgfplotslibrary{external} +\tikzexternalize[ + only named, +] + +\definecolor{pblue}{RGB}{0,102,189} % precice blue +\definecolor{porange}{RGB}{243,98,33} % precice orange + +% Make the 'export as png' a seperate style, with default density 200 +\tikzset{ + export as png/.style={ + external/system call/.add={}{ + && convert -density #1 -transparent white "\image.pdf" "\image.png" + }, + }, + export as png/.default={200}, +} + +\begin{document} + +\tikzset{export as png} +\tikzsetnextfilename{tutorials-partitioned-heat-conduction-schwarz-setup} +\begin{tikzpicture} + \draw + (0,0) coordinate (a) + rectangle + ++(3,3) coordinate (b); + \node[fill=pblue!50, draw=black, fit=(a) (b),inner sep=0pt] (participantL) {$\Omega_\mathcal{L}$}; + + \draw + ($(participantL.south east)+(2,0)$) coordinate (a) + rectangle + ++(3,3) coordinate (b); + \node[fill=porange!50, draw=black, fit=(a) (b),inner sep=0pt] (participantR) {$\Omega_\mathcal{R}$}; + + \draw + ($(participantL.south east)-(1,0)$) coordinate (a) + rectangle + ($(participantL.north east)$) coordinate (b); + \node[fill=porange!50,opacity=0.5, fit=(a) (b),inner sep=0pt] (overlapL){}; + + \draw + ($(participantR.south west)+(1,0)$) coordinate (a) + rectangle + ($(participantR.north west)$) coordinate (b); + \node[fill=pblue!50,opacity=0.5, fit=(a) (b),inner sep=0pt] (overlapR){}; + + \node[below = 0.5cm of participantR,xshift=-0.2cm](overlapLabel){Overlapping region: $\Omega_\mathcal{R}\cap\Omega_\mathcal{L}$}; + \draw[dashed] ([yshift=-.5cm]overlapL.center) -- (overlapLabel); + \draw[dashed] ([yshift=-.5cm]overlapR.center) -- (overlapLabel); + + \draw[very thick, pblue]($(participantL.south east)-(1,0)$) -- ($(participantL.north east)-(1,0)$); + \draw[very thick, porange]($(participantR.south west)+(1,0)$) -- ($(participantR.north west)+(1,0)$); + + \draw[very thick, porange](participantL.south east) -- node[right]{$\Gamma_\mathcal{R}$}($(participantL.north east)$); + \draw[very thick, pblue](participantR.south west) -- node[left]{$\Gamma_\mathcal{L}$} ($(participantR.north west)$); + + \node[left = 0cm of participantL,align=center] {Dirichlet solver $\mathcal{L}$\\ acts on left part $\Omega_\mathcal{L}$}; + \node[right = 0cm of participantR,align=center] {Dirichlet solver $\mathcal{R}$\\ acts on right part $\Omega_\mathcal{R}$}; + + \draw[->]($(participantR.north west)+(1,0)$) to[out=150,in=30] node[above right,align=center]{Temperature $u$ on $\Gamma_\mathcal{R}$ for $\mathcal{L}$} (participantL.north east); + \draw[->]($(participantL.north east)-(1,0)$) to[out=30,in=150] node[above left,align=center]{Temperature $u$ on $\Gamma_\mathcal{L}$ for $\mathcal{R}$} (participantR.north west); + + \draw[draw=none] (participantL.south east) -- node[below]{$\Gamma_D$} (participantL.south west); + \draw[draw=none] (participantR.south east) -- node[below]{$\Gamma_D$} (participantR.south west); +\end{tikzpicture} + +\end{document} \ No newline at end of file diff --git a/volume-coupled-diffusion/fenics/clean.sh b/partitioned-heat-conduction-overlap/left-fenics/clean.sh similarity index 100% rename from volume-coupled-diffusion/fenics/clean.sh rename to partitioned-heat-conduction-overlap/left-fenics/clean.sh diff --git a/partitioned-heat-conduction-overlap/left-fenics/precice-adapter-config.json b/partitioned-heat-conduction-overlap/left-fenics/precice-adapter-config.json new file mode 100644 index 000000000..db25313f4 --- /dev/null +++ b/partitioned-heat-conduction-overlap/left-fenics/precice-adapter-config.json @@ -0,0 +1,9 @@ +{ + "participant_name": "Left", + "config_file_name": "../precice-config.xml", + "interface": { + "coupling_mesh_name": "Left-Mesh", + "write_data_name": "Temperature-Left", + "read_data_name": "Temperature-Right" + } +} diff --git a/partitioned-heat-conduction-overlap/left-fenics/run.sh b/partitioned-heat-conduction-overlap/left-fenics/run.sh new file mode 100755 index 000000000..df525cc51 --- /dev/null +++ b/partitioned-heat-conduction-overlap/left-fenics/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 ../solver-fenics/heat.py Left + +close_log diff --git a/partitioned-heat-conduction-overlap/precice-config.xml b/partitioned-heat-conduction-overlap/precice-config.xml new file mode 100644 index 000000000..5e28ab51a --- /dev/null +++ b/partitioned-heat-conduction-overlap/precice-config.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/partitioned-heat-conduction-overlap/right-fenics/clean.sh b/partitioned-heat-conduction-overlap/right-fenics/clean.sh new file mode 100755 index 000000000..3a8b4619d --- /dev/null +++ b/partitioned-heat-conduction-overlap/right-fenics/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_fenics . diff --git a/partitioned-heat-conduction-overlap/right-fenics/precice-adapter-config.json b/partitioned-heat-conduction-overlap/right-fenics/precice-adapter-config.json new file mode 100644 index 000000000..8409f0b2b --- /dev/null +++ b/partitioned-heat-conduction-overlap/right-fenics/precice-adapter-config.json @@ -0,0 +1,9 @@ +{ + "participant_name": "Right", + "config_file_name": "../precice-config.xml", + "interface": { + "coupling_mesh_name": "Right-Mesh", + "write_data_name": "Temperature-Right", + "read_data_name": "Temperature-Left" + } +} diff --git a/partitioned-heat-conduction-overlap/right-fenics/run.sh b/partitioned-heat-conduction-overlap/right-fenics/run.sh new file mode 100755 index 000000000..ae72b4d1b --- /dev/null +++ b/partitioned-heat-conduction-overlap/right-fenics/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 ../solver-fenics/heat.py Right + +close_log diff --git a/partitioned-heat-conduction/fenics/errorcomputation.py b/partitioned-heat-conduction-overlap/solver-fenics/errorcomputation.py similarity index 100% rename from partitioned-heat-conduction/fenics/errorcomputation.py rename to partitioned-heat-conduction-overlap/solver-fenics/errorcomputation.py diff --git a/partitioned-heat-conduction-overlap/solver-fenics/heat.py b/partitioned-heat-conduction-overlap/solver-fenics/heat.py new file mode 100644 index 000000000..d532c756c --- /dev/null +++ b/partitioned-heat-conduction-overlap/solver-fenics/heat.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python +# coding: utf-8 + +# 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 to allow for an alternating Schwarz overlapping coupling of two separate heat equations. +# +# The original source code can be found on https://github.com/hplgit/fenics-tutorial/blob/master/pub/python/vol1/ft03_heat.py. +# +# Heat equation with Dirichlet conditions. (Dirichlet problem, $f_N = \mathcal{D}\left(u_C\right)$) +# +# \begin{align*} +# \frac{\partial u}{\partial t} &= \Delta u + f && \text{on the domain $\Omega = \left[0,1+\delta\right] \times \left[0,1\right]$}\\ +# u &= u_C && \text{on the coupling boundary $\Gamma_C$ at $x = 1+\delta$}\\ +# u &= u_D && \text{on the remaining boundary $\Gamma = \partial \Omega \setminus \Gamma_C$}\\ +# u &= u_0 && \text{on $\Omega$ at t = 0}\\ +# u &= 1 + x^2 + \alpha y^2 + \beta t \\ +# f &= \beta - 2 - 2\alpha \\ +# \end{align*} +# +# Similarly a second heat equation is defined on $\Omega = \left[1-\delta,2\right]$ with dirichlet boundary conditions applied at $1-\delta$. +# The alternating Schwarz method is applied in the overlap domain where $x \in \left[1-\delta, 1+\delta\right]$. + +from __future__ import print_function, division +from fenics import Function, FunctionSpace, Expression, Constant, DirichletBC, TrialFunction, TestFunction, File, solve, lhs, rhs, grad, inner, dot, dx, ds, interpolate +from fenics import SubDomain, Point, RectangleMesh, near, Function, Expression +from fenicsprecice import Adapter +from errorcomputation import compute_errors +import argparse +import numpy as np +from dolfin import dot +from enum import Enum +import sys + + +class Participant(Enum): + """ + Enum defines which part of the domain [x_left, x_right] x [y_bottom, y_top] we compute. + """ + LEFT = "Left" # left part of domain in simple interface case + RIGHT = "Right" # right part of domain in simple interface case + + +parser = argparse.ArgumentParser(description="Solving heat equation with Schwarz type domain decomposition") +parser.add_argument("participantName", help="Name of the solver.", type=str, choices=[p.value for p in Participant]) +args = parser.parse_args() + +fenics_dt = .1 # time step size +# Error is bounded by coupling accuracy. In theory we would obtain the analytical solution. +error_tol = 10**-6 +alpha = 3 # parameter alpha +beta = 1.3 # parameter beta + +participant_name = args.participantName + +y_bottom, y_top = 0, 1 +x_left, x_right = 0, 2 +# x coordinate of coupling interface; for Schwarz Domain Decomposition coupling interface sits between The DoFs. +x_coupling = 1.0 + +overlap_cells = 1 + +nx = 9 + overlap_cells +ny = 9 +hx = (x_right - x_left) / (2 * nx - overlap_cells) + + +if participant_name == Participant.LEFT.value: + p0 = Point(x_left, y_bottom) + # rightmost point is the DoF hx/2 right of the coupling interface that belongs to the Right participant + x_schwarz_read = x_coupling + hx * (overlap_cells * 0.5) + x_schwarz_write = x_coupling - hx * (overlap_cells * 0.5) + p1 = Point(x_schwarz_read, y_top) +elif participant_name == Participant.RIGHT.value: + # leftmost point is the DoF hx/2 left of the coupling interface that belongs to the Left participant + x_schwarz_read = x_coupling - hx * (overlap_cells * 0.5) + x_schwarz_write = x_coupling + hx * (overlap_cells * 0.5) + p0 = Point(x_schwarz_read, y_bottom) + p1 = Point(x_right, y_top) + + +class ExcludeStraightBoundary(SubDomain): + def get_user_input_args(self, args): + self._interface = args.interface + + def inside(self, x, on_boundary): + tol = 1E-14 + if on_boundary and not near(x[0], x_schwarz_read, tol) or near(x[1], y_top, tol) or near(x[1], y_bottom, tol): + return True + else: + return False + + +class OverlapDomain(SubDomain): + def inside(self, x, on_boundary): + tol = 1E-14 + if (x[0] <= x_coupling + hx * (overlap_cells * 0.5) + tol) and (x[0] >= x_coupling - + hx * (overlap_cells - 0.5) - tol): # Point lies inside of overlapping domain + return True + else: + return False + + +class ReadBoundary(SubDomain): + def inside(self, x, on_boundary): + tol = 1E-14 + if on_boundary and near(x[0], x_schwarz_read, tol): + return True + else: + return False + + +class WriteBoundary(SubDomain): + def inside(self, x, on_boundary): + tol = 1E-14 + if near(x[0], x_schwarz_write, tol): # Point lies inside of the domain! + return True + else: + return False + + +mesh = RectangleMesh(p0, p1, nx, ny, diagonal="left") +read_boundary = ReadBoundary() +write_boundary = WriteBoundary() +remaining_boundary = ExcludeStraightBoundary() + + +# Define function space using mesh +V = FunctionSpace(mesh, 'P', 2) + +# Define boundary conditions +u_D = Expression('1 + x[0]*x[0] + alpha*x[1]*x[1] + beta*t', degree=2, alpha=alpha, beta=beta, t=0) +u_D_function = interpolate(u_D, V) + +# Define initial value +u_n = interpolate(u_D, V) +u_n.rename("Temperature", "") + + +precice, precice_dt, initial_data = None, 0.0, None + +# Initialize the adapter according to the specific participant +precice = Adapter(adapter_config_filename="precice-adapter-config.json") + +precice.initialize(OverlapDomain(), read_function_space=V, write_object=u_D_function) + +precice_dt = precice.get_max_time_step_size() +dt = Constant(0) +dt.assign(np.min([fenics_dt, precice_dt])) + +# Define variational problem +u = TrialFunction(V) +v = TestFunction(V) +f = Expression('beta - 2 - 2*alpha', degree=2, alpha=alpha, beta=beta, t=0) +F = u * v / dt * dx + dot(grad(u), grad(v)) * dx - (u_n / dt + f) * v * dx + +bcs = [DirichletBC(V, u_D, remaining_boundary)] +coupling_expression = precice.create_coupling_expression() +bcs.append(DirichletBC(V, coupling_expression, read_boundary)) + +a, L = lhs(F), rhs(F) + +# Time-stepping +u_np1 = Function(V) +u_np1.rename("Temperature", "") +t = 0 + +# reference solution at t=0 +u_ref = interpolate(u_D, V) +u_ref.rename("reference", " ") + +# Generating output files +temperature_out = File("output/%s.pvd" % precice.get_participant_name()) +ref_out = File("output/ref%s.pvd" % precice.get_participant_name()) +error_out = File("output/error%s.pvd" % precice.get_participant_name()) + +# output solution and reference solution at t=0, n=0 +n = 0 +print('output u^%d and u_ref^%d' % (n, n)) +temperature_out << u_n +ref_out << u_ref + +error_total, error_pointwise = compute_errors(u_n, u_ref, V) +error_out << error_pointwise + +# set t_1 = t_0 + dt, this gives u_D^1 +# call dt(0) to evaluate FEniCS Constant. Todo: is there a better way? +u_D.t = t + dt(0) +f.t = t + dt(0) + +while precice.is_coupling_ongoing(): + + # write checkpoint + if precice.requires_writing_checkpoint(): + precice.store_checkpoint(u_n, t, n) + + precice_dt = precice.get_max_time_step_size() + dt.assign(np.min([fenics_dt, precice_dt])) + + read_data = precice.read_data(dt) + + # Update the coupling expression with the new read data + precice.update_coupling_expression(coupling_expression, read_data) + + # Compute solution u^n+1, use bcs u_D^n+1, u^n and coupling bcs + solve(a == L, u_np1, bcs) + + precice.write_data(u_np1) + + precice_dt = precice.advance(dt(0)) + + # roll back to checkpoint + if precice.requires_reading_checkpoint(): + u_cp, t_cp, n_cp = precice.retrieve_checkpoint() + u_n.assign(u_cp) + t = t_cp + n = n_cp + else: # update solution + u_n.assign(u_np1) + t += float(dt) + n += 1 + + if precice.is_time_window_complete(): + u_ref = interpolate(u_D, V) + u_ref.rename("reference", " ") + error, error_pointwise = compute_errors(u_n, u_ref, V, total_error_tol=error_tol) + print('n = %d, t = %.2f: L2 error on domain = %.3g' % (n, t, error)) + # output solution and reference solution at t_n+1 + print('output u^%d and u_ref^%d' % (n, n)) + + temperature_out << u_np1 + ref_out << u_ref + error_out << error_pointwise + + # Update Dirichlet BC + u_D.t = t + float(dt) + f.t = t + float(dt) + +# Hold plot +precice.finalize() diff --git a/partitioned-heat-conduction/README.md b/partitioned-heat-conduction/README.md index 118cfa4f6..af5624fe5 100644 --- a/partitioned-heat-conduction/README.md +++ b/partitioned-heat-conduction/README.md @@ -21,19 +21,25 @@ The heat equation is solved on a rectangular domain `Omega = [0,2] x [0,1]` with This simple case allows us to compare the solution for the partitioned case to a known analytical solution (method of manufactures solutions, see [1, p.37ff]). For more usage examples and details, please refer to [3, sect. 4.1]. +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-partitioned-heat-conduction-precice-config.png) + ## 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. * FEniCS. Install [FEniCS](https://fenicsproject.org/download/) 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]. -* Nutils. Install [Nutils](http://www.nutils.org/en/latest/). +* Nutils. Install [Nutils](https://nutils.org/install-nutils.html). -* OpenFOAM. This case also requires [funkySetFields](https://openfoamwiki.net/index.php/Contrib/funkySetFields) (part of [swak4Foam](https://openfoamwiki.net/index.php/Contrib/swak4Foam)) and uses the custom [heatTransfer](https://github.com/precice/tutorials/blob/master/partitioned-heat-conduction/openfoam-solver/heatTransfer.C) solver (find it in `openfoam-solver` and build with `wmake`). Read more details in the [OpenFOAM adapter](https://precice.org/adapter-openfoam-overview.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). ## Running the simulation -This tutorial is for FEniCS and Nutils. You can find the corresponding `run.sh` script in the folders `fenics` and `nutils`. +You can find the corresponding `run.sh` script for running the case in the folders corresponding to the solver you want to use. For choosing whether you want to run the Dirichlet-kind and a Neumann-kind participant, please provide the following commandline input: @@ -54,7 +60,7 @@ cd fenics ./run.sh -n ``` -If you want to use Nutils for one or both sides of the setup, just `cd nutils`. The FEniCS case also supports parallel runs. Here, you cannot use the `run.sh` script, but must simply execute +If you want to use Nutils, use `cd nutils` instead of `cd fenics`. The FEniCS case also supports parallel runs. Here, you cannot use the `run.sh` script, but must simply execute ```bash mpirun -n heat.py -d diff --git a/partitioned-heat-conduction/dirichlet-fenics/clean.sh b/partitioned-heat-conduction/dirichlet-fenics/clean.sh new file mode 100755 index 000000000..3a8b4619d --- /dev/null +++ b/partitioned-heat-conduction/dirichlet-fenics/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_fenics . diff --git a/partitioned-heat-conduction/fenics/precice-adapter-config-D.json b/partitioned-heat-conduction/dirichlet-fenics/precice-adapter-config.json similarity index 100% rename from partitioned-heat-conduction/fenics/precice-adapter-config-D.json rename to partitioned-heat-conduction/dirichlet-fenics/precice-adapter-config.json diff --git a/partitioned-heat-conduction/dirichlet-fenics/run.sh b/partitioned-heat-conduction/dirichlet-fenics/run.sh new file mode 100755 index 000000000..874a00a5a --- /dev/null +++ b/partitioned-heat-conduction/dirichlet-fenics/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 ../solver-fenics/heat.py Dirichlet + +close_log diff --git a/partitioned-heat-conduction/dirichlet-nutils/clean.sh b/partitioned-heat-conduction/dirichlet-nutils/clean.sh new file mode 100755 index 000000000..6893c1ea5 --- /dev/null +++ b/partitioned-heat-conduction/dirichlet-nutils/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_nutils . diff --git a/partitioned-heat-conduction/dirichlet-nutils/heat.py b/partitioned-heat-conduction/dirichlet-nutils/heat.py new file mode 100644 index 000000000..dc80100e6 --- /dev/null +++ b/partitioned-heat-conduction/dirichlet-nutils/heat.py @@ -0,0 +1,167 @@ +#! /usr/bin/env python3 + +from nutils import cli, mesh, function, solver, export +import functools +import treelog +import numpy as np +import precice + + +def main(n=10, degree=1, timestep=.1, alpha=3., beta=1.2): + + x_grid = np.linspace(0, 1, n) + y_grid = np.linspace(0, 1, n) + + # define the Nutils mesh + domain, geom = mesh.rectilinear([x_grid, y_grid]) + coupling_boundary = domain.boundary['right'] + coupling_sample = coupling_boundary.sample('gauss', degree=degree * 2) + + # Nutils namespace + ns = function.Namespace() + ns.x = geom + ns.basis = domain.basis('std', degree=degree) + ns.alpha = alpha # parameter of problem + ns.beta = beta # parameter of problem + ns.u = 'basis_n ?lhs_n' # solution + ns.dudt = 'basis_n (?lhs_n - ?lhs0_n) / ?dt' # time derivative + ns.flux = 'basis_n ?fluxdofs_n' # heat flux + ns.f = 'beta - 2 - 2 alpha' # rhs + ns.uexact = '1 + x_0 x_0 + alpha x_1 x_1 + beta ?t' # analytical solution + ns.readbasis = coupling_sample.basis() + ns.readfunc = 'readbasis_n ?readdata_n' + + # define the weak form + res = domain.integral( + '(basis_n dudt - basis_n f + basis_n,i u_,i) d:x' @ ns, + degree=degree * 2) + + # set boundary conditions at non-coupling boundaries + # top and bottom boundary are non-coupling for both sides + sqr = domain.boundary['top,bottom,left'].integral('(u - uexact)^2 d:x' @ ns, degree=degree * 2) + + sqr += coupling_sample.integral('(u - readfunc)^2 d:x' @ ns) + + # preCICE setup + participant = precice.Participant('Dirichlet', "../precice-config.xml", 0, 1) + mesh_name = "Dirichlet-Mesh" + vertex_ids = participant.set_mesh_vertices( + mesh_name, coupling_sample.eval(ns.x)) + precice_write = functools.partial( + participant.write_data, + mesh_name, + "Heat-Flux", + vertex_ids) + precice_read = functools.partial( + participant.read_data, + mesh_name, + "Temperature", + vertex_ids) + + # helper functions to project heat flux to coupling boundary + # To communicate the flux to the Neumann side we should not simply + # evaluate u_,i n_i as this is an unbounded term leading to suboptimal + # convergence. Instead we project ∀ v: ∫_Γ v flux = ∫_Γ v u_,i n_i and + # evaluate flux. While the right-hand-side contains the same unbounded + # term, we can use the strong identity du/dt - u_,ii = f to rewrite it + # to ∫_Ω [v (du/dt - f) + v_,i u_,i] - ∫_∂Ω\Γ v u_,k n_k, in which we + # recognize the residual and an integral over the exterior boundary. + # While the latter still contains the problematic unbounded term, we + # can use the fact that the flux is a known value at the top and bottom + # via the Dirichlet boundary condition, and impose it as constraints. + rightsqr = domain.boundary['right'].integral( + 'flux^2 d:x' @ ns, degree=degree * 2) + rightcons = solver.optimize('fluxdofs', rightsqr, droptol=1e-10) + # rightcons is NaN in dofs that are NOT supported on the right boundary + fluxsqr = domain.boundary['right'].boundary['top,bottom'].integral( + '(flux - uexact_,0)^2 d:x' @ ns, degree=degree * 2) + fluxcons = solver.optimize('fluxdofs', + fluxsqr, + droptol=1e-10, + constrain=np.choose(np.isnan(rightcons), + [np.nan, + 0.])) + # fluxcons is NaN in dofs that are supported on ONLY the right boundary + fluxres = coupling_sample.integral('basis_n flux d:x' @ ns) - res + + # write initial data + if participant.requires_initial_data(): + precice_write(coupling_sample.eval(0.)) + + participant.initialize() + precice_dt = participant.get_max_time_step_size() + solver_dt = timestep + dt = min(precice_dt, solver_dt) + + t = 0. + istep = 0 + + # initial condition + sqr0 = domain.integral('(u - uexact)^2' @ ns, degree=degree * 2) + lhs = solver.optimize('lhs', sqr0, arguments=dict(t=t)) + bezier = domain.sample('bezier', degree * 2) + + while True: + + # generate output + x, u, uexact = bezier.eval(['x_i', 'u', 'uexact'] @ ns, lhs=lhs, t=t) + with treelog.add(treelog.DataLog()): + export.vtk( + "Dirichlet-" + + str(istep), + bezier.tri, + x, + Temperature=u, + reference=uexact) + + if not participant.is_coupling_ongoing(): + break + + # save checkpoint + if participant.requires_writing_checkpoint(): + checkpoint = lhs, t, istep + + # prepare next timestep + precice_dt = participant.get_max_time_step_size() + dt = min(solver_dt, precice_dt) + lhs0 = lhs + istep += 1 + # read data from participant + readdata = precice_read(dt) + t += dt + + # update (time-dependent) boundary condition + cons = solver.optimize( + 'lhs', + sqr, + droptol=1e-15, + arguments=dict( + t=t, + readdata=readdata)) + + # solve nutils timestep + lhs = solver.solve_linear( + 'lhs', res, constrain=cons, arguments=dict( + lhs0=lhs0, dt=dt, t=t, readdata=readdata)) + + # write data to participant + fluxdofs = solver.solve_linear( + 'fluxdofs', fluxres, arguments=dict( + lhs0=lhs0, lhs=lhs, dt=dt, t=t), constrain=fluxcons) + write_data = coupling_sample.eval( + 'flux' @ ns, fluxdofs=fluxdofs) + + precice_write(write_data) + + # do the coupling + participant.advance(dt) + + # read checkpoint if required + if participant.requires_reading_checkpoint(): + lhs, t, istep = checkpoint + + participant.finalize() + + +if __name__ == '__main__': + cli.run(main) diff --git a/partitioned-heat-conduction/dirichlet-nutils/requirements.txt b/partitioned-heat-conduction/dirichlet-nutils/requirements.txt new file mode 100644 index 000000000..cfd521c81 --- /dev/null +++ b/partitioned-heat-conduction/dirichlet-nutils/requirements.txt @@ -0,0 +1,2 @@ +nutils==7 +pyprecice==3 diff --git a/partitioned-heat-conduction/dirichlet-nutils/run.sh b/partitioned-heat-conduction/dirichlet-nutils/run.sh new file mode 100755 index 000000000..e5743798a --- /dev/null +++ b/partitioned-heat-conduction/dirichlet-nutils/run.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 -m venv .venv +. .venv/bin/activate +pip install -r requirements.txt + +rm -rf Dirichlet-*.vtk +NUTILS_RICHOUTPUT=no python3 heat.py + +close_log diff --git a/partitioned-heat-conduction/dirichlet-openfoam/0/T b/partitioned-heat-conduction/dirichlet-openfoam/0/T new file mode 100644 index 000000000..71a73de7f --- /dev/null +++ b/partitioned-heat-conduction/dirichlet-openfoam/0/T @@ -0,0 +1,84 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} + +dimensions [0 0 0 1 0 0 0]; + + +internalField nonuniform #codeStream +{ + codeInclude + #{ + #include "fvCFD.H" + #}; + + codeOptions + #{ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude + #}; + + codeLibs + #{ + -lmeshTools \ + -lfiniteVolume + #}; + + code + + #{ + const IOdictionary& d = static_cast(dict); + const fvMesh& mesh = refCast(d.db()); + const vectorField& CC = mesh.C(); // cell center + + // assign values + scalarField T(mesh.nCells()); + forAll(CC, cellI) + { + scalar x = CC[cellI].x(); + scalar y = CC[cellI].y(); + + T[cellI] = 1 + pow(x, 2) + (3 * pow(y, 2)); // t is zero for initial conditions + } + os << T; + #}; +}; + +boundaryField +{ + interface + { + type fixedValue; + value uniform 2; + } + + DirichletBoundary + { + type codedFixedValue; + value uniform 1; + name DirichletBoundary; + code + #{ + const vectorField& Cf = patch().Cf(); + const scalar t = this->db().time().value(); + + scalarField& field = *this; + forAll(Cf, faceI) + { + const scalar x = Cf[faceI].x(); + const scalar y = Cf[faceI].y(); + + field[faceI] = 1 + pow(x, 2) + (3 * pow(y, 2)) + 1.2 * t; + } + #}; + } + + defaultFaces + { + type empty; + } +} diff --git a/partitioned-heat-conduction/dirichlet-openfoam/clean.sh b/partitioned-heat-conduction/dirichlet-openfoam/clean.sh new file mode 100755 index 000000000..c31d9fc76 --- /dev/null +++ b/partitioned-heat-conduction/dirichlet-openfoam/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . diff --git a/partitioned-heat-conduction/openfoam-dirichlet/constant/physicalProperties b/partitioned-heat-conduction/dirichlet-openfoam/constant/physicalProperties similarity index 100% rename from partitioned-heat-conduction/openfoam-dirichlet/constant/physicalProperties rename to partitioned-heat-conduction/dirichlet-openfoam/constant/physicalProperties diff --git a/partitioned-heat-conduction/openfoam-neumann/constant/physicalProperties b/partitioned-heat-conduction/dirichlet-openfoam/constant/transportProperties similarity index 100% rename from partitioned-heat-conduction/openfoam-neumann/constant/physicalProperties rename to partitioned-heat-conduction/dirichlet-openfoam/constant/transportProperties diff --git a/partitioned-heat-conduction/dirichlet-openfoam/run.sh b/partitioned-heat-conduction/dirichlet-openfoam/run.sh new file mode 100755 index 000000000..da82a9ba2 --- /dev/null +++ b/partitioned-heat-conduction/dirichlet-openfoam/run.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/partitioned-heat-conduction/openfoam-dirichlet/system/blockMeshDict b/partitioned-heat-conduction/dirichlet-openfoam/system/blockMeshDict similarity index 100% rename from partitioned-heat-conduction/openfoam-dirichlet/system/blockMeshDict rename to partitioned-heat-conduction/dirichlet-openfoam/system/blockMeshDict diff --git a/partitioned-heat-conduction/openfoam-dirichlet/system/controlDict b/partitioned-heat-conduction/dirichlet-openfoam/system/controlDict similarity index 74% rename from partitioned-heat-conduction/openfoam-dirichlet/system/controlDict rename to partitioned-heat-conduction/dirichlet-openfoam/system/controlDict index 31a7ba62d..c63fa7760 100644 --- a/partitioned-heat-conduction/openfoam-dirichlet/system/controlDict +++ b/partitioned-heat-conduction/dirichlet-openfoam/system/controlDict @@ -7,12 +7,10 @@ FoamFile } // Make sure you build the solver located -// in ../../openfoam-solver/ before running +// in ../../solver-openfoam/ before running // the case application heatTransfer; -libs ( "libgroovyBC.so" ) ; - startFrom startTime; startTime 0; @@ -21,10 +19,12 @@ stopAt endTime; endTime 1; -deltaT 0.1; +deltaT 0.01; writeControl runTime; +// Write data only at the end of each coupling time window +// Intermediate time step results correspond to the first coupling iteration and are not converged. writeInterval 0.1; purgeWrite 0; diff --git a/partitioned-heat-conduction/dirichlet-openfoam/system/decomposeParDict b/partitioned-heat-conduction/dirichlet-openfoam/system/decomposeParDict new file mode 100644 index 000000000..ad99cf6c5 --- /dev/null +++ b/partitioned-heat-conduction/dirichlet-openfoam/system/decomposeParDict @@ -0,0 +1,16 @@ +FoamFile { + version 2.0; + class dictionary; + object decomposeParDict; + format ascii; +} + +numberOfSubdomains 2; + +method simple; + +simpleCoeffs +{ + n (2 1 1); + delta 0.001; +} diff --git a/partitioned-heat-conduction/openfoam-dirichlet/system/fvSchemes b/partitioned-heat-conduction/dirichlet-openfoam/system/fvSchemes similarity index 100% rename from partitioned-heat-conduction/openfoam-dirichlet/system/fvSchemes rename to partitioned-heat-conduction/dirichlet-openfoam/system/fvSchemes diff --git a/partitioned-heat-conduction/openfoam-neumann/system/fvSolution b/partitioned-heat-conduction/dirichlet-openfoam/system/fvSolution similarity index 89% rename from partitioned-heat-conduction/openfoam-neumann/system/fvSolution rename to partitioned-heat-conduction/dirichlet-openfoam/system/fvSolution index 7da9a801a..0505de916 100644 --- a/partitioned-heat-conduction/openfoam-neumann/system/fvSolution +++ b/partitioned-heat-conduction/dirichlet-openfoam/system/fvSolution @@ -12,7 +12,7 @@ solvers { solver PCG; preconditioner DIC; - tolerance 1e-12; + tolerance 1e-10; relTol 0; } } diff --git a/partitioned-heat-conduction/openfoam-dirichlet/system/preciceDict b/partitioned-heat-conduction/dirichlet-openfoam/system/preciceDict similarity index 100% rename from partitioned-heat-conduction/openfoam-dirichlet/system/preciceDict rename to partitioned-heat-conduction/dirichlet-openfoam/system/preciceDict diff --git a/partitioned-heat-conduction/fenics/run.sh b/partitioned-heat-conduction/fenics/run.sh deleted file mode 100755 index e51fb750b..000000000 --- a/partitioned-heat-conduction/fenics/run.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -set -e -u - -usage() { echo "Usage: cmd [-d] [-n]" 1>&2; exit 1; } - -# Check if no input argument was provided -if [ -z "$*" ] ; then - usage -fi - -# Select appropriate case -while getopts ":dn" opt; do - case ${opt} in - d) - python3 heat.py -d --error-tol 10e-3 - ;; - n) - python3 heat.py -n --error-tol 10e-3 - ;; - *) - usage - ;; - esac -done diff --git a/partitioned-heat-conduction/images/tutorials-partitioned-heat-conduction-precice-config.png b/partitioned-heat-conduction/images/tutorials-partitioned-heat-conduction-precice-config.png new file mode 100644 index 000000000..fc371839d Binary files /dev/null and b/partitioned-heat-conduction/images/tutorials-partitioned-heat-conduction-precice-config.png differ diff --git a/partitioned-heat-conduction/neumann-fenics/clean.sh b/partitioned-heat-conduction/neumann-fenics/clean.sh new file mode 100755 index 000000000..3a8b4619d --- /dev/null +++ b/partitioned-heat-conduction/neumann-fenics/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_fenics . diff --git a/partitioned-heat-conduction/fenics/precice-adapter-config-N.json b/partitioned-heat-conduction/neumann-fenics/precice-adapter-config.json similarity index 100% rename from partitioned-heat-conduction/fenics/precice-adapter-config-N.json rename to partitioned-heat-conduction/neumann-fenics/precice-adapter-config.json diff --git a/partitioned-heat-conduction/neumann-fenics/run.sh b/partitioned-heat-conduction/neumann-fenics/run.sh new file mode 100755 index 000000000..8c02791c1 --- /dev/null +++ b/partitioned-heat-conduction/neumann-fenics/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 ../solver-fenics/heat.py Neumann + +close_log diff --git a/partitioned-heat-conduction/neumann-nutils/clean.sh b/partitioned-heat-conduction/neumann-nutils/clean.sh new file mode 100755 index 000000000..6893c1ea5 --- /dev/null +++ b/partitioned-heat-conduction/neumann-nutils/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_nutils . diff --git a/partitioned-heat-conduction/neumann-nutils/heat.py b/partitioned-heat-conduction/neumann-nutils/heat.py new file mode 100644 index 000000000..4f4f06774 --- /dev/null +++ b/partitioned-heat-conduction/neumann-nutils/heat.py @@ -0,0 +1,136 @@ +#! /usr/bin/env python3 + +from nutils import cli, mesh, function, solver, export +import functools +import treelog +import numpy as np +import precice + + +def main(n=10, degree=1, timestep=.1, alpha=3., beta=1.2): + + x_grid = np.linspace(1, 2, n) + y_grid = np.linspace(0, 1, n) + + # define the Nutils mesh + domain, geom = mesh.rectilinear([x_grid, y_grid]) + coupling_boundary = domain.boundary['left'] + coupling_sample = coupling_boundary.sample('gauss', degree=degree * 2) + + # Nutils namespace + ns = function.Namespace() + ns.x = geom + ns.basis = domain.basis('std', degree=degree) + ns.alpha = alpha # parameter of problem + ns.beta = beta # parameter of problem + ns.u = 'basis_n ?lhs_n' # solution + ns.dudt = 'basis_n (?lhs_n - ?lhs0_n) / ?dt' # time derivative + ns.flux = 'basis_n ?fluxdofs_n' # heat flux + ns.f = 'beta - 2 - 2 alpha' # rhs + ns.uexact = '1 + x_0 x_0 + alpha x_1 x_1 + beta ?t' # analytical solution + ns.readbasis = coupling_sample.basis() + ns.readfunc = 'readbasis_n ?readdata_n' + + # define the weak form + res = domain.integral( + '(basis_n dudt - basis_n f + basis_n,i u_,i) d:x' @ ns, + degree=degree * 2) + + # set boundary conditions at non-coupling boundaries + # top and bottom boundary are non-coupling for both sides + sqr = domain.boundary['top,bottom,right'].integral('(u - uexact)^2 d:x' @ ns, degree=degree * 2) + + res += coupling_sample.integral('basis_n readfunc d:x' @ ns) + + # preCICE setup + participant = precice.Participant("Neumann", "../precice-config.xml", 0, 1) + mesh_name = "Neumann-Mesh" + vertex_ids = participant.set_mesh_vertices( + mesh_name, coupling_sample.eval(ns.x)) + precice_write = functools.partial( + participant.write_data, + mesh_name, + "Temperature", + vertex_ids) + precice_read = functools.partial( + participant.read_data, + mesh_name, + "Heat-Flux", + vertex_ids) + + # write initial data + if participant.requires_initial_data(): + precice_write(coupling_sample.eval(0.)) + + participant.initialize() + precice_dt = participant.get_max_time_step_size() + solver_dt = timestep + dt = min(precice_dt, solver_dt) + + t = 0. + istep = 0 + + # initial condition + sqr0 = domain.integral('(u - uexact)^2' @ ns, degree=degree * 2) + lhs = solver.optimize('lhs', sqr0, arguments=dict(t=t)) + bezier = domain.sample('bezier', degree * 2) + + while True: + + # generate output + x, u, uexact = bezier.eval(['x_i', 'u', 'uexact'] @ ns, lhs=lhs, t=t) + with treelog.add(treelog.DataLog()): + export.vtk( + "Neumann-" + + str(istep), + bezier.tri, + x, + Temperature=u, + reference=uexact) + + if not participant.is_coupling_ongoing(): + break + + # save checkpoint + if participant.requires_writing_checkpoint(): + checkpoint = lhs, t, istep + + # prepare next timestep + precice_dt = participant.get_max_time_step_size() + dt = min(solver_dt, precice_dt) + lhs0 = lhs + istep += 1 + # read data from participant + readdata = precice_read(dt) + t += dt + + # update (time-dependent) boundary condition + cons = solver.optimize( + 'lhs', + sqr, + droptol=1e-15, + arguments=dict( + t=t, + readdata=readdata)) + + # solve nutils timestep + lhs = solver.solve_linear( + 'lhs', res, constrain=cons, arguments=dict( + lhs0=lhs0, dt=dt, t=t, readdata=readdata)) + + # write data to participant + write_data = coupling_sample.eval('u' @ ns, lhs=lhs) + precice_write(write_data) + + # do the coupling + participant.advance(dt) + + # read checkpoint if required + if participant.requires_reading_checkpoint(): + lhs, t, istep = checkpoint + + participant.finalize() + + +if __name__ == '__main__': + cli.run(main) diff --git a/partitioned-heat-conduction/neumann-nutils/requirements.txt b/partitioned-heat-conduction/neumann-nutils/requirements.txt new file mode 100644 index 000000000..cfd521c81 --- /dev/null +++ b/partitioned-heat-conduction/neumann-nutils/requirements.txt @@ -0,0 +1,2 @@ +nutils==7 +pyprecice==3 diff --git a/partitioned-heat-conduction/neumann-nutils/run.sh b/partitioned-heat-conduction/neumann-nutils/run.sh new file mode 100755 index 000000000..021225a41 --- /dev/null +++ b/partitioned-heat-conduction/neumann-nutils/run.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 -m venv .venv +. .venv/bin/activate +pip install -r requirements.txt + +rm -rf Neumann-*.vtk +NUTILS_RICHOUTPUT=no python3 heat.py + +close_log diff --git a/partitioned-heat-conduction/neumann-openfoam/0/T b/partitioned-heat-conduction/neumann-openfoam/0/T new file mode 100644 index 000000000..936cc8e7d --- /dev/null +++ b/partitioned-heat-conduction/neumann-openfoam/0/T @@ -0,0 +1,84 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} + +dimensions [0 0 0 1 0 0 0]; + + +internalField nonuniform #codeStream +{ + codeInclude + #{ + #include "fvCFD.H" + #}; + + codeOptions + #{ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude + #}; + + codeLibs + #{ + -lmeshTools \ + -lfiniteVolume + #}; + + code + + #{ + const IOdictionary& d = static_cast(dict); + const fvMesh& mesh = refCast(d.db()); + const vectorField& CC = mesh.C(); // cell center + + // assign values + scalarField T(mesh.nCells()); + forAll(CC, cellI) + { + scalar x = CC[cellI].x(); + scalar y = CC[cellI].y(); + + T[cellI] = 1 + pow(x, 2) + (3 * pow(y, 2)); // t is zero for initial conditions + } + os << T; + #}; +}; + +boundaryField +{ + interface + { + type fixedGradient; + gradient uniform -2; + } + + DirichletBoundary + { + type codedFixedValue; + value uniform 1; + name DirichletBoundary; + code + #{ + const vectorField& Cf = patch().Cf(); + const scalar t = this->db().time().value(); + + scalarField& field = *this; + forAll(Cf, faceI) + { + const scalar x = Cf[faceI].x(); + const scalar y = Cf[faceI].y(); + + field[faceI] = 1 + pow(x, 2) + (3 * pow(y, 2)) + 1.2 * t; + } + #}; + } + + defaultFaces + { + type empty; + } +} diff --git a/partitioned-heat-conduction/neumann-openfoam/clean.sh b/partitioned-heat-conduction/neumann-openfoam/clean.sh new file mode 100755 index 000000000..c31d9fc76 --- /dev/null +++ b/partitioned-heat-conduction/neumann-openfoam/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . diff --git a/partitioned-heat-conduction/neumann-openfoam/constant/physicalProperties b/partitioned-heat-conduction/neumann-openfoam/constant/physicalProperties new file mode 100644 index 000000000..3ce99aead --- /dev/null +++ b/partitioned-heat-conduction/neumann-openfoam/constant/physicalProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object transportProperties; +} + +DT DT [ 0 2 -1 0 0 0 0 ] 1; diff --git a/partitioned-heat-conduction/neumann-openfoam/constant/transportProperties b/partitioned-heat-conduction/neumann-openfoam/constant/transportProperties new file mode 100644 index 000000000..3ce99aead --- /dev/null +++ b/partitioned-heat-conduction/neumann-openfoam/constant/transportProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object transportProperties; +} + +DT DT [ 0 2 -1 0 0 0 0 ] 1; diff --git a/partitioned-heat-conduction/neumann-openfoam/run.sh b/partitioned-heat-conduction/neumann-openfoam/run.sh new file mode 100755 index 000000000..da82a9ba2 --- /dev/null +++ b/partitioned-heat-conduction/neumann-openfoam/run.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/partitioned-heat-conduction/openfoam-neumann/system/blockMeshDict b/partitioned-heat-conduction/neumann-openfoam/system/blockMeshDict similarity index 100% rename from partitioned-heat-conduction/openfoam-neumann/system/blockMeshDict rename to partitioned-heat-conduction/neumann-openfoam/system/blockMeshDict diff --git a/partitioned-heat-conduction/openfoam-neumann/system/controlDict b/partitioned-heat-conduction/neumann-openfoam/system/controlDict similarity index 74% rename from partitioned-heat-conduction/openfoam-neumann/system/controlDict rename to partitioned-heat-conduction/neumann-openfoam/system/controlDict index 31a7ba62d..c63fa7760 100644 --- a/partitioned-heat-conduction/openfoam-neumann/system/controlDict +++ b/partitioned-heat-conduction/neumann-openfoam/system/controlDict @@ -7,12 +7,10 @@ FoamFile } // Make sure you build the solver located -// in ../../openfoam-solver/ before running +// in ../../solver-openfoam/ before running // the case application heatTransfer; -libs ( "libgroovyBC.so" ) ; - startFrom startTime; startTime 0; @@ -21,10 +19,12 @@ stopAt endTime; endTime 1; -deltaT 0.1; +deltaT 0.01; writeControl runTime; +// Write data only at the end of each coupling time window +// Intermediate time step results correspond to the first coupling iteration and are not converged. writeInterval 0.1; purgeWrite 0; diff --git a/partitioned-heat-conduction/openfoam-neumann/system/fvSchemes b/partitioned-heat-conduction/neumann-openfoam/system/fvSchemes similarity index 100% rename from partitioned-heat-conduction/openfoam-neumann/system/fvSchemes rename to partitioned-heat-conduction/neumann-openfoam/system/fvSchemes diff --git a/partitioned-heat-conduction/neumann-openfoam/system/fvSolution b/partitioned-heat-conduction/neumann-openfoam/system/fvSolution new file mode 100644 index 000000000..0505de916 --- /dev/null +++ b/partitioned-heat-conduction/neumann-openfoam/system/fvSolution @@ -0,0 +1,23 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSolution; +} + +solvers +{ + T + { + solver PCG; + preconditioner DIC; + tolerance 1e-10; + relTol 0; + } +} + +SIMPLE +{ + nNonOrthogonalCorrectors 0; +} diff --git a/partitioned-heat-conduction/openfoam-neumann/system/preciceDict b/partitioned-heat-conduction/neumann-openfoam/system/preciceDict similarity index 100% rename from partitioned-heat-conduction/openfoam-neumann/system/preciceDict rename to partitioned-heat-conduction/neumann-openfoam/system/preciceDict diff --git a/partitioned-heat-conduction/nutils/.gitignore b/partitioned-heat-conduction/nutils/.gitignore deleted file mode 100644 index 53639607d..000000000 --- a/partitioned-heat-conduction/nutils/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -Neumann-*.vtk -Dirichlet-*.vtk -*.log -precice-*-events.json diff --git a/partitioned-heat-conduction/nutils/heat.py b/partitioned-heat-conduction/nutils/heat.py deleted file mode 100644 index a9d08963c..000000000 --- a/partitioned-heat-conduction/nutils/heat.py +++ /dev/null @@ -1,176 +0,0 @@ -#! /usr/bin/env python3 - -from nutils import cli, mesh, function, solver, export -import treelog -import numpy as np -import precice - - -def main(side='Dirichlet'): - print("Running nutils") - - # domain size - y_bottom, y_top = 0, 1 - x_left, x_right = 0, 2 - x_coupling = 1 # x coordinate of coupling interface - - n = 10 # number of mesh vertices per dimension - - if side == 'Dirichlet': - x_grid = np.linspace(x_left, x_coupling, n) - elif side == 'Neumann': - x_grid = np.linspace(x_coupling, x_right, n) - else: - raise Exception('invalid side {!r}'.format(side)) - - y_grid = np.linspace(y_bottom, y_top, n) - - # define the Nutils mesh - domain, geom = mesh.rectilinear([x_grid, y_grid]) - - # Nutils namespace - ns = function.Namespace() - ns.x = geom - - degree = 1 # linear finite elements - ns.basis = domain.basis('std', degree=degree) - ns.alpha = 3 # parameter of problem - ns.beta = 1.3 # parameter of problem - ns.u = 'basis_n ?lhs_n' # solution - ns.dudt = 'basis_n (?lhs_n - ?lhs0_n) / ?dt' # time derivative - ns.flux = 'basis_n ?fluxdofs_n' # heat flux - ns.f = 'beta - 2 - 2 alpha' # rhs - ns.uexact = '1 + x_0 x_0 + alpha x_1 x_1 + beta ?t' # analytical solution - - # define the weak form - res0 = domain.integral('(basis_n dudt - basis_n f + basis_n,i u_,i) d:x' @ ns, degree=degree * 2) - - # set boundary conditions at non-coupling boundaries - # top and bottom boundary are non-coupling for both sides - sqr0 = domain.boundary['top'].integral('(u - 1 - x_0 x_0 - alpha - beta ?t)^2 d:x' @ ns, degree=degree * 2) - sqr0 += domain.boundary['bottom'].integral('(u - 1 - x_0 x_0 - beta ?t)^2 d:x' @ ns, degree=degree * 2) - if side == 'Dirichlet': # left boundary is non-coupling - sqr0 += domain.boundary['left'].integral('(u - 1 - alpha x_1 x_1 - beta ?t)^2 d:x' @ ns, degree=degree * 2) - elif side == 'Neumann': # right boundary is non-coupling - sqr0 += domain.boundary['right'].integral('(u - 1 - x_0 x_0 - alpha x_1 x_1 - beta ?t)^2 d:x' @ ns, - degree=degree * 2) - - # preCICE setup - interface = precice.Interface(side, "../precice-config.xml", 0, 1) - - # define coupling mesh - mesh_name = side + "-Mesh" - mesh_id = interface.get_mesh_id(mesh_name) - coupling_boundary = domain.boundary['right' if side == 'Dirichlet' else 'left'] - coupling_sample = coupling_boundary.sample('gauss', degree=degree * 2) - vertices = coupling_sample.eval(ns.x) - vertex_ids = interface.set_mesh_vertices(mesh_id, vertices) - - # coupling data - write_data = "Temperature" if side == "Neumann" else "Heat-Flux" - read_data = "Heat-Flux" if side == "Neumann" else "Temperature" - write_data_id = interface.get_data_id(write_data, mesh_id) - read_data_id = interface.get_data_id(read_data, mesh_id) - - # helper functions to project heat flux to coupling boundary - projection_matrix = coupling_boundary.integrate(ns.eval_nm('basis_n basis_m d:x'), degree=degree * 2) - projection_cons = np.zeros(res0.shape) - projection_cons[projection_matrix.rowsupp(1e-15)] = np.nan - - def fluxdofs(v): - return projection_matrix.solve(v, constrain=projection_cons) - - # helper data structure to apply heat flux correctly - dx_function = 'd:x' @ ns - - precice_dt = interface.initialize() - - # write initial data - if interface.is_action_required(precice.action_write_initial_data()): - write_data = np.zeros(len(vertex_ids)) - interface.write_block_scalar_data(write_data_id, vertex_ids, write_data) - interface.mark_action_fulfilled(precice.action_write_initial_data()) - - interface.initialize_data() - - t = 0 - - # initial condition - sqr = domain.integral('(u - uexact)^2' @ ns, degree=degree * 2) - lhs0 = solver.optimize('lhs', sqr, droptol=1e-15, arguments=dict(t=t)) - bezier = domain.sample('bezier', degree * 2) - x, u, uexact = bezier.eval(['x_i', 'u', 'uexact'] @ ns, lhs=lhs0, t=t) - with treelog.add(treelog.DataLog()): - export.vtk(side + '-0', bezier.tri, x, Temperature=u, reference=uexact) - - t += precice_dt - timestep = 0 - dt = 0.1 - - while interface.is_coupling_ongoing(): - - # update (time-dependent) boundary condition - cons0 = solver.optimize('lhs', sqr0, droptol=1e-15, arguments=dict(t=t)) - - # read data from interface - if interface.is_read_data_available(): - read_data = interface.read_block_scalar_data(read_data_id, vertex_ids) - read_function = coupling_sample.asfunction(read_data) - - if side == 'Dirichlet': - sqr = coupling_sample.integral((ns.u - read_function) ** 2) - cons = solver.optimize('lhs', sqr, droptol=1e-15, constrain=cons0, arguments=dict(t=t)) - res = res0 - else: - cons = cons0 - res = res0 + coupling_sample.integral(ns.basis * read_function * dx_function) - - # save checkpoint - if interface.is_action_required(precice.action_write_iteration_checkpoint()): - lhs_checkpoint = lhs0 - t_checkpoint = t - timestep_checkpoint = timestep - interface.mark_action_fulfilled(precice.action_write_iteration_checkpoint()) - - # potentially adjust non-matching timestep sizes - dt = min(dt, precice_dt) - - # solve nutils timestep - lhs = solver.solve_linear('lhs', res, constrain=cons, arguments=dict(lhs0=lhs0, dt=dt, t=t)) - - # write data to interface - if interface.is_write_data_required(dt): - if side == 'Dirichlet': - flux_function = res.eval(lhs0=lhs0, lhs=lhs, dt=dt, t=t) - write_data = coupling_sample.eval('flux' @ ns, fluxdofs=fluxdofs(flux_function)) - else: - write_data = coupling_sample.eval('u' @ ns, lhs=lhs) - - interface.write_block_scalar_data(write_data_id, vertex_ids, write_data) - - # do the coupling - precice_dt = interface.advance(dt) - - # advance variables - t += dt - timestep += 1 - lhs0 = lhs - - # read checkpoint if required - if interface.is_action_required(precice.action_read_iteration_checkpoint()): - lhs0 = lhs_checkpoint - t = t_checkpoint - timestep = timestep_checkpoint - interface.mark_action_fulfilled(precice.action_read_iteration_checkpoint()) - else: # go to next timestep - bezier = domain.sample('bezier', degree * 2) - x, u, uexact = bezier.eval(['x_i', 'u', 'uexact'] @ ns, lhs=lhs, t=t) - - with treelog.add(treelog.DataLog()): - export.vtk(side + "-" + str(timestep), bezier.tri, x, Temperature=u, reference=uexact) - - interface.finalize() - - -if __name__ == '__main__': - cli.run(main) diff --git a/partitioned-heat-conduction/nutils/run.sh b/partitioned-heat-conduction/nutils/run.sh deleted file mode 100755 index b3048a04f..000000000 --- a/partitioned-heat-conduction/nutils/run.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh -set -e -u - -usage() { echo "Usage: cmd [-d] [-n]" 1>&2; exit 1; } - -# Check if no input argument was provided -if [ -z "$*" ] ; then - usage -fi - -while getopts ":dn" opt; do - case ${opt} in - d) - rm -rf Dirichlet-*.vtk - python3 heat.py --side=Dirichlet - ;; - n) - rm -rf Neumann-*.vtk - python3 heat.py --side=Neumann - ;; - *) - usage - ;; - esac -done diff --git a/partitioned-heat-conduction/openfoam-dirichlet/0.orig/T b/partitioned-heat-conduction/openfoam-dirichlet/0.orig/T deleted file mode 100644 index fed3ddbc4..000000000 --- a/partitioned-heat-conduction/openfoam-dirichlet/0.orig/T +++ /dev/null @@ -1,35 +0,0 @@ -FoamFile -{ - version 2.0; - format ascii; - class volScalarField; - object T; -} - -dimensions [0 0 0 1 0 0 0]; - - -internalField uniform 0; - -boundaryField -{ - interface - { - type fixedValue; - value uniform 2; - } - - DirichletBoundary - { - type groovyBC; - variables "val=1+pow(pos().x,2)+(3*pow(pos().y,2))+1.3*time();"; - valueExpression "val"; - value uniform 0; - evaluateDuringConstruction 1; - } - - defaultFaces - { - type empty; - } -} diff --git a/partitioned-heat-conduction/openfoam-dirichlet/setInitialField.sh b/partitioned-heat-conduction/openfoam-dirichlet/setInitialField.sh deleted file mode 100755 index bf3dfd29c..000000000 --- a/partitioned-heat-conduction/openfoam-dirichlet/setInitialField.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -set -e -u - -# Remove the old directory and copy the uninitialized field -rm -rf ./0 -cp -r ./0.orig 0 -# Initialize the new field -funkySetFields -keepPatches -field T -expression '1+pow(pos().x,2)+(3*pow(pos().y,2))+1.3*time()' -time '0' diff --git a/partitioned-heat-conduction/openfoam-neumann/0.orig/T b/partitioned-heat-conduction/openfoam-neumann/0.orig/T deleted file mode 100644 index 01f8fc1af..000000000 --- a/partitioned-heat-conduction/openfoam-neumann/0.orig/T +++ /dev/null @@ -1,35 +0,0 @@ -FoamFile -{ - version 2.0; - format ascii; - class volScalarField; - object T; -} - -dimensions [0 0 0 1 0 0 0]; - - -internalField uniform 0; - -boundaryField -{ - interface - { - type fixedGradient; - gradient uniform -2; - } - - DirichletBoundary - { - type groovyBC; - variables "val=1+pow(pos().x,2)+(3*pow(pos().y,2))+1.3*time();"; - valueExpression "val"; - value uniform 0; - evaluateDuringConstruction 1; - } - - defaultFaces - { - type empty; - } -} diff --git a/partitioned-heat-conduction/openfoam-neumann/setInitialField.sh b/partitioned-heat-conduction/openfoam-neumann/setInitialField.sh deleted file mode 100755 index bf3dfd29c..000000000 --- a/partitioned-heat-conduction/openfoam-neumann/setInitialField.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -set -e -u - -# Remove the old directory and copy the uninitialized field -rm -rf ./0 -cp -r ./0.orig 0 -# Initialize the new field -funkySetFields -keepPatches -field T -expression '1+pow(pos().x,2)+(3*pow(pos().y,2))+1.3*time()' -time '0' diff --git a/partitioned-heat-conduction/openfoam-solver/write.H b/partitioned-heat-conduction/openfoam-solver/write.H deleted file mode 100644 index c4d405d44..000000000 --- a/partitioned-heat-conduction/openfoam-solver/write.H +++ /dev/null @@ -1,58 +0,0 @@ - if (runTime.writeTime()) - { - volVectorField gradT(fvc::grad(T)); - - volScalarField gradTx - ( - IOobject - ( - "gradTx", - runTime.timeName(), - mesh, - IOobject::NO_READ, - IOobject::AUTO_WRITE - ), - gradT.component(vector::X) - ); - - volScalarField gradTy - ( - IOobject - ( - "gradTy", - runTime.timeName(), - mesh, - IOobject::NO_READ, - IOobject::AUTO_WRITE - ), - gradT.component(vector::Y) - ); - - volScalarField gradTz - ( - IOobject - ( - "gradTz", - runTime.timeName(), - mesh, - IOobject::NO_READ, - IOobject::AUTO_WRITE - ), - gradT.component(vector::Z) - ); - - volVectorField DTgradT - ( - IOobject - ( - "flux", - runTime.timeName(), - mesh, - IOobject::NO_READ, - IOobject::AUTO_WRITE - ), - DT*gradT - ); - - runTime.write(); - } diff --git a/partitioned-heat-conduction/precice-config.xml b/partitioned-heat-conduction/precice-config.xml index 280fcb2f2..baab5d5c3 100644 --- a/partitioned-heat-conduction/precice-config.xml +++ b/partitioned-heat-conduction/precice-config.xml @@ -7,69 +7,75 @@ enabled="true" /> - - - + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/partitioned-heat-conduction/solver-fenics/errorcomputation.py b/partitioned-heat-conduction/solver-fenics/errorcomputation.py new file mode 100644 index 000000000..2c9ec7367 --- /dev/null +++ b/partitioned-heat-conduction/solver-fenics/errorcomputation.py @@ -0,0 +1,15 @@ +from fenics import inner, assemble, dx, project, sqrt + + +def compute_errors(u_approx, u_ref, v, total_error_tol=10 ** -4): + # compute pointwise L2 error + error_normalized = (u_ref - u_approx) / u_ref + # project onto function space + error_pointwise = project(abs(error_normalized), v) + # determine L2 norm to estimate total error + error_total = sqrt(assemble(inner(error_pointwise, error_pointwise) * dx)) + error_pointwise.rename("error", " ") + + assert (error_total < total_error_tol) + + return error_total, error_pointwise diff --git a/partitioned-heat-conduction/fenics/heat.py b/partitioned-heat-conduction/solver-fenics/heat.py similarity index 66% rename from partitioned-heat-conduction/fenics/heat.py rename to partitioned-heat-conduction/solver-fenics/heat.py index e7b7f6529..78ee6af15 100644 --- a/partitioned-heat-conduction/fenics/heat.py +++ b/partitioned-heat-conduction/solver-fenics/heat.py @@ -33,8 +33,7 @@ import argparse import numpy as np from problem_setup import get_geometry -import dolfin -from dolfin import FacetNormal, dot +import sympy as sp def determine_gradient(V_g, u, flux): @@ -54,25 +53,23 @@ def determine_gradient(V_g, u, flux): parser = argparse.ArgumentParser(description="Solving heat equation for simple or complex interface case") -command_group = parser.add_mutually_exclusive_group(required=True) -command_group.add_argument("-d", "--dirichlet", help="create a dirichlet problem", dest="dirichlet", - action="store_true") -command_group.add_argument("-n", "--neumann", help="create a neumann problem", dest="neumann", action="store_true") -parser.add_argument("-e", "--error-tol", help="set error tolerance", type=float, default=10**-6,) +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() +participant_name = args.participantName -fenics_dt = .1 # time step size +fenics_dt = .01 # time step size # Error is bounded by coupling accuracy. In theory we would obtain the analytical solution. error_tol = args.error_tol alpha = 3 # parameter alpha -beta = 1.3 # parameter beta +beta = 1.2 # parameter beta -if args.dirichlet and not args.neumann: +if participant_name == ProblemType.DIRICHLET.value: problem = ProblemType.DIRICHLET domain_part = DomainPart.LEFT -elif args.neumann and not args.dirichlet: +elif participant_name == ProblemType.NEUMANN.value: problem = ProblemType.NEUMANN domain_part = DomainPart.RIGHT @@ -84,12 +81,15 @@ def determine_gradient(V_g, u, flux): W = V_g.sub(0).collapse() # Define boundary conditions -u_D = Expression('1 + x[0]*x[0] + alpha*x[1]*x[1] + beta*t', degree=2, alpha=alpha, beta=beta, t=0) +# create sympy expression of manufactured solution +x_sp, y_sp, t_sp = sp.symbols(['x[0]', 'x[1]', 't']) +u_D_sp = 1 + x_sp * x_sp + alpha * y_sp * y_sp + beta * t_sp +u_D = Expression(sp.ccode(u_D_sp), degree=2, alpha=alpha, beta=beta, t=0) u_D_function = interpolate(u_D, V) if problem is ProblemType.DIRICHLET: # Define flux in x direction - f_N = Expression("2 * x[0]", degree=1, alpha=alpha, t=0) + f_N = Expression(sp.ccode(u_D_sp.diff(x_sp)), degree=1, alpha=alpha, t=0) f_N_function = interpolate(f_N, W) # Define initial value @@ -99,20 +99,23 @@ def determine_gradient(V_g, u, flux): precice, precice_dt, initial_data = None, 0.0, None # Initialize the adapter according to the specific participant +precice = Adapter(adapter_config_filename="precice-adapter-config.json") + if problem is ProblemType.DIRICHLET: - precice = Adapter(adapter_config_filename="precice-adapter-config-D.json") - precice_dt = precice.initialize(coupling_boundary, read_function_space=V, write_object=f_N_function) + precice.initialize(coupling_boundary, read_function_space=V, write_object=f_N_function) elif problem is ProblemType.NEUMANN: - precice = Adapter(adapter_config_filename="precice-adapter-config-N.json") - precice_dt = precice.initialize(coupling_boundary, read_function_space=W, write_object=u_D_function) + precice.initialize(coupling_boundary, read_function_space=W, write_object=u_D_function) +precice_dt = precice.get_max_time_step_size() dt = Constant(0) dt.assign(np.min([fenics_dt, precice_dt])) # Define variational problem u = TrialFunction(V) v = TestFunction(V) -f = Expression('beta - 2 - 2*alpha', degree=2, alpha=alpha, beta=beta, t=0) +# du_dt-Laplace(u) = f +f_sp = u_D_sp.diff(t_sp) - u_D_sp.diff(x_sp).diff(x_sp) - u_D_sp.diff(y_sp).diff(y_sp) +f = Expression(sp.ccode(f_sp), degree=2, alpha=alpha, beta=beta, t=0) F = u * v / dt * dx + dot(grad(u), grad(v)) * dx - (u_n / dt + f) * v * dx bcs = [DirichletBC(V, u_D, remaining_boundary)] @@ -126,7 +129,7 @@ def determine_gradient(V_g, u, flux): if problem is ProblemType.NEUMANN: # modify Neumann boundary condition on coupling interface, modify weak # form correspondingly - F += v * coupling_expression * dolfin.ds + F += v * coupling_expression * ds a, L = lhs(F), rhs(F) @@ -155,13 +158,27 @@ def determine_gradient(V_g, u, flux): # output solution and reference solution at t=0, n=0 n = 0 -print('output u^%d and u_ref^%d' % (n, n)) -temperature_out << u_n -ref_out << u_ref +print("output u^%d and u_ref^%d" % (n, n)) ranks << mesh_rank error_total, error_pointwise = compute_errors(u_n, u_ref, V) -error_out << error_pointwise + +# create buffer for output. We need this buffer, because we only want to +# write the converged output at the end of the window, but we also want to +# write the samples that are resulting from substeps inside the window +u_write = [] +ref_write = [] +error_write = [] +# copy data to buffer and rename +uu = u_n.copy() +uu.rename("u", "") +u_write.append((uu, t)) +uu_ref = u_ref.copy() +uu_ref.rename("u_ref", "") +ref_write.append(uu_ref) +err = error_pointwise.copy() +err.rename("err", "") +error_write.append(err) # set t_1 = t_0 + dt, this gives u_D^1 # call dt(0) to evaluate FEniCS Constant. Todo: is there a better way? @@ -175,16 +192,33 @@ def determine_gradient(V_g, u, flux): while precice.is_coupling_ongoing(): # write checkpoint - if precice.is_action_required(precice.action_write_iteration_checkpoint()): + if precice.requires_writing_checkpoint(): precice.store_checkpoint(u_n, t, n) - read_data = precice.read_data() + # output solution and reference solution at t_n+1 and substeps (read from buffer) + print('output u^%d and u_ref^%d' % (n, n)) + for sample in u_write: + temperature_out << sample - # Update the coupling expression with the new read data - precice.update_coupling_expression(coupling_expression, read_data) + for sample in ref_write: + ref_out << sample + for sample in error_write: + error_out << error_pointwise + + precice_dt = precice.get_max_time_step_size() dt.assign(np.min([fenics_dt, precice_dt])) + # Dirichlet BC and RHS need to point to end of current timestep + u_D.t = t + float(dt) + f.t = t + float(dt) + + # Coupling BC needs to point to end of current timestep + read_data = precice.read_data(dt) + + # Update the coupling expression with the new read data + precice.update_coupling_expression(coupling_expression, read_data) + # Compute solution u^n+1, use bcs u_D^n+1, u^n and coupling bcs solve(a == L, u_np1, bcs) @@ -198,33 +232,54 @@ def determine_gradient(V_g, u, flux): # Neumann problem reads flux and writes temperature on boundary to Dirichlet problem precice.write_data(u_np1) - precice_dt = precice.advance(dt(0)) + precice.advance(dt) + precice_dt = precice.get_max_time_step_size() # roll back to checkpoint - if precice.is_action_required(precice.action_read_iteration_checkpoint()): + if precice.requires_reading_checkpoint(): u_cp, t_cp, n_cp = precice.retrieve_checkpoint() u_n.assign(u_cp) t = t_cp n = n_cp + # empty buffer if window has not converged + u_write = [] + ref_write = [] + error_write = [] else: # update solution u_n.assign(u_np1) t += float(dt) n += 1 + # copy data to buffer and rename + uu = u_n.copy() + uu.rename("u", "") + u_write.append((uu, t)) + uu_ref = u_ref.copy() + uu_ref.rename("u_ref", "") + ref_write.append(uu_ref) + err = error_pointwise.copy() + err.rename("err", "") + error_write.append(err) if precice.is_time_window_complete(): u_ref = interpolate(u_D, V) u_ref.rename("reference", " ") error, error_pointwise = compute_errors(u_n, u_ref, V, total_error_tol=error_tol) - print('n = %d, t = %.2f: L2 error on domain = %.3g' % (n, t, error)) - # output solution and reference solution at t_n+1 - print('output u^%d and u_ref^%d' % (n, n)) - temperature_out << u_n - ref_out << u_ref - error_out << error_pointwise + print("n = %d, t = %.2f: L2 error on domain = %.3g" % (n, t, error)) # Update Dirichlet BC u_D.t = t + float(dt) f.t = t + float(dt) +# output solution and reference solution at t_n+1 and substeps (read from buffer) +print("output u^%d and u_ref^%d" % (n, n)) +for sample in u_write: + temperature_out << sample + +for sample in ref_write: + ref_out << sample + +for sample in error_write: + error_out << error_pointwise + # Hold plot precice.finalize() diff --git a/partitioned-heat-conduction/solver-fenics/heatHigherOrder.py b/partitioned-heat-conduction/solver-fenics/heatHigherOrder.py new file mode 100644 index 000000000..5311b4d97 --- /dev/null +++ b/partitioned-heat-conduction/solver-fenics/heatHigherOrder.py @@ -0,0 +1,376 @@ +""" +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 and mixed boundary conditions to allow for a Dirichlet-Neumann +coupling of two separate heat equations. + +The original source code can be found on https://github.com/hplgit/fenics-tutorial/blob/master/pub/python/vol1/ft03_heat.py. + +Heat equation with Dirichlet conditions. (Dirichlet problem) + u'= Laplace(u) + f in the unit square [0,1] x [0,1] + u = u_C on the coupling boundary at x = 1 + 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 shifted unit square [1,2] x [0,1] + du/dn = f_N on the coupling boundary at x = 1 + 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 + +For information on the partitioned heat conduction problem using higher-order implicit Runge-Kutta methods see +* "Wullenweber, Nikola. High-order time stepping schemes for solving partial differential equations with FEniCS. Bachelor's thesis at Technical University of Munich, 2021. URL: https://mediatum.ub.tum.de/1621360" +* "Vinnitchenko, Niklas. Evaluation of higher-order coupling schemes with FEniCS-preCICE. Bachelor's thesis at Technical University of Munich, 2023. URL: https://mediatum.ub.tum.de/1732367" + +The implementation of the higher-order implicit Runge-Kutta methods is based on: https://github.com/NikoWul/FenicsIrksome +""" + +from __future__ import print_function, division +from fenics import Function, FunctionSpace, Expression, Constant, DirichletBC, TrialFunction, TestFunction, \ + File, solve, lhs, rhs, grad, inner, dot, dx, ds, interpolate, VectorFunctionSpace, MeshFunction, MPI, MixedElement, split, project +from fenicsprecice import Adapter +from errorcomputation import compute_errors +from my_enums import ProblemType, DomainPart +import argparse +import numpy as np +from problem_setup import get_geometry +import sympy as sp +from utils.ButcherTableaux import * +import utils.utils as utl + + +def determine_gradient(V_g, u, flux): + """ + compute flux following http://hplgit.github.io/INF5620/doc/pub/fenics_tutorial1.1/tu2.html#tut-poisson-gradu + :param V_g: Vector function space + :param u: solution where gradient is to be determined + :param flux: returns calculated flux into this value + """ + + w = TrialFunction(V_g) + v = TestFunction(V_g) + + a = inner(w, v) * dx + L = inner(grad(u), v) * dx + solve(a == L, flux) + + +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() +participant_name = args.participantName + +fenics_dt = .01 # time step size +# Error is bounded by coupling accuracy. In theory we would obtain the analytical solution. +error_tol = args.error_tol + +alpha = 3 # parameter alpha +beta = 1.2 # parameter beta + +if participant_name == ProblemType.DIRICHLET.value: + problem = ProblemType.DIRICHLET + domain_part = DomainPart.LEFT +elif participant_name == ProblemType.NEUMANN.value: + problem = ProblemType.NEUMANN + domain_part = DomainPart.RIGHT + +mesh, coupling_boundary, remaining_boundary = get_geometry(domain_part) + +# Define function space using mesh +V = FunctionSpace(mesh, 'P', 2) +V_g = VectorFunctionSpace(mesh, 'P', 1) +W = V_g.sub(0).collapse() + +# Define boundary conditions +# create sympy expression of manufactured solution +g_degree = 0 # degree of time dependent term g(t). Determines how difficult it is to solve the problem +x_sp, y_sp, t_sp = sp.symbols(['x[0]', 'x[1]', 't']) +u_D_sp = 1 + x_sp * x_sp * (1 + t_sp)**g_degree + alpha * y_sp * y_sp + beta * t_sp +u_D = Expression(sp.ccode(u_D_sp), degree=2, alpha=alpha, beta=beta, t=0) +u_D_function = interpolate(u_D, V) + +if problem is ProblemType.DIRICHLET: + # Define flux in x direction + f_N = Expression(sp.ccode(u_D_sp.diff(x_sp)), degree=1, alpha=alpha, t=0) + f_N_function = interpolate(f_N, W) + +# Define initial value +u_n = interpolate(u_D, V) +u_n.rename("Temperature", "") + +# time stepping setup +# scheme +tsm = GaussLegendre(2) +# depending on tsm, we define the trial and test function space +if tsm.num_stages == 1: + Vbig = V +else: + # for multi-stage RK methods, we need more dimensional function spaces + mixed = MixedElement(tsm.num_stages * [V.ufl_element()]) + Vbig = FunctionSpace(V.mesh(), mixed) + +precice, precice_dt, initial_data = None, 0.0, None + +# Initialize the adapter according to the specific participant +precice = Adapter(adapter_config_filename="precice-adapter-config.json") + +if problem is ProblemType.DIRICHLET: + precice.initialize(coupling_boundary, read_function_space=V, write_object=f_N_function) +elif problem is ProblemType.NEUMANN: + precice.initialize(coupling_boundary, read_function_space=W, write_object=u_D_function) + +precice_dt = precice.get_max_time_step_size() +dt = Constant(0) +dt.assign(np.min([fenics_dt, precice_dt])) + +# stage times of the time stepping scheme relative to the current time and dependent on the current dt +stage_times = [tsm.c[i] * dt for i in range(tsm.num_stages)] + +# Define variational problem +# trial and test functions +u = TrialFunction(Vbig) +v = TestFunction(Vbig) +# if dim(Vbig)>1, f needs to be stored in an array with different times, +# because in each stage, of an RK method it is evaluated at a different time +# du_dt-Laplace(u) = f +f_sp = u_D_sp.diff(t_sp) - u_D_sp.diff(x_sp).diff(x_sp) - u_D_sp.diff(y_sp).diff(y_sp) +# initial time assumed to be 0 +f = [Expression(sp.ccode(f_sp), degree=2, t=float(stage_times[i])) for i in range(tsm.num_stages)] +# get variational form of the problem +F = utl.get_variational_problem(v=v, initial_condition=u_n, dt=dt, fs=f, tsm=tsm, k=u) + +# boundary conditions + +# we define variational form for each RK stage. According to +# https://doi.org/10.1145/3466168, All of those stages +# represent time derivatives and not the actual solution. +# Thus, we need time derivatives of the Dirichlet boundaries as boundary conditions + +# get time derivative of u +du_dt_expr = u_D_sp.diff(t_sp) +du_dt = [Expression(sp.ccode(du_dt_expr), degree=2, t=float(stage_times[i])) for i in range(tsm.num_stages)] +# set up boundary conditions +bc = [] +# Create for each dimension of Vbig a coupling expression for either the time derivatives (Dirichlet side) +# or Neumann side (no time derivatives required as they are enforced with changing F) +coupling_expressions = [precice.create_coupling_expression() for _ in range(tsm.num_stages)] + +# wrap Vbig into array independent of the length to allow equal treatment below +if tsm.num_stages == 1: + Vbigs = [Vbig] + vs = [v] +else: + Vbigs = [Vbig.sub(i) for i in range(tsm.num_stages)] + vs = split(v) + +# for the boundary which is not the coupling boundary, we can just use the boundary conditions as usual. +# Each stage needs a boundary condition +for i in range(tsm.num_stages): + if problem is ProblemType.DIRICHLET: + bc.append(DirichletBC(Vbigs[i], du_dt[i], remaining_boundary)) + bc.append(DirichletBC(Vbigs[i], coupling_expressions[i], coupling_boundary)) + else: + bc.append(DirichletBC(Vbigs[i], du_dt[i], remaining_boundary)) + F += vs[i] * coupling_expressions[i] * ds + +a, L = lhs(F), rhs(F) + +# we additionally need the values of the stages from the RK method. +# they are stored here +k = Function(Vbig) + +# Time-stepping +u_np1 = Function(V) +u_np1.rename("Temperature", "") +t = 0 + +# reference solution at t=0 +u_ref = interpolate(u_D, V) +u_ref.rename("reference", " ") + +# mark mesh w.r.t ranks +mesh_rank = MeshFunction("size_t", mesh, mesh.topology().dim()) +if problem is ProblemType.NEUMANN: + mesh_rank.set_all(MPI.rank(MPI.comm_world) + 4) +else: + mesh_rank.set_all(MPI.rank(MPI.comm_world) + 0) +mesh_rank.rename("myRank", "") + +# Generating output files +temperature_out = File("output/%s.pvd" % precice.get_participant_name()) +ref_out = File("output/ref%s.pvd" % precice.get_participant_name()) +error_out = File("output/error%s.pvd" % precice.get_participant_name()) +ranks = File("output/ranks%s.pvd" % precice.get_participant_name()) + +# output solution and reference solution at t=0, n=0 +n = 0 +print("output u^%d and u_ref^%d" % (n, n)) +ranks << mesh_rank + +error_total, error_pointwise = compute_errors(u_n, u_ref, V) + +# create buffer for output. We need this buffer, because we only want to +# write the converged output at the end of the window, but we also want to +# write the samples that are resulting from substeps inside the window +u_write = [] +ref_write = [] +error_write = [] +# copy data to buffer and rename +uu = u_n.copy() +uu.rename("u", "") +u_write.append((uu, t)) +uu_ref = u_ref.copy() +uu_ref.rename("u_ref", "") +ref_write.append(uu_ref) +err = error_pointwise.copy() +err.rename("err", "") +error_write.append(err) + +if problem is ProblemType.DIRICHLET: + flux = Function(V_g) + flux.rename("Heat-Flux", "") + +while precice.is_coupling_ongoing(): + + # write checkpoint + if precice.requires_writing_checkpoint(): + precice.store_checkpoint(u_n, t, n) + + # output solution and reference solution at t_n+1 and substeps (read from buffer) + print('output u^%d and u_ref^%d' % (n, n)) + for sample in u_write: + temperature_out << sample + + for sample in ref_write: + ref_out << sample + + for sample in error_write: + error_out << error_pointwise + + precice_dt = precice.get_max_time_step_size() + dt.assign(np.min([fenics_dt, precice_dt])) + + # Dirichlet BC and RHS need to point to end of current timestep + u_D.t = t + float(dt) + # update boundary conditions + for i in range(tsm.num_stages): + f[i].t = t + float(stage_times[i]) + du_dt[i].t = t + float(stage_times[i]) + + # can be deleted, if preCICE offers an API call for getting the time derivative of the waveform + # (see https://github.com/precice/precice/issues/1908) + # compute time derivatives for dirichlet side + if problem is ProblemType.DIRICHLET: + # approximate the function which preCICE uses with BSplines + bsplns = utl.b_splines(precice, 5, float(dt)) + + # get first derivative + bsplns_der = {} + for ki in bsplns.keys(): + bsplns_der[ki] = bsplns[ki].derivative(1) + + if problem is ProblemType.DIRICHLET: + # if preCICE offers API to get the time derivative directly from it, you can remove the entire for-loop + # and directly insert it into update_coupling_expression + for i in range(tsm.num_stages): + # values of derivative at current time + val = {} + for ki in bsplns_der.keys(): + val[ki] = bsplns_der[ki](float(stage_times[i])) + precice.update_coupling_expression(coupling_expressions[i], val) + else: + # Neumann boundaries just need temperature flux + for i in range(tsm.num_stages): + precice.update_coupling_expression(coupling_expressions[i], precice.read_data(stage_times[i])) + + # getting the solution of the current time step + + # instead of directly solving for u, we look for the values of k. + # with those we can assemble the solution and thus get the discrete evolution + solve(a == L, k, bc) + + if tsm.num_stages == 1: + ks = [k] + else: + ks = [k.sub(i) for i in range(tsm.num_stages)] + + # now we need to add up the stages k according to the time stepping scheme + # -> assembly of discrete evolution + u_np1 = u_n + for i in range(tsm.num_stages): + u_np1 += dt * tsm.b[i] * ks[i] + + # u is in function space V and not Vbig -> project u_np1 to V + u_np1 = project(u_np1, V) + + # 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 + determine_gradient(V_g, u_np1, flux) + flux_x = interpolate(flux.sub(0), W) + precice.write_data(flux_x) + elif problem is ProblemType.NEUMANN: + # Neumann problem reads flux and writes temperature on boundary to Dirichlet problem + precice.write_data(u_np1) + + precice.advance(dt) + precice_dt = precice.get_max_time_step_size() + + # roll back to checkpoint + if precice.requires_reading_checkpoint(): + u_cp, t_cp, n_cp = precice.retrieve_checkpoint() + u_n.assign(u_cp) + t = t_cp + n = n_cp + # empty buffer if window has not converged + u_write = [] + ref_write = [] + error_write = [] + else: # update solution + u_n.assign(u_np1) + t += float(dt) + n += 1 + # copy data to buffer and rename + uu = u_n.copy() + uu.rename("u", "") + u_write.append((uu, t)) + uu_ref = u_ref.copy() + uu_ref.rename("u_ref", "") + ref_write.append(uu_ref) + err = error_pointwise.copy() + err.rename("err", "") + error_write.append(err) + + if precice.is_time_window_complete(): + u_ref = interpolate(u_D, V) + u_ref.rename("reference", " ") + error, error_pointwise = compute_errors(u_n, u_ref, V, total_error_tol=error_tol) + print("n = %d, t = %.2f: L2 error on domain = %.3g" % (n, t, error)) + + # Update Dirichlet BC + u_D.t = t + float(dt) + for i in range(tsm.num_stages): + f[i].t = t + float(stage_times[i]) + du_dt[i].t = t + float(stage_times[i]) + + +# output solution and reference solution at t_n+1 and substeps (read from buffer) +print("output u^%d and u_ref^%d" % (n, n)) +for sample in u_write: + temperature_out << sample + +for sample in ref_write: + ref_out << sample + +for sample in error_write: + error_out << error_pointwise + +# Hold plot +precice.finalize() diff --git a/partitioned-heat-conduction/fenics/my_enums.py b/partitioned-heat-conduction/solver-fenics/my_enums.py similarity index 84% rename from partitioned-heat-conduction/fenics/my_enums.py rename to partitioned-heat-conduction/solver-fenics/my_enums.py index 27fc5d9ae..bd3c841f2 100644 --- a/partitioned-heat-conduction/fenics/my_enums.py +++ b/partitioned-heat-conduction/solver-fenics/my_enums.py @@ -5,8 +5,8 @@ class ProblemType(Enum): """ Enum defines problem type. Details see above. """ - DIRICHLET = 1 # Dirichlet problem - NEUMANN = 2 # Neumann problem + DIRICHLET = "Dirichlet" # Dirichlet problem + NEUMANN = "Neumann" # Neumann problem class DomainPart(Enum): diff --git a/partitioned-heat-conduction/fenics/problem_setup.py b/partitioned-heat-conduction/solver-fenics/problem_setup.py similarity index 98% rename from partitioned-heat-conduction/fenics/problem_setup.py rename to partitioned-heat-conduction/solver-fenics/problem_setup.py index b85f30358..ff2996fce 100644 --- a/partitioned-heat-conduction/fenics/problem_setup.py +++ b/partitioned-heat-conduction/solver-fenics/problem_setup.py @@ -33,7 +33,7 @@ def inside(self, x, on_boundary): def get_geometry(domain_part): - nx = ny = 9 + nx = ny = 11 if domain_part is DomainPart.LEFT: p0 = Point(x_left, y_bottom) diff --git a/partitioned-heat-conduction/solver-fenics/utils/ButcherTableaux.py b/partitioned-heat-conduction/solver-fenics/utils/ButcherTableaux.py new file mode 100644 index 000000000..597e51f03 --- /dev/null +++ b/partitioned-heat-conduction/solver-fenics/utils/ButcherTableaux.py @@ -0,0 +1,210 @@ +""" +The original source code can be found on https://github.com/firedrakeproject/Irksome/blob/master/irksome/ButcherTableaux.py +See also: + Irksome: Automating Runge–Kutta Time-Stepping for Finite Element Methods + by Farrell, Patrick E. and Kirby, Robert C. and Marchena-Menendez, Jorge, + 2021, https://doi.org/10.1145/3466168 +""" + +import FIAT +import numpy +from numpy import vander + + +class ButcherTableau(object): + """Top-level class representing a Butcher tableau encoding + a Runge-Kutta method. It has members + + :arg A: a 2d array containing the Butcher matrix + :arg b: a 1d array giving weights assigned to each stage when + computing the solution at time n+1. + :arg btilde: If present, a 1d array giving weights for an embedded + lower-order method (used in estimating temporal + truncation error.) + :arg c: a 1d array containing weights at which time-dependent + terms are evaluated. + :arg order: the (integer) formal order of accuracy of the method + """ + + def __init__(self, A, b, btilde, c, order): + + self.A = A + self.b = b + self.btilde = btilde + self.c = c + self.order = order + + @property + def num_stages(self): + """Return the number of stages the method has.""" + return len(self.b) + + def __str__(self): + return str(self.__class__).split(".")[-1][:-2] + "()" + + +class CollocationButcherTableau(ButcherTableau): + """When an RK method is based on collocation with point sets present + in FIAT, we have a general formula for producing the Butcher tableau. + + :arg L: a one-dimensional class :class:`FIAT.FiniteElement` + of Lagrange type -- the degrees of freedom must all be point + evaluation. + :arg order: the order of the resulting RK method. + """ + + def __init__(self, L, order): + assert L.ref_el == FIAT.ufc_simplex(1) + + for ell in L.dual.nodes: + assert isinstance(ell, FIAT.functional.PointEvaluation) + + c = numpy.asarray([list(ell.pt_dict.keys())[0][0] + for ell in L.dual.nodes]) + + num_stages = len(c) + + Q = FIAT.make_quadrature(L.ref_el, 2 * num_stages) + qpts = Q.get_points() + qwts = Q.get_weights() + + Lvals = L.tabulate(0, qpts)[0, ] + + # integrates them all! + b = Lvals @ qwts + + # now for A, which means we have to adjust the interval + A = numpy.zeros((num_stages, num_stages)) + for i in range(num_stages): + qpts_i = qpts * c[i] + qwts_i = qwts * c[i] + Lvals_i = L.tabulate(0, qpts_i)[0, ] + A[i, :] = Lvals_i @ qwts_i + + V = vander(c, increasing=True) + rhs = numpy.array([1.0 / (s + 1) for s in range(num_stages - 1)] + [0]) + btilde = numpy.linalg.solve(V.T, rhs) + + super(CollocationButcherTableau, self).__init__(A, b, btilde, c, order) + + +class GaussLegendre(CollocationButcherTableau): + """Collocation method based on the Gauss-Legendre points. + The order of accuracy is 2 * `num_stages`. + GL methods are A-stable, B-stable, and symplectic. + + :arg num_stages: The number of stages (1 or greater) + """ + + def __init__(self, num_stages): + assert num_stages > 0 + U = FIAT.ufc_simplex(1) + L = FIAT.GaussLegendre(U, num_stages - 1) + super(GaussLegendre, self).__init__(L, 2 * num_stages) + + def __str__(self): + return "GaussLegendre(%d)" % self.num_stages + + +class LobattoIIIA(CollocationButcherTableau): + """Collocation method based on the Gauss-Lobatto points. + The order of accuracy is 2 * `num_stages` - 2. + LobattoIIIA methods are A-stable but not B- or L-stable. + + :arg num_stages: The number of stages (2 or greater) + """ + + def __init__(self, num_stages): + assert num_stages > 1 + U = FIAT.ufc_simplex(1) + L = FIAT.GaussLobattoLegendre(U, num_stages - 1) + super(LobattoIIIA, self).__init__(L, 2 * num_stages - 2) + + def __str__(self): + return "LobattoIIIA(%d)" % self.num_stages + + +class RadauIIA(CollocationButcherTableau): + """Collocation method based on the Gauss-Radau points. + The order of accuracy is 2 * `num_stages` - 1. + RadauIIA methods are algebraically (hence B-) stable. + + :arg num_stages: The number of stages (2 or greater) + """ + + def __init__(self, num_stages): + assert num_stages >= 1 + U = FIAT.ufc_simplex(1) + L = FIAT.GaussRadau(U, num_stages - 1) + super(RadauIIA, self).__init__(L, 2 * num_stages - 1) + + def __str__(self): + return "RadauIIA(%d)" % self.num_stages + + +class BackwardEuler(RadauIIA): + """The rock-solid first-order implicit method.""" + + def __init__(self): + super(BackwardEuler, self).__init__(1) + + def __str__(self): + return ButcherTableau.__str__(self) + + +class LobattoIIIC(ButcherTableau): + """Discontinuous collocation method based on the Lobatto points. + The order of accuracy is 2 * `num_stages` - 2. + LobattoIIIC methods are A-, L-, algebraically, and B- stable. + + :arg num_stages: The number of stages (2 or greater) + """ + + def __init__(self, num_stages): + assert num_stages > 1 + # mooch the b and c from IIIA + IIIA = LobattoIIIA(num_stages) + b = IIIA.b + c = IIIA.c + + A = numpy.zeros((num_stages, num_stages)) + for i in range(num_stages): + A[i, 0] = b[0] + for j in range(num_stages): + A[-1, j] = b[j] + + mat = numpy.vander(c[1:], increasing=True).T + for i in range(num_stages - 1): + rhs = numpy.array([(c[i]**(k + 1)) / (k + 1) - b[0] * c[0]**k + for k in range(num_stages - 1)]) + A[i, 1:] = numpy.linalg.solve(mat, rhs) + + super(LobattoIIIC, self).__init__(A, b, None, c, 2 * num_stages - 2) + + def __str__(self): + return "LobattoIIIC(%d)" % self.num_stages + + +class PareschiRusso(ButcherTableau): + """Second order, diagonally implicit, 2-stage. + A-stable if x >= 1/4 and L-stable iff x = 1 plus/minus 1/sqrt(2).""" + + def __init__(self, x): + self.x = x + A = numpy.array([[x, 0.0], [1 - 2 * x, x]]) + b = numpy.array([0.5, 0.5]) + c = numpy.array([x, 1 - x]) + super(PareschiRusso, self).__init__(A, b, None, c, 2) + + def __str__(self): + return "PareschiRusso(%f)" % self.x + + +class QinZhang(PareschiRusso): + "Symplectic Pareschi-Russo DIRK" + + def __init__(self): + super(QinZhang, self).__init__(0.25) + + def __str__(self): + return "QinZhang()" diff --git a/partitioned-heat-conduction/solver-fenics/utils/__init__.py b/partitioned-heat-conduction/solver-fenics/utils/__init__.py new file mode 100644 index 000000000..c63bdeb86 --- /dev/null +++ b/partitioned-heat-conduction/solver-fenics/utils/__init__.py @@ -0,0 +1,7 @@ +from .ButcherTableaux import GaussLegendre # noqa: F401 +from .ButcherTableaux import LobattoIIIA # noqa: F401 +from .ButcherTableaux import LobattoIIIC # noqa: F401 +from .ButcherTableaux import BackwardEuler # noqa: F401 +from .ButcherTableaux import RadauIIA # noqa: F401 +from .ButcherTableaux import PareschiRusso # noqa: F401 +from .ButcherTableaux import QinZhang # noqa: F401 diff --git a/partitioned-heat-conduction/solver-fenics/utils/utils.py b/partitioned-heat-conduction/solver-fenics/utils/utils.py new file mode 100644 index 000000000..477ebf224 --- /dev/null +++ b/partitioned-heat-conduction/solver-fenics/utils/utils.py @@ -0,0 +1,79 @@ +""" +The core functionality of weak_lhs and get_variational_problem were taken from: + https://github.com/NikoWul/FenicsIrksome +""" + +import numpy as np +import scipy.interpolate as interpol +from fenics import * +from sympy import ccode, diff + + +def b_splines(precice, degree, dt): + ''' + :param degree: Degree of BSpline + :param precice: Object of preCICE + :param dt: current time step size + + Determines an approximation of the waveform from preCICE with BSplines. \n + The function assumes an equal set of nodes for the whole time interval! + ''' + # use equidistant samples + # documentation is not clear about how many samples are required. + no_samples = 1 + degree + nodes = np.linspace(0, dt, no_samples) + weights = np.array([None] * len(nodes)) + b_splns = {} + key_ref = precice.read_data(0).keys() + + i = 0 + for node in nodes: + val = precice.read_data(node) + # check if every key set is equal + assert (key_ref == val.keys()) + weights[i] = val + i += 1 + + for k in key_ref: + weights_k = [None] * len(nodes) + for i in range(no_samples): + weights_k[i] = weights[i][k] + b1, b2, b3 = interpol.splrep(nodes, weights_k, s=0, k=degree) + b_splns[k] = interpol.BSpline(b1, b2, b3, extrapolate=False) + return b_splns + + +def get_variational_problem(v, k, tsm, fs, dt, initial_condition): + """ + Following https://doi.org/10.1145/3466168, this function creates for each stage of the time stepping scheme + (Runge-Kutta methods) + ``tsm``, a weak formulation of a given equation. + As the stages of Runge-Kutta methods are the time derivatives at different times of the actual solution, + the solution of the variational problem this function returns, are the time derivatives at the respective stage times. + It is therefore necessary to assemble after solving the variational form returned by this function + the discrete evolution according to the time stepping scheme which is used.\n + **Note that this approach requires the time derivative of Dirichlet boundary conditions. + Neumann and Robin BCs do not need to be changed.** + :param v: test function + :param k: trial function + :param tsm: time stepping method which should be used + :param fs: rhs of the problem + :param dt: time step (must not be a float but a fenics expression! e.g. Constant(0)) + :param initial_condition: function which defined the inital value/initial condition + :return: returns variational problem (F=0) for the given parameters + """ + num_stages = tsm.num_stages + ks = split(k) + vs = split(v) + us = num_stages * [None] + for i in range(num_stages): + us[i] = initial_condition + for j in range(num_stages): + us[i] += tsm.A[i][j] * dt * ks[j] + + # Assemble weak form + F = 0 + for i in range(num_stages): + # cf. https://doi.org/10.1145/3466168 p.5 equation 14 + F += inner(ks[i], vs[i]) * dx + inner(grad(us[i]), grad(vs[i])) * dx - fs[i] * vs[i] * dx + return F diff --git a/partitioned-heat-conduction/solver-openfoam/.clang-format b/partitioned-heat-conduction/solver-openfoam/.clang-format new file mode 100644 index 000000000..00adea7a3 --- /dev/null +++ b/partitioned-heat-conduction/solver-openfoam/.clang-format @@ -0,0 +1,175 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +# +# Proposed clang-format-11 style for OpenFOAM, trying to follow the OpenFOAM style guide: +# https://develop.openfoam.com/Development/openfoam/-/wikis/coding/style/style +# Configuration developed for the OpenFOAM-preCICE adapter code: +# https://github.com/precice/openfoam-adapter +# Contribute to the discussion at the respective OpenFOAM issue: +# https://develop.openfoam.com/Development/openfoam/-/issues/1634 +# +# Keep `public:` at the first indentation level +AccessModifierOffset: -4 +# Undocumented guideline: align arguments after an open bracket. +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: false +AlignConsecutiveAssignments: false +AlignConsecutiveBitFields: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +# Align operands after operators (+,*,<<) (see BreakBeforeBinaryOperators) +AlignOperands: AlignAfterOperator +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Always +AllowShortLoopsOnASingleLine: false +# Guideline: Splitting return type and function name +# (this guideline is apparently not strictly followed in OpenFOAM) +# AlwaysBreakAfterReturnType: All +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +# Covered by "BreakBeforeBraces" +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: true + BeforeWhile: true + IndentBraces: true + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +# Guideline (almost): Splitting long lines at an = sign. Indent after split. +# Guideline (almost): Splitting formulae over several lines. +BreakBeforeBinaryOperators: NonAssignment +# Always break before braces: if, for, functions, classes, etc. +BreakBeforeBraces: Allman +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +# Guideline (almost): Splitting logical tests over several lines. +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +# Undocumented guideline (almost): Have the initializer : in a new line. +BreakConstructorInitializers: BeforeColon +BreakStringLiterals: true +# Here we could set the 80 charactes limit, but that would lead to more aggressive changes. +ColumnLimit: 0 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 0 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +# Undocumented guideline: add line after "public:" etc (since clang-format 12) +# EmptyLineAfterAccessModifier: Always +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +# Guideline: Macro loops are like for loops, but without a space. +ForEachMacros: + - forAllIters + - forAllConstIters + - forAllReverseIters + - forAllConstReverseIters + - forAll + - forAllReverse + - forAllIter + - forAllConstIter +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + - Regex: '.*' + Priority: 1 + SortPriority: 0 +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +# Guideline: The normal indentation is 4 spaces per logical level. +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +# Required to not change code following the guidelines +# "Leave two empty lines between sections" and +# "Use two empty lines between functions" +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: None +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +ReflowComments: true +# Do not change the order of include statements (could be catastrophic for OpenFOAM) +SortIncludes: false +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +# No "template " (guideline already used, but not documented) +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +# No a{1} (no guideline) +SpaceBeforeCpp11BracedList: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +# Guideline: Spaces in "if ()", "for ()", but not "forAll ()". +SpaceBeforeParens: ControlStatementsExceptForEachMacros +# Guideline: Range-based for should have a space surrounding the ':'. +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInConditionalStatement: false +# No "arr[3] = [ 1, 2, 3 ]" (no guideline). +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +# Treat the code as C++11 or later +Standard: Latest +StatementMacros: +TabWidth: 4 +UseCRLF: false +# Guideline: No tab characters - only use spaces for indentation. +UseTab: Never +WhitespaceSensitiveMacros: +... + diff --git a/partitioned-heat-conduction/solver-openfoam/.gitignore b/partitioned-heat-conduction/solver-openfoam/.gitignore new file mode 100644 index 000000000..1729c7850 --- /dev/null +++ b/partitioned-heat-conduction/solver-openfoam/.gitignore @@ -0,0 +1,4 @@ +Make/* +!Make/files +!Make/options +lnInclude/ diff --git a/partitioned-heat-conduction/openfoam-solver/Make/files b/partitioned-heat-conduction/solver-openfoam/Make/files similarity index 100% rename from partitioned-heat-conduction/openfoam-solver/Make/files rename to partitioned-heat-conduction/solver-openfoam/Make/files diff --git a/partitioned-heat-conduction/openfoam-solver/Make/options b/partitioned-heat-conduction/solver-openfoam/Make/options similarity index 88% rename from partitioned-heat-conduction/openfoam-solver/Make/options rename to partitioned-heat-conduction/solver-openfoam/Make/options index 04ef6c148..d27c95d03 100644 --- a/partitioned-heat-conduction/openfoam-solver/Make/options +++ b/partitioned-heat-conduction/solver-openfoam/Make/options @@ -4,5 +4,4 @@ EXE_INC = \ EXE_LIBS = \ -lfiniteVolume \ - -lfvOptions \ -lmeshTools diff --git a/partitioned-heat-conduction/openfoam-solver/clean.sh b/partitioned-heat-conduction/solver-openfoam/clean.sh similarity index 100% rename from partitioned-heat-conduction/openfoam-solver/clean.sh rename to partitioned-heat-conduction/solver-openfoam/clean.sh diff --git a/partitioned-heat-conduction/openfoam-solver/createFields.H b/partitioned-heat-conduction/solver-openfoam/createFields.H similarity index 53% rename from partitioned-heat-conduction/openfoam-solver/createFields.H rename to partitioned-heat-conduction/solver-openfoam/createFields.H index e10432449..e3e245c83 100644 --- a/partitioned-heat-conduction/openfoam-solver/createFields.H +++ b/partitioned-heat-conduction/solver-openfoam/createFields.H @@ -1,48 +1,37 @@ -Info<< "Reading field T\n" << endl; +Info << "Reading field T\n" + << endl; -volScalarField T -( - IOobject - ( +volScalarField T( + IOobject( "T", runTime.timeName(), mesh, IOobject::MUST_READ, - IOobject::AUTO_WRITE - ), - mesh -); + IOobject::AUTO_WRITE), + mesh); +Info << "Reading diffusivity DT\n" + << endl; -Info<< "Reading diffusivity DT\n" << endl; - -volScalarField DT -( - IOobject - ( +volScalarField DT( + IOobject( "DT", runTime.timeName(), mesh, IOobject::READ_IF_PRESENT, - IOobject::AUTO_WRITE - ), + IOobject::AUTO_WRITE), mesh, - dimensionedScalar(dimViscosity, Zero) -); + dimensionedScalar(dimViscosity, Zero)); if (!DT.headerOk()) { - IOdictionary transportProperties - ( - IOobject - ( + IOdictionary transportProperties( + IOobject( "transportProperties", runTime.constant(), mesh, IOobject::MUST_READ_IF_MODIFIED, - IOobject::NO_WRITE - ) - ); + IOobject::NO_WRITE)); DT = dimensionedScalar("DT", dimViscosity, transportProperties); } diff --git a/partitioned-heat-conduction/openfoam-solver/heatTransfer.C b/partitioned-heat-conduction/solver-openfoam/heatTransfer.C similarity index 64% rename from partitioned-heat-conduction/openfoam-solver/heatTransfer.C rename to partitioned-heat-conduction/solver-openfoam/heatTransfer.C index a089d6ee0..7e3b4887f 100644 --- a/partitioned-heat-conduction/openfoam-solver/heatTransfer.C +++ b/partitioned-heat-conduction/solver-openfoam/heatTransfer.C @@ -40,70 +40,63 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -int main(int argc, char *argv[]) +int main(int argc, char* argv[]) { - argList::addNote - ( - "Laplace equation solver for a scalar quantity." - ); + argList::addNote( + "Laplace equation solver for a scalar quantity."); - #include "postProcess.H" +#include "postProcess.H" - #include "setRootCaseLists.H" - #include "createTime.H" - #include "createMesh.H" +#include "setRootCaseLists.H" +#include "createTime.H" +#include "createMesh.H" simpleControl simple(mesh); - #include "createFields.H" +#include "createFields.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - Info<< "\nCalculating temperature distribution\n" << endl; + Info << "\nCalculating temperature distribution\n" + << endl; const double alpha = 3; - const double beta = 1.3; - const double rhs = beta - 2 - 2 * alpha; - - volScalarField f - ( - IOobject - ( - "RHS", - runTime.timeName(), - mesh, - IOobject::NO_READ, - IOobject::NO_WRITE - ), - mesh, - dimensionedScalar( - "Tdim", - dimensionSet(0, 0, -1, 1, 0, 0, 0), - Foam::scalar(rhs)) - ); + const double beta = 1.3; + const double rhs = beta - 2 - 2 * alpha; + + volScalarField f( + IOobject( + "RHS", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::NO_WRITE), + mesh, + dimensionedScalar( + "Tdim", + dimensionSet(0, 0, -1, 1, 0, 0, 0), + Foam::scalar(rhs))); while (simple.loop(runTime)) { - Info<< "Time = " << runTime.timeName() << nl << endl; + Info << "Time = " << runTime.timeName() << nl << endl; while (simple.correctNonOrthogonal()) { - fvScalarMatrix TEqn - ( - fvm::ddt(T) - fvm::laplacian(DT, T) - fvm::Su(f,T) - == - fvModels.source(T) - ); + fvScalarMatrix TEqn( + fvm::ddt(T) - fvm::laplacian(DT, T) - fvm::Su(f, T) + == fvModels.source(T)); fvConstraints.constrain(TEqn); TEqn.solve(); fvConstraints.constrain(T); } - #include "write.H" +#include "write.H" } - Info<< "End\n" << endl; + Info << "End\n" + << endl; return 0; } diff --git a/partitioned-heat-conduction/solver-openfoam/openfoam-solver/heatTransfer.C b/partitioned-heat-conduction/solver-openfoam/openfoam-solver/heatTransfer.C new file mode 100644 index 000000000..7e3b4887f --- /dev/null +++ b/partitioned-heat-conduction/solver-openfoam/openfoam-solver/heatTransfer.C @@ -0,0 +1,105 @@ +// This solver is based on previous work of OpenCFD Ltd. In particular, major code +// parts are part of the laplacianFoam solver of OpenFOAM 2012, which served as a +// basis for this solver. +// ------------------------------------------------------------------------------- +// Application +// heatTransfer +// +// Group +// grpBasicSolvers +// +// Description +// Modified version of the Laplace equation solver for a scalar quantity with +// a non-zero RHS. +// +// \heading Solver details +// The solver is applicable to, e.g. for thermal diffusion in a solid. The +// equation is given by: +// +// \f[ +// \ddt{T} = \div \left( D_T \grad T \right) + F +// \f] +// +// Where: +// \vartable +// T | Scalar field which is solved for, e.g. temperature +// D_T | Diffusion coefficient +// F | The RHS which is defined as: beta - 2 - 2 * alpha +// \endvartable +// +// \heading Required fields +// \plaintable +// T | Scalar field which is solved for, e.g. temperature +// \endplaintable + + +#include "fvCFD.H" +#include "fvModels.H" +#include "fvConstraints.H" +#include "simpleControl.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +int main(int argc, char* argv[]) +{ + argList::addNote( + "Laplace equation solver for a scalar quantity."); + +#include "postProcess.H" + +#include "setRootCaseLists.H" +#include "createTime.H" +#include "createMesh.H" + + simpleControl simple(mesh); + +#include "createFields.H" + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + Info << "\nCalculating temperature distribution\n" + << endl; + + const double alpha = 3; + const double beta = 1.3; + const double rhs = beta - 2 - 2 * alpha; + + volScalarField f( + IOobject( + "RHS", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::NO_WRITE), + mesh, + dimensionedScalar( + "Tdim", + dimensionSet(0, 0, -1, 1, 0, 0, 0), + Foam::scalar(rhs))); + + while (simple.loop(runTime)) + { + Info << "Time = " << runTime.timeName() << nl << endl; + + while (simple.correctNonOrthogonal()) + { + fvScalarMatrix TEqn( + fvm::ddt(T) - fvm::laplacian(DT, T) - fvm::Su(f, T) + == fvModels.source(T)); + + fvConstraints.constrain(TEqn); + TEqn.solve(); + fvConstraints.constrain(T); + } + +#include "write.H" + } + + Info << "End\n" + << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/partitioned-heat-conduction/solver-openfoam/write.H b/partitioned-heat-conduction/solver-openfoam/write.H new file mode 100644 index 000000000..3c74dc1ba --- /dev/null +++ b/partitioned-heat-conduction/solver-openfoam/write.H @@ -0,0 +1,91 @@ +// We need to disable the runTime.writeTime if condition for implicit coupling +// as the condition only returns true in the very first coupling iteration +// if (runTime.writeTime()) +{ + volVectorField gradT(fvc::grad(T)); + + volScalarField gradTx( + IOobject( + "gradTx", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE), + gradT.component(vector::X)); + + volScalarField gradTy( + IOobject( + "gradTy", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE), + gradT.component(vector::Y)); + + volScalarField gradTz( + IOobject( + "gradTz", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE), + gradT.component(vector::Z)); + + volVectorField DTgradT( + IOobject( + "flux", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE), + DT * gradT); + volScalarField error_total( + IOobject( + "error", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE), + DT * 0); + + /** Not available in OpenFOAM.org + // Print error metrics + Functions::compute_and_print_errors(mesh, alpha, beta, runTime.value()); + + // compute and store the error also in a paraView field + { + const Foam::volScalarField* T_(&mesh.lookupObject("T")); + + // Get the locations of the volume centered mesh vertices + const vectorField& CellCenters = mesh.C(); + + for (int i = 0; i < CellCenters.size(); i++) + { + const double coord_x = CellCenters[i].x(); + const double coord_y = CellCenters[i].y(); + const double exact_solution = Functions::get_solution(coord_x, coord_y, alpha, beta, runTime.value()); + + error_total.ref()[i] = std::abs((exact_solution - T_->internalField()[i])); + } + + T.correctBoundaryConditions(); + for (int j = 0; j < mesh.boundaryMesh().size() - 1; ++j) + { + // Get the face centers of the current patch + const vectorField faceCenters = + mesh.boundaryMesh()[j].faceCentres(); + + // Assign the (x,y,z) locations to the vertices + for (int i = 0; i < faceCenters.size(); i++) + { + const double coord_x = faceCenters[i].x(); + const double coord_y = faceCenters[i].y(); + const double exact_solution = Functions::get_solution(coord_x, coord_y, alpha, beta, runTime.value()); + error_total.boundaryFieldRef()[j][i] = std::abs(exact_solution - T_->boundaryField()[j][i]); + } + } + } + */ + + runTime.write(); +} diff --git a/partitioned-pipe-two-phase/README.md b/partitioned-pipe-two-phase/README.md new file mode 100644 index 000000000..6e6fc0762 --- /dev/null +++ b/partitioned-pipe-two-phase/README.md @@ -0,0 +1,75 @@ +--- +title: Partitioned pipe two phase +permalink: tutorials-partitioned-pipe-two-phase.html +keywords: tutorial, FF, fluid-fluid coupling, OpenFOAM, interFoam, multiphase +summary: This tutorial describes how to run a partitioned two-phse fluid simulation using preCICE. +--- + +{% note %} +Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/partitioned-pipe-two-phase). Read how in the [tutorials introduction](https://www.precice.org/tutorials.html). +{% endnote %} + +## Setup + +This scenario consists of two pipes connected in series, both simulated with OpenFOAM's interFoam solver. Fluids can enter from the left (here $$ z=0 $$) boundary of the Fluid1 participant with a uniform velocity profile ($$ u_{in} = 1 m/s $$) and fixed flux pressure boundary coundition. +The simulation begins with some water being present at the bottom left of the pipe. The volume fraction variable alpha is set to be 1 (water) at the bottom half of the inlet and 0 (air) at the top half. The water stream will approach the coupling interface at around $$ t=5s $$ in the simulation. +At the right boundary of Fluid2 there is a zero gradient boundary condition for velocity and alpha as well as a total pressure set to zero. + +![two-phase-setup](images/tutorials-partitioned-pipe-two-phase-setup.png) + +On the coupling interface, Fluid1 sends velocity, and alpha to Fluid2 and receives pressure, velocity gradient and alpha gradient. Fluid2 uses the [fixedFluxExtrapolatedPressure](https://www.openfoam.com/documentation/guides/v2112/api/classFoam_1_1fixedFluxExtrapolatedPressureFvPatchScalarField.html) boundary condition as shown in the [partitioned pipe tutorial](https://precice.org/tutorials-partitioned-pipe.html). + +To make sure that preCICE works on the correct OpenFOAM fields, the field names are passed to the OpenFOAM adapter in `fluid*/system/preciceDict`: + +```CPP +FF +{ + nameP p_rgh; + nameAlpha alpha.water; +} +``` + +{% note %} +This is a very basic example case demonstrating the coupling of a two-phase flow. To keep it as simple as possible, gravity is set to $0$ to avoid any kind of turbulences/vortices. Read more in the accompanying conference paper [1]. +{% endnote %} + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-partitioned-pipe-two-phase-precice-config.png) + +## Available solvers + +Both Fluid1 and Fluid2 are simulated with OpenFOAM (interFoam). An incompressible multiphase solver for two immiscible fluids using the *Volume-of-fluid* method. For more information, have a look at the [OpenFOAM adapter documentation](https://www.precice.org/adapter-openfoam-overview.html). + +## Running the Simulation + +Open two separate terminals and start the fluid1 and fluid2 participants by calling the respective run script. For example: + +```bash +cd fluid1-openfoam +./run.sh +``` + +and + +```bash +cd fluid2-openfoam +./run.sh +``` + +## Post-processing + +The OpenFOAM solvers generate a `.foam` file each. You can open this file in ParaView. +You can see the water-air interface crossing the coupling interface at around $t=5.0s$. + +![result](images/tutorials-partitioned-pipe-two-phase-result.png) + +{% disclaimer %} +This offering is not approved or endorsed by OpenCFD Limited, producer and distributor of the OpenFOAM software via www.openfoam.com, and owner of the OPENFOAM® and OpenCFD® trade marks. +{% enddisclaimer %} + +## References + +[1] M. Mühlhäußer, G. Chourdakis and B. Uekermann, Partitioned Flow Simulations with preCICE and OpenFOAM, in: COUPLED 2023. DOI: [10.23967/c.coupled.2023.014](https://doi.org/10.23967/c.coupled.2023.014) diff --git a/partitioned-pipe-two-phase/clean-tutorial.sh b/partitioned-pipe-two-phase/clean-tutorial.sh new file mode 120000 index 000000000..4713f5092 --- /dev/null +++ b/partitioned-pipe-two-phase/clean-tutorial.sh @@ -0,0 +1 @@ +../tools/clean-tutorial-base.sh \ No newline at end of file diff --git a/partitioned-pipe-two-phase/fluid1-openfoam/0.orig/U b/partitioned-pipe-two-phase/fluid1-openfoam/0.orig/U new file mode 100644 index 000000000..772073697 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid1-openfoam/0.orig/U @@ -0,0 +1,36 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0 0 1); + +boundaryField +{ + inlet + { + type fixedValue; + value uniform (0 0 1); + } + + outlet + { + type fixedGradient; + gradient uniform (0 0 0); + } + + fixedWalls + { + type noSlip; + } + + defaultFaces + { + type empty; + } +} diff --git a/partitioned-pipe-two-phase/fluid1-openfoam/0.orig/alpha.water b/partitioned-pipe-two-phase/fluid1-openfoam/0.orig/alpha.water new file mode 100644 index 000000000..cc05137e3 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid1-openfoam/0.orig/alpha.water @@ -0,0 +1,57 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object alpha.water; +} + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + inlet + { + type codedFixedValue; + value uniform 1; + + // Name of generated boundary condition + name halvedFixedValue; + + // Split the inlet in half water / half air across the y-axis. + code + #{ + const vectorField &faceCenters = this->patch().Cf(); + scalarField &alphaIn = *this; + forAll(faceCenters, faceID) + { + if (faceCenters[faceID].y() < 0.0) + { + alphaIn[faceID] = 1.0; + } + else + { + alphaIn[faceID] = 0.0; + } + } + #}; + } + + outlet + { + type fixedGradient; + gradient uniform 0; + } + + fixedWalls + { + type zeroGradient; + } + + defaultFaces + { + type empty; + } +} diff --git a/partitioned-pipe-two-phase/fluid1-openfoam/0.orig/p_rgh b/partitioned-pipe-two-phase/fluid1-openfoam/0.orig/p_rgh new file mode 100644 index 000000000..3404840c1 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid1-openfoam/0.orig/p_rgh @@ -0,0 +1,37 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p_rgh; +} + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + inlet + { + type fixedFluxPressure; + value uniform 0; + } + + outlet + { + type fixedValue; + value uniform 0; + } + + fixedWalls + { + type fixedFluxPressure; + value uniform 0; + } + + defaultFaces + { + type empty; + } +} diff --git a/partitioned-pipe-two-phase/fluid1-openfoam/clean.sh b/partitioned-pipe-two-phase/fluid1-openfoam/clean.sh new file mode 100755 index 000000000..144bd0dc4 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid1-openfoam/clean.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . +rm -rf ./0/ diff --git a/partitioned-pipe-two-phase/fluid1-openfoam/constant/g b/partitioned-pipe-two-phase/fluid1-openfoam/constant/g new file mode 100644 index 000000000..858f3457c --- /dev/null +++ b/partitioned-pipe-two-phase/fluid1-openfoam/constant/g @@ -0,0 +1,10 @@ +FoamFile +{ + version 2.0; + format ascii; + class uniformDimensionedVectorField; + object g; +} + +dimensions [0 1 -2 0 0 0 0]; +value (0 0 0); diff --git a/partitioned-pipe-two-phase/fluid1-openfoam/constant/transportProperties b/partitioned-pipe-two-phase/fluid1-openfoam/constant/transportProperties new file mode 100644 index 000000000..31085647a --- /dev/null +++ b/partitioned-pipe-two-phase/fluid1-openfoam/constant/transportProperties @@ -0,0 +1,25 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object transportProperties; +} + +phases (water air); + +water +{ + transportModel Newtonian; + nu 1e-06; + rho 1000; +} + +air +{ + transportModel Newtonian; + nu 1.48e-05; + rho 1; +} + +sigma 0.07; diff --git a/partitioned-pipe-two-phase/fluid1-openfoam/constant/turbulenceProperties b/partitioned-pipe-two-phase/fluid1-openfoam/constant/turbulenceProperties new file mode 100644 index 000000000..b75c49530 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid1-openfoam/constant/turbulenceProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object turbulenceProperties; +} + +simulationType laminar; diff --git a/partitioned-pipe-two-phase/fluid1-openfoam/run.sh b/partitioned-pipe-two-phase/fluid1-openfoam/run.sh new file mode 100755 index 000000000..63adb50c4 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid1-openfoam/run.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh +cp -r 0.orig 0 +setFields + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/partitioned-pipe-two-phase/fluid1-openfoam/system/blockMeshDict b/partitioned-pipe-two-phase/fluid1-openfoam/system/blockMeshDict new file mode 100644 index 000000000..e11f0201f --- /dev/null +++ b/partitioned-pipe-two-phase/fluid1-openfoam/system/blockMeshDict @@ -0,0 +1,77 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant/polyMesh"; + object blockMeshDict; +} + +scale 1; + + +zmin 0; +zmax 10; + +xcells 1; // per block (5 blocks) +ycells 10; // per block (5 blocks) +zcells 20; + +vertices +( + (0.0 -2.0 $zmin) // 0 + (0.0 2.0 $zmin) // 1 + (0.0 -2.0 $zmax) // 2 + (0.0 2.0 $zmax)// 3 + (-1.0 -2.0 $zmin) // 4 + (-1.0 2.0 $zmin) // 5 + (-1.0 -2.0 $zmax) // 6 + (-1.0 2.0 $zmax) // 7 +); + +blocks +( +hex (4 0 1 5 6 2 3 7) pipe ($xcells $ycells $zcells) edgeGrading (1 1 1 1 1 1 1 1 1 1 1 1) +); + +edges +( +); + + +patches +( + + patch fixedWalls + ( + (0 4 6 2) + (1 3 7 5) + ) + + patch inlet + ( + (0 1 5 4) + ) + + patch outlet + ( + (3 2 6 7) + ) +); + +boundaries +( + emptyWalls + { + type empty; + faces + ( + (0 2 3 1) + (4 5 7 6) + ) + } +); + +mergePatchPairs +( +); diff --git a/partitioned-pipe-two-phase/fluid1-openfoam/system/controlDict b/partitioned-pipe-two-phase/fluid1-openfoam/system/controlDict new file mode 100644 index 000000000..b30459654 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid1-openfoam/system/controlDict @@ -0,0 +1,55 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} + +application interFoam; + +startFrom startTime; + +startTime 0.0; + +stopAt endTime; + +endTime 20; + +deltaT 0.05; + +writeControl adjustable; + +writeInterval 0.1; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable yes; + +adjustTimeStep no; + +maxCo 1; + +maxAlphaCo 1; + +maxDeltaT 1; + + +libs ("libpreciceAdapterFunctionObject.so"); +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + } +} diff --git a/partitioned-pipe-two-phase/fluid1-openfoam/system/decomposeParDict b/partitioned-pipe-two-phase/fluid1-openfoam/system/decomposeParDict new file mode 100644 index 000000000..05708e995 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid1-openfoam/system/decomposeParDict @@ -0,0 +1,16 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object decomposeParDict; +} + +numberOfSubdomains 4; + +method simple; + +coeffs +{ + n (2 2 1); +} diff --git a/partitioned-pipe-two-phase/fluid1-openfoam/system/fvSchemes b/partitioned-pipe-two-phase/fluid1-openfoam/system/fvSchemes new file mode 100644 index 000000000..1325b0200 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid1-openfoam/system/fvSchemes @@ -0,0 +1,40 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ + div(rhoPhi,U) Gauss linearUpwind grad(U); + div(phi,alpha) Gauss vanLeer; + div(phirb,alpha) Gauss linear; + div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/partitioned-pipe-two-phase/fluid1-openfoam/system/fvSolution b/partitioned-pipe-two-phase/fluid1-openfoam/system/fvSolution new file mode 100644 index 000000000..9c2b40aba --- /dev/null +++ b/partitioned-pipe-two-phase/fluid1-openfoam/system/fvSolution @@ -0,0 +1,75 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSolution; +} + +solvers +{ + "alpha.water.*" + { + nAlphaCorr 2; + nAlphaSubCycles 1; + cAlpha 1; + + MULESCorr yes; + nLimiterIter 5; + + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-8; + relTol 0; + } + + "pcorr.*" + { + solver PCG; + preconditioner DIC; + tolerance 1e-5; + relTol 0; + } + + p_rgh + { + solver PCG; + preconditioner DIC; + tolerance 1e-07; + relTol 0.05; + } + + p_rghFinal + { + $p_rgh; + relTol 0; + } + + U + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-06; + relTol 0; + } + UFinal + { + $U; + } +} + +PIMPLE +{ + momentumPredictor no; + nOuterCorrectors 1; + nCorrectors 3; + nNonOrthogonalCorrectors 0; +} + +relaxationFactors +{ + equations + { + ".*" 1; + } +} diff --git a/partitioned-pipe-two-phase/fluid1-openfoam/system/preciceDict b/partitioned-pipe-two-phase/fluid1-openfoam/system/preciceDict new file mode 100644 index 000000000..8b4aa4da6 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid1-openfoam/system/preciceDict @@ -0,0 +1,42 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Fluid1; + +modules (FF); + +interfaces +{ + Interface1 + { + mesh Fluid1-Mesh; + patches (outlet); + + readData + ( + Pressure + VelocityGradient + AlphaGradient + ); + + writeData + ( + Velocity + Alpha + ); + }; +}; + +FF +{ + nameP p_rgh; + nameAlpha alpha.water; +} diff --git a/partitioned-pipe-two-phase/fluid1-openfoam/system/setFieldsDict b/partitioned-pipe-two-phase/fluid1-openfoam/system/setFieldsDict new file mode 100644 index 000000000..f724fdbfc --- /dev/null +++ b/partitioned-pipe-two-phase/fluid1-openfoam/system/setFieldsDict @@ -0,0 +1,24 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object setFieldsDict; +} + +defaultFieldValues +( + volScalarFieldValue alpha.water 0 +); + +regions +( + boxToCell + { + box (-1 -2 0) (0 0 5); + fieldValues + ( + volScalarFieldValue alpha.water 1 + ); + } +); diff --git a/partitioned-pipe-two-phase/fluid2-openfoam/0.orig/U b/partitioned-pipe-two-phase/fluid2-openfoam/0.orig/U new file mode 100644 index 000000000..8fd51dc2f --- /dev/null +++ b/partitioned-pipe-two-phase/fluid2-openfoam/0.orig/U @@ -0,0 +1,36 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0 0 1); + +boundaryField +{ + inlet + { + type fixedValue; + value uniform (0 0 0); + } + + outlet + { + type fixedGradient; + gradient uniform (0 0 0); + } + + fixedWalls + { + type noSlip; + } + + defaultFaces + { + type empty; + } +} diff --git a/partitioned-pipe-two-phase/fluid2-openfoam/0.orig/alpha.water b/partitioned-pipe-two-phase/fluid2-openfoam/0.orig/alpha.water new file mode 100644 index 000000000..60db2bb30 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid2-openfoam/0.orig/alpha.water @@ -0,0 +1,36 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object alpha.water; +} + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + inlet + { + type fixedValue; + value uniform 0; + } + + outlet + { + type fixedGradient; + gradient uniform 0; + } + + fixedWalls + { + type zeroGradient; + } + + defaultFaces + { + type empty; + } +} diff --git a/partitioned-pipe-two-phase/fluid2-openfoam/0.orig/p_rgh b/partitioned-pipe-two-phase/fluid2-openfoam/0.orig/p_rgh new file mode 100644 index 000000000..b4b6984a2 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid2-openfoam/0.orig/p_rgh @@ -0,0 +1,37 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p_rgh; +} + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + inlet + { + type fixedFluxExtrapolatedPressure; + value uniform 0; + } + + outlet + { + type fixedValue; + value uniform 0; + } + + fixedWalls + { + type fixedFluxPressure; + value uniform 0; + } + + defaultFaces + { + type empty; + } +} diff --git a/partitioned-pipe-two-phase/fluid2-openfoam/clean.sh b/partitioned-pipe-two-phase/fluid2-openfoam/clean.sh new file mode 100755 index 000000000..144bd0dc4 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid2-openfoam/clean.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . +rm -rf ./0/ diff --git a/partitioned-pipe-two-phase/fluid2-openfoam/constant/g b/partitioned-pipe-two-phase/fluid2-openfoam/constant/g new file mode 100644 index 000000000..858f3457c --- /dev/null +++ b/partitioned-pipe-two-phase/fluid2-openfoam/constant/g @@ -0,0 +1,10 @@ +FoamFile +{ + version 2.0; + format ascii; + class uniformDimensionedVectorField; + object g; +} + +dimensions [0 1 -2 0 0 0 0]; +value (0 0 0); diff --git a/partitioned-pipe-two-phase/fluid2-openfoam/constant/transportProperties b/partitioned-pipe-two-phase/fluid2-openfoam/constant/transportProperties new file mode 100644 index 000000000..31085647a --- /dev/null +++ b/partitioned-pipe-two-phase/fluid2-openfoam/constant/transportProperties @@ -0,0 +1,25 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object transportProperties; +} + +phases (water air); + +water +{ + transportModel Newtonian; + nu 1e-06; + rho 1000; +} + +air +{ + transportModel Newtonian; + nu 1.48e-05; + rho 1; +} + +sigma 0.07; diff --git a/partitioned-pipe-two-phase/fluid2-openfoam/constant/turbulenceProperties b/partitioned-pipe-two-phase/fluid2-openfoam/constant/turbulenceProperties new file mode 100644 index 000000000..b75c49530 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid2-openfoam/constant/turbulenceProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object turbulenceProperties; +} + +simulationType laminar; diff --git a/partitioned-pipe-two-phase/fluid2-openfoam/run.sh b/partitioned-pipe-two-phase/fluid2-openfoam/run.sh new file mode 100755 index 000000000..63adb50c4 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid2-openfoam/run.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh +cp -r 0.orig 0 +setFields + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/partitioned-pipe-two-phase/fluid2-openfoam/system/blockMeshDict b/partitioned-pipe-two-phase/fluid2-openfoam/system/blockMeshDict new file mode 100644 index 000000000..14c9579fe --- /dev/null +++ b/partitioned-pipe-two-phase/fluid2-openfoam/system/blockMeshDict @@ -0,0 +1,77 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant/polyMesh"; + object blockMeshDict; +} + +scale 1; + + +zmin 10; +zmax 20; + +xcells 1; // per block (5 blocks) +ycells 10; // per block (5 blocks) +zcells 20; + +vertices +( + (0.0 -2.0 $zmin) // 0 + (0.0 2.0 $zmin) // 1 + (0.0 -2.0 $zmax) // 2 + (0.0 2.0 $zmax)// 3 + (-1.0 -2.0 $zmin) // 4 + (-1.0 2.0 $zmin) // 5 + (-1.0 -2.0 $zmax) // 6 + (-1.0 2.0 $zmax) // 7 +); + +blocks +( +hex (4 0 1 5 6 2 3 7) pipe ($xcells $ycells $zcells) edgeGrading (1 1 1 1 1 1 1 1 1 1 1 1) +); + +edges +( +); + + +patches +( + + patch fixedWalls + ( + (0 4 6 2) + (1 3 7 5) + ) + + patch inlet + ( + (0 1 5 4) + ) + + patch outlet + ( + (3 2 6 7) + ) +); + +boundaries +( + emptyWalls + { + type empty; + faces + ( + (0 2 3 1) + (4 5 7 6) + ) + } +); + +mergePatchPairs +( +); diff --git a/partitioned-pipe-two-phase/fluid2-openfoam/system/controlDict b/partitioned-pipe-two-phase/fluid2-openfoam/system/controlDict new file mode 100644 index 000000000..b30459654 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid2-openfoam/system/controlDict @@ -0,0 +1,55 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} + +application interFoam; + +startFrom startTime; + +startTime 0.0; + +stopAt endTime; + +endTime 20; + +deltaT 0.05; + +writeControl adjustable; + +writeInterval 0.1; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable yes; + +adjustTimeStep no; + +maxCo 1; + +maxAlphaCo 1; + +maxDeltaT 1; + + +libs ("libpreciceAdapterFunctionObject.so"); +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + } +} diff --git a/partitioned-pipe-two-phase/fluid2-openfoam/system/decomposeParDict b/partitioned-pipe-two-phase/fluid2-openfoam/system/decomposeParDict new file mode 100644 index 000000000..05708e995 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid2-openfoam/system/decomposeParDict @@ -0,0 +1,16 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object decomposeParDict; +} + +numberOfSubdomains 4; + +method simple; + +coeffs +{ + n (2 2 1); +} diff --git a/partitioned-pipe-two-phase/fluid2-openfoam/system/fvSchemes b/partitioned-pipe-two-phase/fluid2-openfoam/system/fvSchemes new file mode 100644 index 000000000..1325b0200 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid2-openfoam/system/fvSchemes @@ -0,0 +1,40 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ + div(rhoPhi,U) Gauss linearUpwind grad(U); + div(phi,alpha) Gauss vanLeer; + div(phirb,alpha) Gauss linear; + div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/partitioned-pipe-two-phase/fluid2-openfoam/system/fvSolution b/partitioned-pipe-two-phase/fluid2-openfoam/system/fvSolution new file mode 100644 index 000000000..9c2b40aba --- /dev/null +++ b/partitioned-pipe-two-phase/fluid2-openfoam/system/fvSolution @@ -0,0 +1,75 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSolution; +} + +solvers +{ + "alpha.water.*" + { + nAlphaCorr 2; + nAlphaSubCycles 1; + cAlpha 1; + + MULESCorr yes; + nLimiterIter 5; + + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-8; + relTol 0; + } + + "pcorr.*" + { + solver PCG; + preconditioner DIC; + tolerance 1e-5; + relTol 0; + } + + p_rgh + { + solver PCG; + preconditioner DIC; + tolerance 1e-07; + relTol 0.05; + } + + p_rghFinal + { + $p_rgh; + relTol 0; + } + + U + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-06; + relTol 0; + } + UFinal + { + $U; + } +} + +PIMPLE +{ + momentumPredictor no; + nOuterCorrectors 1; + nCorrectors 3; + nNonOrthogonalCorrectors 0; +} + +relaxationFactors +{ + equations + { + ".*" 1; + } +} diff --git a/partitioned-pipe-two-phase/fluid2-openfoam/system/preciceDict b/partitioned-pipe-two-phase/fluid2-openfoam/system/preciceDict new file mode 100644 index 000000000..968224d5b --- /dev/null +++ b/partitioned-pipe-two-phase/fluid2-openfoam/system/preciceDict @@ -0,0 +1,42 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Fluid2; + +modules (FF); + +interfaces +{ + Interface1 + { + mesh Fluid2-Mesh; + patches (inlet); + + readData + ( + Velocity + Alpha + ); + + writeData + ( + Pressure + VelocityGradient + AlphaGradient + ); + }; +}; + +FF +{ + nameP p_rgh; + nameAlpha alpha.water; +} diff --git a/partitioned-pipe-two-phase/fluid2-openfoam/system/setFieldsDict b/partitioned-pipe-two-phase/fluid2-openfoam/system/setFieldsDict new file mode 100644 index 000000000..e7e2b05b4 --- /dev/null +++ b/partitioned-pipe-two-phase/fluid2-openfoam/system/setFieldsDict @@ -0,0 +1,24 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object setFieldsDict; +} + +defaultFieldValues +( + volScalarFieldValue alpha.water 0 +); + +regions +( + boxToCell + { + box (-1 -5 20) (0 0 40); + fieldValues + ( + volScalarFieldValue alpha.water 0 + ); + } +); diff --git a/partitioned-pipe-two-phase/images/tutorials-partitioned-pipe-two-phase-precice-config.png b/partitioned-pipe-two-phase/images/tutorials-partitioned-pipe-two-phase-precice-config.png new file mode 100644 index 000000000..4df21ef55 Binary files /dev/null and b/partitioned-pipe-two-phase/images/tutorials-partitioned-pipe-two-phase-precice-config.png differ diff --git a/partitioned-pipe-two-phase/images/tutorials-partitioned-pipe-two-phase-result.png b/partitioned-pipe-two-phase/images/tutorials-partitioned-pipe-two-phase-result.png new file mode 100644 index 000000000..0d0e01d78 Binary files /dev/null and b/partitioned-pipe-two-phase/images/tutorials-partitioned-pipe-two-phase-result.png differ diff --git a/partitioned-pipe-two-phase/images/tutorials-partitioned-pipe-two-phase-setup.png b/partitioned-pipe-two-phase/images/tutorials-partitioned-pipe-two-phase-setup.png new file mode 100644 index 000000000..575660240 Binary files /dev/null and b/partitioned-pipe-two-phase/images/tutorials-partitioned-pipe-two-phase-setup.png differ diff --git a/partitioned-pipe-two-phase/monolithic/0.orig/U b/partitioned-pipe-two-phase/monolithic/0.orig/U new file mode 100644 index 000000000..772073697 --- /dev/null +++ b/partitioned-pipe-two-phase/monolithic/0.orig/U @@ -0,0 +1,36 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0 0 1); + +boundaryField +{ + inlet + { + type fixedValue; + value uniform (0 0 1); + } + + outlet + { + type fixedGradient; + gradient uniform (0 0 0); + } + + fixedWalls + { + type noSlip; + } + + defaultFaces + { + type empty; + } +} diff --git a/partitioned-pipe-two-phase/monolithic/0.orig/alpha.water b/partitioned-pipe-two-phase/monolithic/0.orig/alpha.water new file mode 100644 index 000000000..04a47d879 --- /dev/null +++ b/partitioned-pipe-two-phase/monolithic/0.orig/alpha.water @@ -0,0 +1,59 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object alpha.water; +} + +dimensions [0 0 0 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + inlet + { + type codedFixedValue; + value uniform 1; + + // Name of generated boundary condition + name halvedFixedValue; + + // Split the inlet in half water / half air across the y-axis. + code + #{ + const vectorField &faceCenters = this->patch().Cf(); + scalarField &alphaIn = *this; + forAll(faceCenters, faceID) + { + if (faceCenters[faceID].y() < 0.0) + { + alphaIn[faceID] = 1.0; + } + else + { + alphaIn[faceID] = 0.0; + } + } + #}; + } + + outlet + { + type inletOutlet; + value uniform 0; + inletValue uniform 0; + gradient uniform 0; + } + + fixedWalls + { + type zeroGradient; + } + + defaultFaces + { + type empty; + } +} diff --git a/partitioned-pipe-two-phase/monolithic/0.orig/p_rgh b/partitioned-pipe-two-phase/monolithic/0.orig/p_rgh new file mode 100644 index 000000000..3404840c1 --- /dev/null +++ b/partitioned-pipe-two-phase/monolithic/0.orig/p_rgh @@ -0,0 +1,37 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p_rgh; +} + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + inlet + { + type fixedFluxPressure; + value uniform 0; + } + + outlet + { + type fixedValue; + value uniform 0; + } + + fixedWalls + { + type fixedFluxPressure; + value uniform 0; + } + + defaultFaces + { + type empty; + } +} diff --git a/partitioned-pipe-two-phase/monolithic/clean.sh b/partitioned-pipe-two-phase/monolithic/clean.sh new file mode 100755 index 000000000..144bd0dc4 --- /dev/null +++ b/partitioned-pipe-two-phase/monolithic/clean.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . +rm -rf ./0/ diff --git a/partitioned-pipe-two-phase/monolithic/constant/g b/partitioned-pipe-two-phase/monolithic/constant/g new file mode 100644 index 000000000..858f3457c --- /dev/null +++ b/partitioned-pipe-two-phase/monolithic/constant/g @@ -0,0 +1,10 @@ +FoamFile +{ + version 2.0; + format ascii; + class uniformDimensionedVectorField; + object g; +} + +dimensions [0 1 -2 0 0 0 0]; +value (0 0 0); diff --git a/partitioned-pipe-two-phase/monolithic/constant/transportProperties b/partitioned-pipe-two-phase/monolithic/constant/transportProperties new file mode 100644 index 000000000..31085647a --- /dev/null +++ b/partitioned-pipe-two-phase/monolithic/constant/transportProperties @@ -0,0 +1,25 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object transportProperties; +} + +phases (water air); + +water +{ + transportModel Newtonian; + nu 1e-06; + rho 1000; +} + +air +{ + transportModel Newtonian; + nu 1.48e-05; + rho 1; +} + +sigma 0.07; diff --git a/partitioned-pipe-two-phase/monolithic/constant/turbulenceProperties b/partitioned-pipe-two-phase/monolithic/constant/turbulenceProperties new file mode 100644 index 000000000..b75c49530 --- /dev/null +++ b/partitioned-pipe-two-phase/monolithic/constant/turbulenceProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object turbulenceProperties; +} + +simulationType laminar; diff --git a/partitioned-pipe-two-phase/monolithic/run.sh b/partitioned-pipe-two-phase/monolithic/run.sh new file mode 100755 index 000000000..63adb50c4 --- /dev/null +++ b/partitioned-pipe-two-phase/monolithic/run.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh +cp -r 0.orig 0 +setFields + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/partitioned-pipe-two-phase/monolithic/system/blockMeshDict b/partitioned-pipe-two-phase/monolithic/system/blockMeshDict new file mode 100644 index 000000000..2028f529d --- /dev/null +++ b/partitioned-pipe-two-phase/monolithic/system/blockMeshDict @@ -0,0 +1,77 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant/polyMesh"; + object blockMeshDict; +} + +scale 1; + + +zmin 0; +zmax 20; + +xcells 1; +ycells 10; +zcells 20; + +vertices +( + (0.0 -2.0 $zmin) // 0 + (0.0 2.0 $zmin) // 1 + (0.0 -2.0 $zmax) // 2 + (0.0 2.0 $zmax)// 3 + (-1.0 -2.0 $zmin) // 4 + (-1.0 2.0 $zmin) // 5 + (-1.0 -2.0 $zmax) // 6 + (-1.0 2.0 $zmax) // 7 +); + +blocks +( +hex (4 0 1 5 6 2 3 7) pipe ($xcells $ycells $zcells) edgeGrading (1 1 1 1 1 1 1 1 1 1 1 1) +); + +edges +( +); + + +patches +( + + patch fixedWalls + ( + (0 4 6 2) + (1 3 7 5) + ) + + patch inlet + ( + (0 1 5 4) + ) + + patch outlet + ( + (3 2 6 7) + ) +); + +boundaries +( + emptyWalls + { + type empty; + faces + ( + (0 2 3 1) + (4 5 7 6) + ) + } +); + +mergePatchPairs +( +); diff --git a/partitioned-pipe-two-phase/monolithic/system/controlDict b/partitioned-pipe-two-phase/monolithic/system/controlDict new file mode 100644 index 000000000..2fe146fab --- /dev/null +++ b/partitioned-pipe-two-phase/monolithic/system/controlDict @@ -0,0 +1,45 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} + +application interFoam; + +startFrom startTime; + +startTime 0.0; + +stopAt endTime; + +endTime 20; + +deltaT 0.05; + +writeControl adjustable; + +writeInterval 0.1; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable yes; + +adjustTimeStep no; + +maxCo 1; + +maxAlphaCo 1; + +maxDeltaT 1; diff --git a/partitioned-pipe-two-phase/monolithic/system/decomposeParDict b/partitioned-pipe-two-phase/monolithic/system/decomposeParDict new file mode 100644 index 000000000..05708e995 --- /dev/null +++ b/partitioned-pipe-two-phase/monolithic/system/decomposeParDict @@ -0,0 +1,16 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object decomposeParDict; +} + +numberOfSubdomains 4; + +method simple; + +coeffs +{ + n (2 2 1); +} diff --git a/partitioned-pipe-two-phase/monolithic/system/fvSchemes b/partitioned-pipe-two-phase/monolithic/system/fvSchemes new file mode 100644 index 000000000..1325b0200 --- /dev/null +++ b/partitioned-pipe-two-phase/monolithic/system/fvSchemes @@ -0,0 +1,40 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ + div(rhoPhi,U) Gauss linearUpwind grad(U); + div(phi,alpha) Gauss vanLeer; + div(phirb,alpha) Gauss linear; + div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/partitioned-pipe-two-phase/monolithic/system/fvSolution b/partitioned-pipe-two-phase/monolithic/system/fvSolution new file mode 100644 index 000000000..9c2b40aba --- /dev/null +++ b/partitioned-pipe-two-phase/monolithic/system/fvSolution @@ -0,0 +1,75 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSolution; +} + +solvers +{ + "alpha.water.*" + { + nAlphaCorr 2; + nAlphaSubCycles 1; + cAlpha 1; + + MULESCorr yes; + nLimiterIter 5; + + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-8; + relTol 0; + } + + "pcorr.*" + { + solver PCG; + preconditioner DIC; + tolerance 1e-5; + relTol 0; + } + + p_rgh + { + solver PCG; + preconditioner DIC; + tolerance 1e-07; + relTol 0.05; + } + + p_rghFinal + { + $p_rgh; + relTol 0; + } + + U + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-06; + relTol 0; + } + UFinal + { + $U; + } +} + +PIMPLE +{ + momentumPredictor no; + nOuterCorrectors 1; + nCorrectors 3; + nNonOrthogonalCorrectors 0; +} + +relaxationFactors +{ + equations + { + ".*" 1; + } +} diff --git a/partitioned-pipe-two-phase/monolithic/system/sampling b/partitioned-pipe-two-phase/monolithic/system/sampling new file mode 100644 index 000000000..f364f46c0 --- /dev/null +++ b/partitioned-pipe-two-phase/monolithic/system/sampling @@ -0,0 +1,44 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object sampling; +} + +functions +{ + sampleSets + { + type sets; + libs (sampling); + + writeControl timeStep; + writeInterval 1; + + setFormat vtk; + interpolationScheme cellPointFace; + fields ( alpha.water ); + + sets + ( + gauge_1 + { + type face; + axis y; + start (0.02 0.20 0.005); + end (0.02 0.25 0.005); + nPoints 100; + } + + gauge_2 + { + type face; + axis y; + start (0.2 0.03 0.005); + end (0.2 0.55 0.005); + nPoints 100; + } + ); + } +} diff --git a/partitioned-pipe-two-phase/monolithic/system/setFieldsDict b/partitioned-pipe-two-phase/monolithic/system/setFieldsDict new file mode 100644 index 000000000..f724fdbfc --- /dev/null +++ b/partitioned-pipe-two-phase/monolithic/system/setFieldsDict @@ -0,0 +1,24 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object setFieldsDict; +} + +defaultFieldValues +( + volScalarFieldValue alpha.water 0 +); + +regions +( + boxToCell + { + box (-1 -2 0) (0 0 5); + fieldValues + ( + volScalarFieldValue alpha.water 1 + ); + } +); diff --git a/partitioned-pipe-two-phase/precice-config.xml b/partitioned-pipe-two-phase/precice-config.xml new file mode 100644 index 000000000..68bca6253 --- /dev/null +++ b/partitioned-pipe-two-phase/precice-config.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/partitioned-pipe/README.md b/partitioned-pipe/README.md index 8a48ff24f..f7cb79209 100644 --- a/partitioned-pipe/README.md +++ b/partitioned-pipe/README.md @@ -11,9 +11,15 @@ Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/ ## Setup -This scenario consists of two pipes connected in series. A fluid enters from the left (here $$ z=0 $$) boundary of the Fluid1 participant with a uniform velocity profile ($$ u_{in} = 0.1 m/s $$) and zero pressure gradient. In its starting, uncoupled state, it exits from the right side (outlet: zero velocity gradient, zero pressure). This is also the coupling interface with Fluid2, which has the same boundary conditions as Fluid1. +This scenario consists of two pipes connected in series, both simulated with OpenFOAM solvers. A fluid enters from the left (here $$ z=0 $$) boundary of the Fluid1 participant with a uniform velocity profile ($$ u_{in} = 0.1 m/s $$) and zero pressure gradient. In its starting, uncoupled state, it exits from the right side (outlet: zero velocity gradient, zero pressure). This is also the coupling interface with Fluid2, which has the same boundary conditions as Fluid1. -On the coupling interface, Fluid1 sends velocity and pressure gradient to Fluid2 and receives pressure. The additional pressure gradient exchange was found to help convergence [1], but this fluid-fluid coupling scenario is part of active research. +On the coupling interface, Fluid1 sends velocity to Fluid2 and receives pressure. Fluid2 uses the [fixedFluxExtrapolatedPressure](https://www.openfoam.com/documentation/guides/v2112/api/classFoam_1_1fixedFluxExtrapolatedPressureFvPatchScalarField.html) boundary condition, which allows a seamless flow continuity across the coupling interface [1]. Not all OpenFOAM solvers support this boundary condition. In such cases, it is recommended to use a fixed Gradient and additionally send the pressure gradient from Fluid1 to Fluid2 for better convergence[2]. + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-partitioned-pipe-precice-config.png) ## Available solvers @@ -28,14 +34,14 @@ Both for Fluid1 and Fluid2, the following participants are available: All listed solvers can be used in order to run the simulation. Open two separate terminals and start the desired fluid1 and fluid2 participants by calling the respective run script. For example: ```bash -cd fluid1-openfoam-pimplefoam +cd fluid1-openfoam-sonicliquidfoam ./run.sh ``` and ```bash -cd fluid2-openfoam-sonicliquidfoam +cd fluid2-openfoam-pimplefoam ./run.sh ``` @@ -44,15 +50,60 @@ cd fluid2-openfoam-sonicliquidfoam The OpenFOAM solvers generate a `.foam` file each. You can open this file in ParaView. An example of the visualized expected results looks as follows: -![result](images/tutorials-partitioned-pipe-results-pimpleFoam-sonicliquidfoam.png) +![result](images/tutorials-partitioned-pipe-results-sonicliquidfoam-pimplefoam.png) + +Observe that the velocity and pressure values are smoothly changing around the coupling interface. + +Note that here we are only coupling sonicLiquidFoam and pimpleFoam only to showcase that they are different solvers working on different domains. In practice, coupling such a compressible and an incompressible solver would not be trivial, due to, e.g., the different pressure units. + +## Coupling with pressure gradient + +The solver sonicLiquidFoam does not support the fixedFluxExtrapolatedPressure boundary condition. Therefore, when using sonicLiquidFoam for Fluid2, you might want to enable the exchange of the pressure gradient. For this, you have to uncomment these lines: + +```c++ + // In precice-config.xml + + + // In fluid1*/system/preciceDict + writeData + ( + Velocity + PressureGradient + ); +``` + +In `fluid2-openfoam-sonicLiquidFoam/0/p`, we have to set a `fixedGradient` boundary condition at the inlet. Coupling with the pressure gradient works with all OpenFOAM solvers. However, you will observe a less perfect coupling interface. -Observe that the velocity and pressure values are smoothly changing around the coupling interface. The simulation starts with oscillations, which disappear after a few time steps. +## Non-Orthogonality + +The standard mesh for the pipe is a structured mesh that is orthogonal along the z-axis. It is possible to run the case (pimpleFoam only) with a skewed mesh by using: + +```bash +./run.sh -skewed +``` + +The mesh looks like this: +![pipe_skewed](images/tutorials-partitioned-pipe-results-skewed.png) + +In the end of the simulation, the script runs a post-process utility to calculate the flow rate at the inlet of each participant. Comparing the output for both participants with the skewed mesh, we can observe a loss of mass across the coupling interface. + +To avoid this problem in cases with non-orthogonal meshes, it is possible to enable *flux corrected velocity in the preCICE FF module* by adding the following option to the ```preciceDict```: + +```C +// $fluid1Folder/system/preciceDict + +FF +{ + fluxCorrection true +} +``` -Note that here we are only coupling pimpleFoam and sonicLiquidFoam only to showcase that they are different solvers working on different domains. In practice, coupling such an incompressible and a compressible solver would not be trivial, due to, e.g., the different pressure units. +Now the mass flux should stay consistent across the coupling interface. ## References -[1] G. Chourdakis, B. Uekermann, G. V. Zwieten, and H. V. Brummelen: [Coupling OpenFOAM to different solvers, physics, models, and dimensions using preCICE](https://mediatum.ub.tum.de/1515271), 14th OpenFOAM Workshop, Duisburg, Germany, submitted (proceedings publication delayed/cancelled), July 2019. +[1] M. Mühlhäußer: [Partitioned flow simulations with preCICE and OpenFOAM](https://mediatum.ub.tum.de/node?id=1696254&change_language=en), Master's Thesis, 2022 +[2] G. Chourdakis, B. Uekermann, G. V. Zwieten, and H. V. Brummelen: [Coupling OpenFOAM to different solvers, physics, models, and dimensions using preCICE](https://mediatum.ub.tum.de/1515271), 14th OpenFOAM Workshop, Duisburg, Germany, submitted (proceedings publication delayed/cancelled), July 2019. {% disclaimer %} This offering is not approved or endorsed by OpenCFD Limited, producer and distributor of the OpenFOAM software via www.openfoam.com, and owner of the OPENFOAM® and OpenCFD® trade marks. diff --git a/partitioned-pipe/fluid1-openfoam-pimplefoam/run.sh b/partitioned-pipe/fluid1-openfoam-pimplefoam/run.sh index 7cadd6f3a..198f58108 100755 --- a/partitioned-pipe/fluid1-openfoam-pimplefoam/run.sh +++ b/partitioned-pipe/fluid1-openfoam-pimplefoam/run.sh @@ -1,8 +1,27 @@ -#!/bin/sh +#!/bin/bash set -e -u -blockMesh -touch fluid1-openfoam-pimplefoam.foam +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +use_skewed=false + +for arg in "$@" +do + shift + [ "$arg" = "-skewed" ] && use_skewed=true && continue + set -- "$@" "$arg" +done + +if [ "$use_skewed" = true ]; then + blockMesh -dict system/blockMeshDictSkewed +else + blockMesh +fi ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +postProcess -func "flowRatePatch(name=inlet)" -latestTime -noZero + +close_log diff --git a/partitioned-pipe/fluid1-openfoam-pimplefoam/system/blockMeshDictSkewed b/partitioned-pipe/fluid1-openfoam-pimplefoam/system/blockMeshDictSkewed new file mode 100644 index 000000000..aabedd7c9 --- /dev/null +++ b/partitioned-pipe/fluid1-openfoam-pimplefoam/system/blockMeshDictSkewed @@ -0,0 +1,110 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +convertToMeters 1; + + +zmin 0; +zmax 20; +zmid #calc "$zmin+0.5*($zmax-$zmin)"; +ztq #calc "$zmin+0.75*($zmax-$zmin)"; + +xcells 10; // per block (5 blocks) +ycells 10; // per block (5 blocks) +zcells 20; + +vertices +( + (-3.535534 -3.535534 $zmin) // 0 + ( 3.535534 -3.535534 $zmin) // 1 + ( 3.535534 3.535534 $zmin) // 2 + (-3.535534 3.535534 $zmin) // 3 + (-1.414214 -1.414214 $zmin) // 4 + ( 1.414214 -1.414214 $zmin) // 5 + ( 1.414214 1.414214 $zmin) // 6 + (-1.414214 1.414214 $zmin) // 7 + + (-3.535534 -3.535534 $zmax) // 8 + ( 3.535534 -3.535534 $zmax) // 9 + ( 3.535534 3.535534 $zmax) // 10 + (-3.535534 3.535534 $zmax) // 11 + (-1.414214 -1.414214 $zmax) // 12 + ( 1.414214 -1.414214 $zmax) // 13 + ( 1.414214 1.414214 $zmax) // 14 + (-1.414214 1.414214 $zmax) // 15 +); + +blocks +( +hex (0 1 5 4 8 9 13 12) pipe ($xcells $ycells $zcells) edgeGrading (1 1 1 1 1 1 1 1 1 1 1 1) +hex (1 2 6 5 9 10 14 13) pipe ($xcells $ycells $zcells) edgeGrading (1 1 1 1 1 1 1 1 1 1 1 1) +hex (2 3 7 6 10 11 15 14) pipe ($xcells $ycells $zcells) edgeGrading (1 1 1 1 1 1 1 1 1 1 1 1) +hex (3 0 4 7 11 8 12 15) pipe ($xcells $ycells $zcells) edgeGrading (1 1 1 1 1 1 1 1 1 1 1 1) +hex (4 5 6 7 12 13 14 15) pipe ($xcells $ycells $zcells) edgeGrading (1 1 1 1 1 1 1 1 1 1 1 1) +); + +edges +( +arc 0 1 ( 0 -5 $zmin) +arc 1 2 ( 5 0 $zmin) +arc 2 3 ( 0 5 $zmin) +arc 3 0 (-5 0 $zmin) +arc 4 5 ( 0 -1.5 $zmin) +arc 5 6 ( 1.5 0 $zmin) +arc 6 7 ( 0 1.5 $zmin) +arc 7 4 (-1.5 0 $zmin) + +arc 8 9 ( 0 -5 $zmax) +arc 9 10 ( 5 0 $zmax) +arc 10 11 ( 0 5 $zmax) +arc 11 8 (-5 0 $zmax) +arc 12 13 ( 0 -1.5 $zmax) +arc 13 14 (1.5 0 $zmax) +arc 14 15 ( 0 1.5 $zmax) +arc 15 12 (-1.5 0 $zmax) + +spline 4 12 ( (-1.5 -1.5 $zmid) (-2.5 -2.5 $ztq)) +spline 5 13 ( (1.5 -1.5 $zmid) (2.5 -2.5 $ztq)) +spline 6 14 ( (1.5 1.5 $zmid) (2.5 2.5 $ztq)) +spline 7 15 ( (-1.5 1.5 $zmid) (-2.5 2.5 $ztq)) +); + + +patches +( + + patch fixedWalls + ( + (0 1 9 8) + (1 2 10 9) + (2 3 11 10) + (3 0 8 11) + ) + + patch inlet + ( + (0 1 5 4) + (1 2 6 5) + (2 3 7 6) + (3 0 4 7) + (4 5 6 7) + ) + + patch outlet + ( + (8 9 13 12) + (9 10 14 13) + (10 11 15 14) + (12 13 14 15) + (11 8 12 15) + ) +); + +mergePatchPairs +( +); diff --git a/partitioned-pipe/fluid1-openfoam-pimplefoam/system/controlDict b/partitioned-pipe/fluid1-openfoam-pimplefoam/system/controlDict index 83323d140..2e63d8bb2 100644 --- a/partitioned-pipe/fluid1-openfoam-pimplefoam/system/controlDict +++ b/partitioned-pipe/fluid1-openfoam-pimplefoam/system/controlDict @@ -14,7 +14,7 @@ startTime 0; stopAt endTime; -endTime 10.0; +endTime 1.0; deltaT 0.01; diff --git a/partitioned-pipe/fluid1-openfoam-pimplefoam/system/fvSolution b/partitioned-pipe/fluid1-openfoam-pimplefoam/system/fvSolution index 7e4fe2724..22afb088d 100644 --- a/partitioned-pipe/fluid1-openfoam-pimplefoam/system/fvSolution +++ b/partitioned-pipe/fluid1-openfoam-pimplefoam/system/fvSolution @@ -9,14 +9,12 @@ FoamFile solvers { - p { - - solver PCG; - preconditioner DIC; - tolerance 1e-8; - relTol 1.0e-3; + solver PCG; + preconditioner DIC; + tolerance 1e-8; + relTol 1.0e-3; } pFinal @@ -25,23 +23,7 @@ solvers relTol 0; } - pcorr - { - $p; - } - - pcorrFinal - { - $pcorr; - relTol 0; - } - - Phi - { - $p; - } - - "(U|cellDisplacement)" + U { solver smoothSolver; smoother symGaussSeidel; @@ -50,7 +32,7 @@ solvers minIter 2; } - "(U|cellDisplacement)Final" + UFinal { $U; relTol 0; @@ -59,16 +41,8 @@ solvers PIMPLE { - nCorrectors 4; + nCorrectors 3; nNonOrthogonalCorrectors 1; - consistent true; - correctPhi true; momentumPredictor true; - nOuterCorrectors 1; -} - - -potentialFlow -{ - nNonOrthogonalCorrectors 10; + nOuterCorrectors 2; } diff --git a/partitioned-pipe/fluid1-openfoam-pimplefoam/system/preciceDict b/partitioned-pipe/fluid1-openfoam-pimplefoam/system/preciceDict index 2e0095445..01a44932f 100644 --- a/partitioned-pipe/fluid1-openfoam-pimplefoam/system/preciceDict +++ b/partitioned-pipe/fluid1-openfoam-pimplefoam/system/preciceDict @@ -27,7 +27,12 @@ interfaces writeData ( Velocity - PressureGradient + // PressureGradient ); }; }; + +FF +{ + // fluxCorrection true; +} \ No newline at end of file diff --git a/partitioned-pipe/fluid1-openfoam-rhoPimpleFoam/run.sh b/partitioned-pipe/fluid1-openfoam-rhoPimpleFoam/run.sh index 76e94cbc8..da82a9ba2 100755 --- a/partitioned-pipe/fluid1-openfoam-rhoPimpleFoam/run.sh +++ b/partitioned-pipe/fluid1-openfoam-rhoPimpleFoam/run.sh @@ -1,8 +1,12 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + blockMesh -touch fluid1-openfoam-sonicliquidfoam.foam ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/partitioned-pipe/fluid1-openfoam-rhoPimpleFoam/system/controlDict b/partitioned-pipe/fluid1-openfoam-rhoPimpleFoam/system/controlDict index 27558b283..7be61e221 100644 --- a/partitioned-pipe/fluid1-openfoam-rhoPimpleFoam/system/controlDict +++ b/partitioned-pipe/fluid1-openfoam-rhoPimpleFoam/system/controlDict @@ -14,7 +14,7 @@ startTime 0; stopAt endTime; -endTime 10.0; +endTime 1.0; deltaT 0.01; diff --git a/partitioned-pipe/fluid1-openfoam-rhoPimpleFoam/system/fvSolution b/partitioned-pipe/fluid1-openfoam-rhoPimpleFoam/system/fvSolution index f846b32aa..ccef5a367 100644 --- a/partitioned-pipe/fluid1-openfoam-rhoPimpleFoam/system/fvSolution +++ b/partitioned-pipe/fluid1-openfoam-rhoPimpleFoam/system/fvSolution @@ -36,7 +36,8 @@ solvers PIMPLE { - nOuterCorrectors 4; - nCorrectors 2; - nNonOrthogonalCorrectors 0; + nCorrectors 3; + nNonOrthogonalCorrectors 1; + momentumPredictor true; + nOuterCorrectors 2; } diff --git a/partitioned-pipe/fluid2-openfoam-pimplefoam/0/p b/partitioned-pipe/fluid2-openfoam-pimplefoam/0/p index ada3a6d88..9710105bd 100644 --- a/partitioned-pipe/fluid2-openfoam-pimplefoam/0/p +++ b/partitioned-pipe/fluid2-openfoam-pimplefoam/0/p @@ -14,8 +14,10 @@ boundaryField { inlet { - type fixedGradient; - gradient uniform 0; + // Pressure Gradient is calculated by OpenFOAM to match inlet flux + type fixedFluxExtrapolatedPressure; + // type fixedGradient; + // gradient uniform 0; } outlet diff --git a/partitioned-pipe/fluid2-openfoam-pimplefoam/run.sh b/partitioned-pipe/fluid2-openfoam-pimplefoam/run.sh index d00617f49..198f58108 100755 --- a/partitioned-pipe/fluid2-openfoam-pimplefoam/run.sh +++ b/partitioned-pipe/fluid2-openfoam-pimplefoam/run.sh @@ -1,8 +1,27 @@ -#!/bin/sh +#!/bin/bash set -e -u -blockMesh -touch fluid2-openfoam-pimplefoam.foam +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +use_skewed=false + +for arg in "$@" +do + shift + [ "$arg" = "-skewed" ] && use_skewed=true && continue + set -- "$@" "$arg" +done + +if [ "$use_skewed" = true ]; then + blockMesh -dict system/blockMeshDictSkewed +else + blockMesh +fi ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +postProcess -func "flowRatePatch(name=inlet)" -latestTime -noZero + +close_log diff --git a/partitioned-pipe/fluid2-openfoam-pimplefoam/system/blockMeshDictSkewed b/partitioned-pipe/fluid2-openfoam-pimplefoam/system/blockMeshDictSkewed new file mode 100644 index 000000000..f958b9c8d --- /dev/null +++ b/partitioned-pipe/fluid2-openfoam-pimplefoam/system/blockMeshDictSkewed @@ -0,0 +1,111 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant/polyMesh"; + object blockMeshDict; +} + +convertToMeters 1; + + +zmin 20; +zmax 40; +zmid #calc "$zmin+0.5*($zmax-$zmin)"; +zqu #calc "$zmin+0.25*($zmax-$zmin)"; + +xcells 10; // per block (5 blocks) +ycells 10; // per block (5 blocks) +zcells 20; + +vertices +( + (-3.535534 -3.535534 $zmin) // 0 + ( 3.535534 -3.535534 $zmin) // 1 + ( 3.535534 3.535534 $zmin) // 2 + (-3.535534 3.535534 $zmin) // 3 + (-1.414214 -1.414214 $zmin) // 4 + ( 1.414214 -1.414214 $zmin) // 5 + ( 1.414214 1.414214 $zmin) // 6 + (-1.414214 1.414214 $zmin) // 7 + + (-3.535534 -3.535534 $zmax) // 8 + ( 3.535534 -3.535534 $zmax) // 9 + ( 3.535534 3.535534 $zmax) // 10 + (-3.535534 3.535534 $zmax) // 11 + (-1.414214 -1.414214 $zmax) // 12 + ( 1.414214 -1.414214 $zmax) // 13 + ( 1.414214 1.414214 $zmax) // 14 + (-1.414214 1.414214 $zmax) // 15 +); + +blocks +( +hex (0 1 5 4 8 9 13 12) pipe ($xcells $ycells $zcells) edgeGrading (1 1 1 1 1 1 1 1 1 1 1 1) +hex (1 2 6 5 9 10 14 13) pipe ($xcells $ycells $zcells) edgeGrading (1 1 1 1 1 1 1 1 1 1 1 1) +hex (2 3 7 6 10 11 15 14) pipe ($xcells $ycells $zcells) edgeGrading (1 1 1 1 1 1 1 1 1 1 1 1) +hex (3 0 4 7 11 8 12 15) pipe ($xcells $ycells $zcells) edgeGrading (1 1 1 1 1 1 1 1 1 1 1 1) +hex (4 5 6 7 12 13 14 15) pipe ($xcells $ycells $zcells) edgeGrading (1 1 1 1 1 1 1 1 1 1 1 1) +); + +edges +( +arc 0 1 ( 0 -5 $zmin) +arc 1 2 ( 5 0 $zmin) +arc 2 3 ( 0 5 $zmin) +arc 3 0 (-5 0 $zmin) +arc 4 5 ( 0 -1.5 $zmin) +arc 5 6 ( 1.5 0 $zmin) +arc 6 7 ( 0 1.5 $zmin) +arc 7 4 (-1.5 0 $zmin) + +arc 8 9 ( 0 -5 $zmax) +arc 9 10 ( 5 0 $zmax) +arc 10 11 ( 0 5 $zmax) +arc 11 8 (-5 0 $zmax) +arc 12 13 ( 0 -1.5 $zmax) +arc 13 14 (1.5 0 $zmax) +arc 14 15 ( 0 1.5 $zmax) +arc 15 12 (-1.5 0 $zmax) + +spline 4 12 ( (-1 -1 $zqu) (-1.5 -1.5 $zmid)) +spline 5 13 ( (1 -1 $zqu) (1.5 -1.5 $zmid)) +spline 6 14 ( (1 1 $zqu) (1.5 1.5 $zmid)) +spline 7 15 ( (-1 1 $zqu) (-1.5 1.5 $zmid)) +); + + +patches +( + + patch fixedWalls + ( + (0 1 9 8) + (1 2 10 9) + (2 3 11 10) + (3 0 8 11) + ) + + patch inlet + ( + (0 1 5 4) + (1 2 6 5) + (2 3 7 6) + (3 0 4 7) + (4 5 6 7) + ) + + patch outlet + ( + (8 9 13 12) + (9 10 14 13) + (10 11 15 14) + (12 13 14 15) + (11 8 12 15) + ) +); + +mergePatchPairs +( +); diff --git a/partitioned-pipe/fluid2-openfoam-pimplefoam/system/controlDict b/partitioned-pipe/fluid2-openfoam-pimplefoam/system/controlDict index 839905b56..e9adefeb6 100644 --- a/partitioned-pipe/fluid2-openfoam-pimplefoam/system/controlDict +++ b/partitioned-pipe/fluid2-openfoam-pimplefoam/system/controlDict @@ -15,7 +15,7 @@ startTime 0; stopAt endTime; -endTime 10.0; +endTime 1.0; deltaT 0.01; diff --git a/partitioned-pipe/fluid2-openfoam-pimplefoam/system/fvSolution b/partitioned-pipe/fluid2-openfoam-pimplefoam/system/fvSolution index 7e4fe2724..23279d2b8 100644 --- a/partitioned-pipe/fluid2-openfoam-pimplefoam/system/fvSolution +++ b/partitioned-pipe/fluid2-openfoam-pimplefoam/system/fvSolution @@ -9,14 +9,12 @@ FoamFile solvers { - p - { - - solver PCG; - preconditioner DIC; - tolerance 1e-8; - relTol 1.0e-3; + { + solver PCG; + preconditioner DIC; + tolerance 1e-8; + relTol 1.0e-3; } pFinal @@ -25,23 +23,7 @@ solvers relTol 0; } - pcorr - { - $p; - } - - pcorrFinal - { - $pcorr; - relTol 0; - } - - Phi - { - $p; - } - - "(U|cellDisplacement)" + U { solver smoothSolver; smoother symGaussSeidel; @@ -50,7 +32,7 @@ solvers minIter 2; } - "(U|cellDisplacement)Final" + UFinal { $U; relTol 0; @@ -59,16 +41,8 @@ solvers PIMPLE { - nCorrectors 4; + nCorrectors 3; nNonOrthogonalCorrectors 1; - consistent true; - correctPhi true; momentumPredictor true; - nOuterCorrectors 1; -} - - -potentialFlow -{ - nNonOrthogonalCorrectors 10; + nOuterCorrectors 2; } diff --git a/partitioned-pipe/fluid2-openfoam-pimplefoam/system/preciceDict b/partitioned-pipe/fluid2-openfoam-pimplefoam/system/preciceDict index f17b23d93..408426559 100644 --- a/partitioned-pipe/fluid2-openfoam-pimplefoam/system/preciceDict +++ b/partitioned-pipe/fluid2-openfoam-pimplefoam/system/preciceDict @@ -23,7 +23,7 @@ interfaces readData ( Velocity - PressureGradient + // PressureGradient ); writeData diff --git a/partitioned-pipe/fluid2-openfoam-rhoPimpleFoam/run.sh b/partitioned-pipe/fluid2-openfoam-rhoPimpleFoam/run.sh index 5a24175c5..da82a9ba2 100755 --- a/partitioned-pipe/fluid2-openfoam-rhoPimpleFoam/run.sh +++ b/partitioned-pipe/fluid2-openfoam-rhoPimpleFoam/run.sh @@ -1,8 +1,12 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + blockMesh -touch fluid2-openfoam-sonicliquidfoam.foam ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/partitioned-pipe/fluid2-openfoam-rhoPimpleFoam/system/controlDict b/partitioned-pipe/fluid2-openfoam-rhoPimpleFoam/system/controlDict index 27558b283..7be61e221 100644 --- a/partitioned-pipe/fluid2-openfoam-rhoPimpleFoam/system/controlDict +++ b/partitioned-pipe/fluid2-openfoam-rhoPimpleFoam/system/controlDict @@ -14,7 +14,7 @@ startTime 0; stopAt endTime; -endTime 10.0; +endTime 1.0; deltaT 0.01; diff --git a/partitioned-pipe/fluid2-openfoam-rhoPimpleFoam/system/fvSolution b/partitioned-pipe/fluid2-openfoam-rhoPimpleFoam/system/fvSolution index f846b32aa..ccef5a367 100644 --- a/partitioned-pipe/fluid2-openfoam-rhoPimpleFoam/system/fvSolution +++ b/partitioned-pipe/fluid2-openfoam-rhoPimpleFoam/system/fvSolution @@ -36,7 +36,8 @@ solvers PIMPLE { - nOuterCorrectors 4; - nCorrectors 2; - nNonOrthogonalCorrectors 0; + nCorrectors 3; + nNonOrthogonalCorrectors 1; + momentumPredictor true; + nOuterCorrectors 2; } diff --git a/partitioned-pipe/images/tutorials-partitioned-pipe-precice-config.png b/partitioned-pipe/images/tutorials-partitioned-pipe-precice-config.png new file mode 100644 index 000000000..e651795b0 Binary files /dev/null and b/partitioned-pipe/images/tutorials-partitioned-pipe-precice-config.png differ diff --git a/partitioned-pipe/images/tutorials-partitioned-pipe-results-pimpleFoam-sonicliquidfoam.png b/partitioned-pipe/images/tutorials-partitioned-pipe-results-pimpleFoam-sonicliquidfoam.png deleted file mode 100644 index 919d5193f..000000000 Binary files a/partitioned-pipe/images/tutorials-partitioned-pipe-results-pimpleFoam-sonicliquidfoam.png and /dev/null differ diff --git a/partitioned-pipe/images/tutorials-partitioned-pipe-results-skewed.png b/partitioned-pipe/images/tutorials-partitioned-pipe-results-skewed.png new file mode 100644 index 000000000..3abf86d1f Binary files /dev/null and b/partitioned-pipe/images/tutorials-partitioned-pipe-results-skewed.png differ diff --git a/partitioned-pipe/images/tutorials-partitioned-pipe-results-sonicliquidfoam-pimplefoam.png b/partitioned-pipe/images/tutorials-partitioned-pipe-results-sonicliquidfoam-pimplefoam.png new file mode 100644 index 000000000..1cc9faf39 Binary files /dev/null and b/partitioned-pipe/images/tutorials-partitioned-pipe-results-sonicliquidfoam-pimplefoam.png differ diff --git a/partitioned-pipe/precice-config.xml b/partitioned-pipe/precice-config.xml index 1a8cf842f..bf50c5631 100644 --- a/partitioned-pipe/precice-config.xml +++ b/partitioned-pipe/precice-config.xml @@ -7,73 +7,66 @@ enabled="true" /> - - - - - + + - - - - - - + + + + + + - - - - - - + + + + + - - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/perpendicular-flap/README.md b/perpendicular-flap/README.md index 41da352e3..0b1e8f0f6 100644 --- a/perpendicular-flap/README.md +++ b/perpendicular-flap/README.md @@ -17,26 +17,40 @@ We model a two-dimensional fluid flowing through a channel. A solid, elastic fla The simulated flow domain is 6 units long (x) and 4 units tall (y). The flap is located at the center of the bottom (x=0) and is 1 unit long (y) and 0.1 units thick (x). We set the fluid density $$ \rho_F= 1.0kg/m^{3} $$, the kinematic viscosity $$ \nu_f= 1.0m^{2}/s $$, the solid density $$ \rho_s= 3.0·10^{3}kg/m^{3} $$, the Young’s modulus to $$ E= 4.0·10^{6} kg/ms^{2} $$ and the Poisson ratio $$ \nu_s = 0.3 $$. On the left boundary a constant inflow profile in x-direction of 10m/s is prescribed. The right boundary is an outflow and the top and bottom of the channel as well as the surface of the flap are no-slip walls. +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-perpendicular-flap-precice-config.png) + ## Available solvers 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://www.precice.org/adapter-openfoam-overview.html). -* Nutils. For more information, have a look at the [Nutils adapter documentation](https://www.precice.org/adapter-nutils.html). This Nutils solver requires at least Nutils v6.0. - * SU2. As opposed to the other two fluid codes, SU2 is in particular specialized for compressible flow. Therefore the default simulation parameters haven 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://www.precice.org/adapter-su2-overview.html). +* Nutils. For more information, have a look at the [Nutils adapter documentation](https://www.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). + +* 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. + Solid participant: -* FEniCS. The structural model is currently limited to linear elasticity. For more information, have a look at the [FeniCS adapter documentation](https://www.precice.org/adapter-fenics.html). +* FEniCS. The structural model is currently limited to linear elasticity. For more information, have a look at the [FEniCS adapter documentation](https://www.precice.org/adapter-fenics.html). -* CalculiX. In order to allow a reasonable comparison to all solid codes, the geometrically non-linear solver has been disabled and only a linear model is used by default. For more information, have a look at the [CalculiX adapter documentation](https://www.precice.org/adapter-calculix-overview.html) +* CalculiX. In order to allow a reasonable comparison to all solid codes, the geometrically non-linear solver has been disabled and only a linear model is used by default. For more information, have a look at the [CalculiX adapter documentation](https://www.precice.org/adapter-calculix-overview.html). Two cases are provided: one as a regular simulation, and one with modal dynamic simulations where a few eigenmodes are computed, and then used to simulate a reduced model. In that case, the `run.sh` script runs the frequency analysis, renames the output file to match with the actual input file, and then runs it. For more details, see the [adapter configuration documentation](https://precice.org/adapter-calculix-config.html). To run the modal dynamic version, add the `-modal` argument to the `run.sh` script. * deal.II. This tutorial works only with `Model = linear` since the deal.II codes were developed with read data `Stress` instead of `Force` as applied here (example given in Turek-Hron-FSI) in the first place. The `./run.sh` script takes the compiled executable `elasticity` as input argument (`run.sh -e=/path/to/elasticity`) and is required in case the executable is not discoverable at runtime (e.g. has been added to the system `PATH`). For more information, have a look at the [deal.II adapter documentation](https://www.precice.org/adapter-dealii-overview.html). * 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://www.precice.org/adapter-nutils.html). This Nutils solver requires at least Nutils v8.0. + +* 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://solids4foam.github.io/tutorials/more-tutorials/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. + +* OpenFOAM (solidDisplacementFoam). For more information, have a look at the [OpenFOAM plateHole tutorial](https://www.openfoam.com/documentation/tutorial-guide/5-stress-analysis/5.1-stress-analysis-of-a-plate-with-a-hole). The solidDisplacementFoam solver only supports linear geometry and this case is only provided for quick testing purposes, leading to outlier results. For general solid mechanics procedures in OpenFOAM, see solids4foam. + ## Running the Simulation All listed solvers can be used in order to run the simulation. OpenFOAM can be executed in parallel using `run.sh -parallel`. The default setting uses 4 MPI ranks. Open two separate terminals and start the desired fluid and solid participant by calling the respective run script `run.sh` located in the participant directory. For example: @@ -65,17 +79,41 @@ As we defined a watchpoint on the 'Solid' participant at the flap tip (see `prec ![Flap watchpoint](images/tutorials-perpendicular-flap-displacement-watchpoint.png) -There is moreover a script `plot-all-displacements.sh` to plot and compare all possible variants. This script expects all watchpoint logs to be available in a subfolder `watchpoints` in the format `openfoam-dealii.log` or similar. If you want to use this script, you need to copy the files over accordingly. +There is moreover a script `plot-all-displacements.sh` to plot and compare all possible variants. This script expects all watchpoint logs to be available in a subfolder `watchpoints` in the format `openfoam-dealii-version.log` or similar. If you want to use this script, you need to edit it to exclude combinations you want to exclude and copy the files over accordingly. You should get results similar to this one: -![All flap watchpoints](images/tutorials-perpendicular-flap-displacement-all-watchpoints.png) +![Selected flap watchpoints](images/tutorials-perpendicular-flap-displacement-selected-watchpoints.png) Reasons for the differences: * The CalculiX adapter only supports linear finite elements (deal.II uses 4th order, FEniCS 2nd order). * SU2 models a compressible fluid, OpenFOAM and Nutils an incompressible one. +### Looking closer + +Excluding the `solid-openfoam` (outlier, provided mainly for technical testing), let's look at an overview of different combinations. + +Comparison of the different flow solvers (incompressible `fluid-openfoam` and `fluid-nutils`, compressible `fluid-su2`, dummy `fluid-fake`): + +![Flap watchpoints using solid-calculix](images/tutorials-perpendicular-flap-displacement-flow-comparison-watchpoints.png) + +Combinations using the incompressible `fluid-openfoam` case: + +![Flap watchpoints using fluid-openfoam](images/tutorials-perpendicular-flap-displacement-openfoam-watchpoints.png) + +Combinations (excerpt) using the incompressible `fluid-nutils` case: + +![Flap watchpoints using fluid-nutils](images/tutorials-perpendicular-flap-displacement-nutils-watchpoints.png) + +Combinations (excerpt) using the compressible `fluid-su2` case: + +![Flap watchpoints using fluid-su2](images/tutorials-perpendicular-flap-displacement-su2-watchpoints.png) + +Combinations (excerpt) using the dummy `fluid-fake` case: + +![Flap watchpoints using fluid-fake](images/tutorials-perpendicular-flap-displacement-fake-watchpoints.png) + {% disclaimer %} This offering is not approved or endorsed by OpenCFD Limited, producer and distributor of the OpenFOAM software via www.openfoam.com, and owner of the OPENFOAM® and OpenCFD® trade marks. {% enddisclaimer %} diff --git a/perpendicular-flap/fluid-fake/fake.py b/perpendicular-flap/fluid-fake/fake.py new file mode 100644 index 000000000..f6006f8b1 --- /dev/null +++ b/perpendicular-flap/fluid-fake/fake.py @@ -0,0 +1,53 @@ +from __future__ import division + +import argparse +import numpy as np +import precice + +configuration_file_name = "../precice-config.xml" +participant_name = "Fluid" +mesh_name = "Fluid-Mesh" +write_data_name = 'Force' + +solver_process_index = 0 +solver_process_size = 1 + +interface = precice.Participant(participant_name, configuration_file_name, solver_process_index, solver_process_size) +dimensions = interface.get_mesh_dimensions(mesh_name) +assert (dimensions == 2) + +# infomation about beam geometry and position +W = 0.1 # width of the beam +H = 1.0 # height of the beam +x_left = 0.0 - 0.5 * W # x-coordinate of the left side of the beam +y_bottom = 0.0 # bottom of the beam +y_top = y_bottom + H # top of the beam +F_max = 1.0 +# define vertices where we want to prove a load +n = 100 # Number of vertices +vertices = np.zeros((n, dimensions)) +vertices[:, 0] = x_left # all vertices are at left side of beam +vertices[:, 1] = np.linspace(y_bottom, y_top, n) # have n equally disrtibuted vertices +vertex_ids = interface.set_mesh_vertices(mesh_name, vertices) + +interface.initialize() +solver_dt = np.inf # we just want to use dt = precice_dt + +while interface.is_coupling_ongoing(): + if interface.requires_writing_checkpoint(): + pass + + precice_dt = interface.get_max_time_step_size() + dt = min([solver_dt, precice_dt]) + + write_data = np.zeros((n, dimensions)) + write_data[:, 0] = F_max * vertices[:, 1] / H # linearly increasing load + write_data[:, 1] = 0 + + interface.write_data(mesh_name, write_data_name, vertex_ids, write_data) + interface.advance(dt) + + if interface.requires_reading_checkpoint(): + pass + +interface.finalize() diff --git a/perpendicular-flap/fluid-fake/requirements.txt b/perpendicular-flap/fluid-fake/requirements.txt new file mode 100644 index 000000000..3f8163356 --- /dev/null +++ b/perpendicular-flap/fluid-fake/requirements.txt @@ -0,0 +1,2 @@ +numpy +pyprecice==3 diff --git a/perpendicular-flap/fluid-fake/run.sh b/perpendicular-flap/fluid-fake/run.sh new file mode 100755 index 000000000..8d735f1f6 --- /dev/null +++ b/perpendicular-flap/fluid-fake/run.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -e -u + +python3 -m venv .venv +. .venv/bin/activate +pip install -r requirements.txt +python3 fake.py diff --git a/perpendicular-flap/fluid-nutils/fluid.py b/perpendicular-flap/fluid-nutils/fluid.py index e0e6b15fc..0dd44ba6e 100644 --- a/perpendicular-flap/fluid-nutils/fluid.py +++ b/perpendicular-flap/fluid-nutils/fluid.py @@ -105,24 +105,22 @@ def main(inflow: 'inflow velocity' = 10, participantName = "Fluid" solverProcessIndex = 0 solverProcessSize = 1 - interface = precice.Interface(participantName, configFileName, solverProcessIndex, solverProcessSize) + participant = precice.Participant(participantName, configFileName, solverProcessIndex, solverProcessSize) # define coupling meshes meshName = "Fluid-Mesh" - meshID = interface.get_mesh_id(meshName) couplinginterface = domain.boundary['flap'] couplingsample = couplinginterface.sample('gauss', degree=2) # mesh located at Gauss points - dataIndices = interface.set_mesh_vertices(meshID, couplingsample.eval(ns.x0)) + dataIndices = participant.set_mesh_vertices(meshName, couplingsample.eval(ns.x0)) # coupling data - writeData = "Force" - readData = "Displacement" - writedataID = interface.get_data_id(writeData, meshID) - readdataID = interface.get_data_id(readData, meshID) + writeDataName = "Force" + readDataName = "Displacement" # initialize preCICE - precice_dt = interface.initialize() + participant.initialize() + precice_dt = participant.get_max_time_step_size() dt = min(precice_dt, timestepsize) # boundary conditions for fluid equations @@ -155,25 +153,27 @@ def main(inflow: 'inflow velocity' = 10, meshsqr = domain.integral('d_i,x0_j d_i,x0_j d:x0' @ ns, degree=2) # better initial guess: start from Stokes solution, comment out for comparison with other solvers - #res_stokes = domain.integral('(ubasis_ni,j ((u_i,j + u_j,i) rho nu - p δ_ij) + pbasis_n u_k,k) d:x' @ ns, degree=4) - #lhs0 = solver.solve_linear('lhs', res_stokes, constrain=cons, arguments=dict(meshdofs=meshdofs, oldmeshdofs=oldmeshdofs, oldoldmeshdofs=oldoldmeshdofs, oldoldoldmeshdofs=oldoldoldmeshdofs, dt=dt)) + # res_stokes = domain.integral('(ubasis_ni,j ((u_i,j + u_j,i) rho nu - p δ_ij) + pbasis_n u_k,k) d:x' @ ns, degree=4) + # lhs0 = solver.solve_linear('lhs', res_stokes, constrain=cons, arguments=dict(meshdofs=meshdofs, oldmeshdofs=oldmeshdofs, oldoldmeshdofs=oldoldmeshdofs, oldoldoldmeshdofs=oldoldoldmeshdofs, dt=dt)) lhs00 = lhs0 timestep = 0 t = 0 - while interface.is_coupling_ongoing(): + while participant.is_coupling_ongoing(): - # read displacements from interface - if interface.is_read_data_available(): - readdata = interface.read_block_vector_data(readdataID, dataIndices) - coupledata = couplingsample.asfunction(readdata) - sqr = couplingsample.integral(((ns.d - coupledata)**2).sum(0)) - meshcons = solver.optimize('meshdofs', sqr, droptol=1e-15, constrain=meshcons0) - meshdofs = solver.optimize('meshdofs', meshsqr, constrain=meshcons) + precice_dt = participant.get_max_time_step_size() + dt = min(precice_dt, timestepsize) + + # read displacements from participant + readdata = participant.read_data(meshName, readDataName, dataIndices, dt) + coupledata = couplingsample.asfunction(readdata) + sqr = couplingsample.integral(((ns.d - coupledata)**2).sum(0)) + meshcons = solver.optimize('meshdofs', sqr, droptol=1e-15, constrain=meshcons0) + meshdofs = solver.optimize('meshdofs', meshsqr, constrain=meshcons) # save checkpoint - if interface.is_action_required(precice.action_write_iteration_checkpoint()): + if participant.requires_writing_checkpoint(): lhs_checkpoint = lhs0 lhs00_checkpoint = lhs00 t_checkpoint = t @@ -181,7 +181,6 @@ def main(inflow: 'inflow velocity' = 10, oldmeshdofs_checkpoint = oldmeshdofs oldoldmeshdofs_checkpoint = oldoldmeshdofs oldoldoldmeshdofs_checkpoint = oldoldoldmeshdofs - interface.mark_action_fulfilled(precice.action_write_iteration_checkpoint()) # solve fluid equations lhs1 = solver.newton('lhs', res, lhs0=lhs0, constrain=cons, @@ -189,20 +188,18 @@ def main(inflow: 'inflow velocity' = 10, oldoldmeshdofs=oldoldmeshdofs, oldoldoldmeshdofs=oldoldoldmeshdofs) ).solve(tol=1e-6) - # write forces to interface - if interface.is_write_data_required(dt): - F = solver.solve_linear('F', resF, constrain=consF, - arguments=dict(lhs00=lhs00, lhs0=lhs0, lhs=lhs1, dt=dt, meshdofs=meshdofs, - oldmeshdofs=oldmeshdofs, oldoldmeshdofs=oldoldmeshdofs, - oldoldoldmeshdofs=oldoldoldmeshdofs)) - # writedata = couplingsample.eval(ns.F, F=F) # for stresses - writedata = couplingsample.eval('F_i d:x' @ ns, F=F, meshdofs=meshdofs) * \ - numpy.concatenate([p.weights for p in couplingsample.points])[:, numpy.newaxis] - interface.write_block_vector_data(writedataID, dataIndices, writedata) + # write forces to participant + F = solver.solve_linear('F', resF, constrain=consF, + arguments=dict(lhs00=lhs00, lhs0=lhs0, lhs=lhs1, dt=dt, meshdofs=meshdofs, + oldmeshdofs=oldmeshdofs, oldoldmeshdofs=oldoldmeshdofs, + oldoldoldmeshdofs=oldoldoldmeshdofs)) + # writedata = couplingsample.eval(ns.F, F=F) # for stresses + writedata = couplingsample.eval('F_i d:x' @ ns, F=F, meshdofs=meshdofs) * \ + numpy.concatenate([p.weights for p in couplingsample.points])[:, numpy.newaxis] + participant.write_data(meshName, writeDataName, dataIndices, writedata) # do the coupling - precice_dt = interface.advance(dt) - dt = min(precice_dt, timestepsize) + participant.advance(dt) # advance variables timestep += 1 @@ -214,7 +211,7 @@ def main(inflow: 'inflow velocity' = 10, oldmeshdofs = meshdofs # read checkpoint if required - if interface.is_action_required(precice.action_read_iteration_checkpoint()): + if participant.requires_reading_checkpoint(): lhs0 = lhs_checkpoint lhs00 = lhs00_checkpoint t = t_checkpoint @@ -222,15 +219,14 @@ def main(inflow: 'inflow velocity' = 10, oldmeshdofs = oldmeshdofs_checkpoint oldoldmeshdofs = oldoldmeshdofs_checkpoint oldoldoldmeshdofs = oldoldoldmeshdofs_checkpoint - interface.mark_action_fulfilled(precice.action_read_iteration_checkpoint()) - if interface.is_time_window_complete(): + if participant.is_time_window_complete(): x, u, p = bezier.eval(['x_i', 'u_i', 'p'] @ ns, lhs=lhs1, meshdofs=meshdofs, oldmeshdofs=oldmeshdofs, oldoldmeshdofs=oldoldmeshdofs, oldoldoldmeshdofs=oldoldoldmeshdofs, dt=dt) with treelog.add(treelog.DataLog()): export.vtk('Fluid_' + str(timestep), bezier.tri, x, u=u, p=p) - interface.finalize() + participant.finalize() if __name__ == '__main__': diff --git a/perpendicular-flap/fluid-nutils/requirements.txt b/perpendicular-flap/fluid-nutils/requirements.txt new file mode 100644 index 000000000..9e344b1e3 --- /dev/null +++ b/perpendicular-flap/fluid-nutils/requirements.txt @@ -0,0 +1,2 @@ +nutils==6 +pyprecice==3 diff --git a/perpendicular-flap/fluid-nutils/run.sh b/perpendicular-flap/fluid-nutils/run.sh index 788f40d13..7094b61c8 100755 --- a/perpendicular-flap/fluid-nutils/run.sh +++ b/perpendicular-flap/fluid-nutils/run.sh @@ -1,4 +1,12 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 -m venv .venv +. .venv/bin/activate +pip install -r requirements.txt python3 fluid.py + +close_log diff --git a/perpendicular-flap/fluid-openfoam/run.sh b/perpendicular-flap/fluid-openfoam/run.sh index c191b9e48..da82a9ba2 100755 --- a/perpendicular-flap/fluid-openfoam/run.sh +++ b/perpendicular-flap/fluid-openfoam/run.sh @@ -1,8 +1,12 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + blockMesh -touch fluid-openfoam.foam ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/perpendicular-flap/fluid-openfoam/system/controlDict b/perpendicular-flap/fluid-openfoam/system/controlDict index 2b316a90a..9d35646a2 100644 --- a/perpendicular-flap/fluid-openfoam/system/controlDict +++ b/perpendicular-flap/fluid-openfoam/system/controlDict @@ -15,7 +15,7 @@ startTime 0; stopAt endTime; -endTime 10; +endTime 5; deltaT 0.01; diff --git a/perpendicular-flap/fluid-su2/euler_config_coupled.cfg b/perpendicular-flap/fluid-su2/euler_config_unsteady.cfg similarity index 73% rename from perpendicular-flap/fluid-su2/euler_config_coupled.cfg rename to perpendicular-flap/fluid-su2/euler_config_unsteady.cfg index 9c7cea24e..ba06b1902 100644 --- a/perpendicular-flap/fluid-su2/euler_config_coupled.cfg +++ b/perpendicular-flap/fluid-su2/euler_config_unsteady.cfg @@ -7,31 +7,12 @@ % Date: 01.11.2017 % % % % Modified for SU2-FEniCS tutorial by Ishaan Desai % -% Date: 28.08.2020 % +% Date: 28.08.2020 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -% ------------- PRECICE PROBLEM DEFINITION ------------% - -PRECICE_USAGE= YES -% -PRECICE_CONFIG_FILENAME= ../precice-config.xml -% -PRECICE_PARTICIPANT_NAME= Fluid -% -PRECICE_MESH_NAME= Fluid-Mesh -% -PRECICE_READ_DATA_NAME= Displacement -% -PRECICE_WRITE_DATA_NAME= Force -% -PRECICE_WETSURFACE_MARKER_NAME= wetSurface -% -PRECICE_NUMBER_OF_WETSURFACES= 1 - % ------------- DIRECT, ADJOINT, AND LINEARIZED PROBLEM DEFINITION ------------% % Physical governing equations (EULER, NAVIER_STOKES, NS_PLASMA) -PHYSICAL_PROBLEM= EULER +SOLVER= EULER % % Mathematical problem (DIRECT, CONTINUOUS_ADJOINT) MATH_PROBLEM= DIRECT @@ -57,42 +38,30 @@ FREESTREAM_PRESSURE= 101325.0 % Free-stream temperature (288.15 K by default) FREESTREAM_TEMPERATURE= 288.15 -% ------------------------- UNSTEADY SIMULATION -------------------------------% - +% ------------------------- TIME-DEPENDENT SIMULATION -------------------------------% +% Time domain simulation +TIME_DOMAIN= YES % Unsteady simulation (NO, TIME_STEPPING, DUAL_TIME_STEPPING-1ST_ORDER, % DUAL_TIME_STEPPING-2ND_ORDER, TIME_SPECTRAL) -UNSTEADY_SIMULATION= DUAL_TIME_STEPPING-1ST_ORDER +TIME_MARCHING= DUAL_TIME_STEPPING-1ST_ORDER % -% Time Step for dual time stepping simulations (s) -UNST_TIMESTEP= 0.01 +% Time Step for dual time stepping simulations (s) -- Only used when UNST_CFL_NUMBER = 0.0 +% For the DG-FEM solver it is used as a synchronization time when UNST_CFL_NUMBER != 0.0 +TIME_STEP= 0.01 % % Total Physical Time for dual time stepping simulations (s) -UNST_TIME= 5.0 +MAX_TIME= 5.0 % % Number of internal iterations (dual time method) -UNST_INT_ITER= 200 +INNER_ITER= 1000 % % Iteration number to begin unsteady restarts -UNST_RESTART_ITER= 1 - -% ----------------------- DYNAMIC MESH DEFINITION -----------------------------% - -% Dynamic mesh simulation (NO, YES) -GRID_MOVEMENT= YES -% -% Type of dynamic mesh (NONE, RIGID_MOTION, DEFORMING, ROTATING_FRAME, -% MOVING_WALL, STEADY_TRANSLATION, FLUID_STRUCTURE, -% AEROELASTIC, ELASTICITY, EXTERNAL, -% AEROELASTIC_RIGID_MOTION, GUST, PRECICE_MOVEMENT) -GRID_MOVEMENT_KIND= PRECICE_MOVEMENT -% -% Moving wall boundary marker(s) (NONE = no marker, ignored for RIGID_MOTION) -MARKER_MOVING= ( wetSurface ) +RESTART_ITER= 1 % -------------------- BOUNDARY CONDITION DEFINITION --------------------------% % Euler wall boundary marker(s) (NONE = no marker) -MARKER_EULER= ( upper_wall, lower_wall, wetSurface ) +MARKER_EULER= ( upper_wall, lower_wall, interface ) % % Inlet boundary marker(s) (NONE = no marker) % Format: ( inlet marker, total temperature, total pressure, flow_direction_x, @@ -103,6 +72,35 @@ MARKER_INLET= ( inlet, 288.6, 101400.0, 1.0, 0.0, 0.0 ) % Format: ( outlet marker, back pressure (static), ... ) MARKER_OUTLET= ( outlet, 101100.0 ) +% ---------------- MESH DEFORMATION PARAMETERS (NEW SOLVER) -------------------% +% +% Use the reformatted pseudo-elastic solver for grid deformation +DEFORM_MESH= YES +% Moving markers which deform the mesh +MARKER_DEFORM_MESH = ( interface ) + +% ------------------------ GRID DEFORMATION PARAMETERS ------------------------% +% +% Linear solver or smoother for implicit formulations (FGMRES, RESTARTED_FGMRES, BCGSTAB) +DEFORM_LINEAR_SOLVER= CONJUGATE_GRADIENT +% +% Preconditioner of the Krylov linear solver (ILU, LU_SGS, JACOBI) +DEFORM_LINEAR_SOLVER_PREC= LU_SGS +% +% Number of smoothing iterations for mesh deformation +DEFORM_LINEAR_SOLVER_ITER= 50 +% +% Number of nonlinear deformation iterations (surface deformation increments) +DEFORM_NONLINEAR_ITER= 1 +% +% Print the residuals during mesh deformation to the console (YES, NO) +%DEFORM_CONSOLE_OUTPUT= YES +% +% Type of element stiffness imposed for FEA mesh deformation (INVERSE_VOLUME, +% WALL_DISTANCE, CONSTANT_STIFFNESS) +DEFORM_STIFFNESS_TYPE= INVERSE_VOLUME +% + % ------------- COMMON PARAMETERS DEFINING THE NUMERICAL METHOD ---------------% % Numerical method for spatial gradients (GREEN_GAUSS, WEIGHTED_LEAST_SQUARES) @@ -121,8 +119,8 @@ CFL_ADAPT_PARAM= ( 1.5, 0.5, 1.0, 100.0 ) % Runge-Kutta alpha coefficients RK_ALPHA_COEFF= ( 0.66667, 0.66667, 1.000000 ) % -% Number of total iterations -EXT_ITER= 999999 +% Maximum number of time iterations +TIME_ITER= 999999 % ------------------------ LINEAR SOLVER DEFINITION ---------------------------% @@ -130,10 +128,10 @@ EXT_ITER= 999999 LINEAR_SOLVER= FGMRES % % Preconditioner of the Krylov linear solver (JACOBI, LINELET, LU_SGS) -LINEAR_SOLVER_PREC= LU_SGS +LINEAR_SOLVER_PREC= ILU % % Minimum error of the linear solver for implicit formulations -LINEAR_SOLVER_ERROR= 1E-4 +LINEAR_SOLVER_ERROR= 1E-6 % % Max number of iterations of the linear solver for the implicit formulation LINEAR_SOLVER_ITER= 20 @@ -189,24 +187,28 @@ TIME_DISCRE_FLOW= EULER_IMPLICIT % --------------------------- CONVERGENCE PARAMETERS --------------------------% -% Convergence criteria (CAUCHY, RESIDUAL) -% -CONV_CRITERIA= RESIDUAL +% Convergence field +CONV_FIELD= RMS_ENERGY % -% Residual reduction (order of magnitude with respect to the initial value) -RESIDUAL_REDUCTION= 1 % % Min value of the residual (log10 of the residual) -RESIDUAL_MINVAL= -3.5 +CONV_RESIDUAL_MINVAL= -1.5 % % Start convergence criteria at iteration number -STARTCONV_ITER= 10 +CONV_STARTITER= 10 +% ------------------------- SCREEN/HISTORY VOLUME OUTPUT --------------------------% +% Screen output fields (use 'SU2_CFD -d ' to view list of available fields) +SCREEN_OUTPUT= (INNER_ITER, RMS_DENSITY, RMS_MOMENTUM-X, RMS_MOMENTUM-Y, RMS_ENERGY) +% +% History output groups (use 'SU2_CFD -d ' to view list of available fields) +HISTORY_OUTPUT= (ITER, RMS_RES) +% +% Volume output fields/groups (use 'SU2_CFD -d ' to view list of available fields) +VOLUME_OUTPUT= (COORDINATES, SOLUTION, PRIMITIVE) % ------------------------- INPUT/OUTPUT INFORMATION --------------------------% -% Write residuals -WRT_RESIDUALS= YES -% + % Mesh input file MESH_FILENAME= fluidMesh.su2 % @@ -214,70 +216,31 @@ MESH_FILENAME= fluidMesh.su2 MESH_FORMAT= SU2 % % Restart flow input file -SOLUTION_FLOW_FILENAME= initial_flow.dat +SOLUTION_FILENAME= initial_flow.dat +% +% Files to output +% Possible formats : (TECPLOT_ASCII, TECPLOT, SURFACE_TECPLOT_ASCII, +% SURFACE_TECPLOT, CSV, SURFACE_CSV, PARAVIEW_ASCII, PARAVIEW_LEGACY, SURFACE_PARAVIEW_ASCII, +% SURFACE_PARAVIEW_LEGACY, PARAVIEW, SURFACE_PARAVIEW, RESTART_ASCII, RESTART, CGNS, SURFACE_CGNS, STL_ASCII, STL_BINARY) +% default : (RESTART, PARAVIEW, SURFACE_PARAVIEW) +OUTPUT_FILES= (PARAVIEW) % -% Output file format (PARAVIEW, TECPLOT, STL) -OUTPUT_FORMAT= PARAVIEW +OUTPUT_WRT_FREQ= (50, 50) % % Output file with the forces breakdown BREAKDOWN_FILENAME= forces_breakdown.dat % % Output file restart flow -RESTART_FLOW_FILENAME= restart_flow.dat -% -% Output file convergence history (w/o extension) -CONV_FILENAME= history -% -% Write binary restart files (YES, NO) -WRT_BINARY_RESTART= NO +RESTART_FILENAME= restart_flow.dat % % Read binary restart files (YES, NO) READ_BINARY_RESTART= NO % +% Output file convergence history (w/o extension) +CONV_FILENAME= history +% % Output file flow (w/o extension) variables -VOLUME_FLOW_FILENAME= flow +VOLUME_FILENAME= flow % % Output file surface flow coefficient (w/o extension) -SURFACE_FLOW_FILENAME= surface_flow -% -% Write surface solution files -WRT_SRF_SOL= NO -% -% Writing solution file frequency -WRT_SOL_FREQ= 1 -% -% Writing solution file frequency for physical time steps (dual time) -WRT_SOL_FREQ_DUALTIME= 1 -% -% Writing convergence history frequency -WRT_CON_FREQ= 1 -% -% Writing convergence history frequency -WRT_CON_FREQ_DUALTIME= 1 - -% ------------------------ GRID DEFORMATION PARAMETERS ------------------------% -% -% Linear solver or smoother for implicit formulations (FGMRES, RESTARTED_FGMRES, BCGSTAB) -DEFORM_LINEAR_SOLVER= FGMRES -% -% Preconditioner of the Krylov linear solver (ILU, LU_SGS, JACOBI) -DEFORM_LINEAR_SOLVER_PREC= LU_SGS -% -% Number of smoothing iterations for mesh deformation -DEFORM_LINEAR_ITER= 50 -% -% Number of nonlinear deformation iterations (surface deformation increments) -DEFORM_NONLINEAR_ITER= 1 -% -% Print the residuals during mesh deformation to the console (YES, NO) -%DEFORM_CONSOLE_OUTPUT= NO -% -% Factor to multiply smallest cell volume for deform tolerance (0.001 default) -DEFORM_TOL_FACTOR = 0.1 -% -% Type of element stiffness imposed for FEA mesh deformation (INVERSE_VOLUME, -% WALL_DISTANCE, CONSTANT_STIFFNESS) -DEFORM_STIFFNESS_TYPE= INVERSE_VOLUME -% -% Visualize the deformation (NO, YES) -%VISUALIZE_DEFORMATION= YES +SURFACE_FILENAME= surface_flow \ No newline at end of file diff --git a/perpendicular-flap/fluid-su2/fluidMesh.su2 b/perpendicular-flap/fluid-su2/fluidMesh.su2 index 3eb81ba50..a16a21fbe 100644 --- a/perpendicular-flap/fluid-su2/fluidMesh.su2 +++ b/perpendicular-flap/fluid-su2/fluidMesh.su2 @@ -1162,7 +1162,7 @@ MARKER_ELEMS= 24 3 58 59 3 59 60 3 60 5 -MARKER_TAG= wetSurface +MARKER_TAG= interface MARKER_ELEMS= 28 3 1 25 3 25 26 diff --git a/perpendicular-flap/fluid-su2/initial_flow_00000.csv b/perpendicular-flap/fluid-su2/initial_flow_00000.csv new file mode 100644 index 000000000..cec432cda --- /dev/null +++ b/perpendicular-flap/fluid-su2/initial_flow_00000.csv @@ -0,0 +1,403 @@ +"PointID", "x", "y", "Density", "X-Momentum", "Y-Momentum", "Energy", "Residual_Density", "Residual_X-Momentum", "Residual_Y-Momentum", "Residual_Energy", "Pressure", "Temperature", "Pressure_Coefficient", "Mach" +0, -3.000000000000000e+00, 0.000000000000000e+00, 1.223757965043072e+00, 7.878551614679247e+00, -2.635336810878929e-02, 2.534631943474481e+05, 1.110223024625157e-15, 1.223021683927072e-12, 1.460324916546796e-13, 1.746229827404022e-10, 1.013751332052040e+05, 2.885800150174616e+02, 1.059557258553220e+01, 1.890476623917364e-02 +1, -5.000000000000000e-02, 0.000000000000000e+00, 1.223978054994548e+00, 1.993560131193193e-01, 1.965771061654800e-01, 2.535026982174745e+05, 4.491962357633383e-13, -1.410999095341481e-11, -1.361069590366526e-11, -7.275957614183426e-10, 1.014010664786917e+05, 2.886019337268216e+02, 1.425278221572884e+01, 6.716537369509270e-04 +2, -5.000000000000000e-02, 1.000000000000000e+00, 1.222562828826684e+00, 4.187407444558510e+00, 7.450950470713709e+00, 2.532093886783100e+05, -1.602673549427891e-11, 7.883471653258312e-11, 1.064446308873812e-10, -5.995389074087143e-09, 1.012718049944566e+05, 2.885676938200937e+02, -3.976167753963526e+00, 2.052907242177121e-02 +3, 5.000000000000000e-02, 1.000000000000000e+00, 1.222524960034132e+00, -5.785116429801803e-03, 6.143653425102283e-01, 2.531108076650082e+05, -7.941602930827685e-11, 4.675237974538504e-11, -1.106572611320189e-10, -6.402842700481415e-10, 1.012442613121325e+05, 2.884981460233004e+02, -7.860483411008150e+00, 1.475937164099120e-03 +4, 5.000000000000000e-02, 0.000000000000000e+00, 1.223574222895994e+00, -6.656253986478188e-01, 6.418631435123792e-01, 2.532831050908447e+05, -5.681366488374806e-11, -7.511691269002085e-11, 4.577016543549917e-11, 1.257285475730896e-08, 1.013131022744092e+05, 2.884467434409618e+02, 1.847732958565746e+00, 2.219640395189620e-03 +5, 3.000000000000000e+00, 0.000000000000000e+00, 1.223823542781361e+00, -5.225883058831674e+00, 2.233226658268434e-01, 2.533553488172249e+05, -2.220446049250313e-16, 8.579803534303210e-13, -6.067368829576480e-14, 0.000000000000000e+00, 1.013376683387159e+05, 2.884579078276023e+02, 5.312133509511043e+00, 1.255298484653515e-02 +6, 3.000000000000000e+00, 4.000000000000000e+00, 1.223240607331094e+00, 1.640920683810398e+01, 6.211286818964271e-02, 2.533923193535832e+05, -2.220446049250313e-16, -5.329070518200751e-14, -1.702804564018834e-14, -8.731149137020111e-11, 1.013129027269839e+05, 2.885248435105395e+02, 1.819592015776307e+00, 3.939475089449580e-02 +7, -3.000000000000000e+00, 4.000000000000000e+00, 1.223611973761945e+00, 1.001789360302413e+01, -1.403905034563661e-02, 2.534362490378598e+05, 0.000000000000000e+00, 2.842170943040401e-14, 1.856327591642781e-13, 5.820766091346741e-11, 1.013580959853187e+05, 2.885659411317438e+02, 8.192918533170031e+00, 2.404151006528091e-02 +8, -3.000000000000000e+00, 3.428571428571430e+00, 1.223593289671423e+00, 9.843652433656628e+00, 2.409716032426736e-02, 2.534317513777481e+05, 8.881784197001252e-16, 5.293543381412746e-13, 8.951173136040325e-14, 2.037268131971359e-10, 1.013568622697478e+05, 2.885668350563773e+02, 8.018935234490122e+00, 2.362372793145228e-02 +9, -3.000000000000000e+00, 2.857142857142859e+00, 1.223608818539996e+00, 9.579797396802602e+00, 5.652627433494539e-02, 2.534343881266471e+05, 8.881784197001252e-16, 5.293543381412746e-13, 8.951173136040325e-14, 2.037268131971359e-10, 1.013587544249059e+05, 2.885685598123111e+02, 8.285774207566712e+00, 2.299047451524354e-02 +10, -3.000000000000000e+00, 2.285714285714289e+00, 1.223658301177137e+00, 9.254966786671991e+00, 7.996263064156479e-02, 2.534443155810829e+05, 2.220446049250313e-16, 4.281019982954604e-13, -1.296740492762183e-13, 1.164153218269348e-10, 1.013637254604591e+05, 2.885710425710946e+02, 8.986808695400549e+00, 2.221036489112886e-02 +11, -3.000000000000000e+00, 1.714285714285720e+00, 1.223690747347469e+00, 8.876058496425516e+00, 1.042926092240423e-01, 2.534507512795583e+05, 2.220446049250313e-16, 4.281019982954604e-13, -1.296740492762183e-13, 1.164153218269348e-10, 1.013674222104140e+05, 2.885739150567588e+02, 9.508138543794939e+00, 2.130105313659993e-02 +12, -3.000000000000000e+00, 1.142857142857147e+00, 1.223770775340336e+00, 8.500316548962836e+00, 9.222928266231895e-02, 2.534671528555470e+05, -2.220446049250313e-16, 3.144151605738443e-13, 4.219402605087907e-13, 1.164153218269348e-10, 1.013750511057104e+05, 2.885767604872736e+02, 1.058399460025608e+01, 2.039769348248397e-02 +13, -3.000000000000000e+00, 5.714285714285738e-01, 1.223776789906796e+00, 8.130590418479297e+00, 2.516453412873485e-02, 2.534677233087809e+05, -2.220446049250313e-16, 3.144151605738443e-13, 4.219402605087907e-13, 1.164153218269348e-10, 1.013762855340710e+05, 2.885788561398342e+02, 1.075807841926094e+01, 1.950926252599033e-02 +14, -2.473871371856578e+00, 0.000000000000000e+00, 1.223789663026069e+00, 7.683895890466811e+00, -4.223266672329690e-03, 2.534694156373136e+05, 0.000000000000000e+00, 8.926193117986259e-13, 1.164901508587946e-13, 1.164153218269348e-10, 1.013781171664137e+05, 2.885810344510186e+02, 1.101638223292599e+01, 1.843707485379359e-02 +15, -2.029065741919601e+00, 0.000000000000000e+00, 1.223769771619374e+00, 7.316686706442264e+00, 2.835258352155217e-04, 2.534647100176870e+05, 0.000000000000000e+00, 8.926193117986259e-13, 1.164901508587946e-13, 1.164153218269348e-10, 1.013771349914213e+05, 2.885829292205371e+02, 1.087787215079969e+01, 1.755620221018881e-02 +16, -1.653013276730948e+00, 0.000000000000000e+00, 1.223805494217887e+00, 6.764408435810212e+00, 5.182658639998013e-03, 2.534712832245824e+05, -3.774758283725532e-15, 5.773159728050814e-13, 5.567768468495160e-14, 2.910383045673370e-11, 1.013810354269597e+05, 2.885856083143117e+02, 1.142792652089782e+01, 1.623048028894917e-02 +17, -1.335086820797576e+00, 0.000000000000000e+00, 1.223830412707588e+00, 6.085314974435907e+00, 2.931240368014256e-03, 2.534755288378695e+05, -3.774758283725532e-15, 5.773159728050814e-13, 5.567768468495160e-14, 2.910383045673370e-11, 1.013841598687493e+05, 2.885886260850625e+02, 1.186854727813651e+01, 1.460069136002613e-02 +18, -1.066301883479915e+00, 0.000000000000000e+00, 1.223869695735947e+00, 5.334137703603092e+00, 8.762097934947753e-03, 2.534827748354416e+05, -1.110223024625157e-14, -6.155076448521868e-13, 1.096234214514880e-12, 2.910383045673370e-10, 1.013884602395376e+05, 2.885916036959023e+02, 1.247500205014994e+01, 1.279790660968453e-02 +19, -8.390627380676499e-01, 0.000000000000000e+00, 1.223893852609366e+00, 4.515843855081984e+00, 1.007795045011813e-02, 2.534869444518391e+05, -1.110223024625157e-14, -6.155076448521868e-13, 1.096234214514880e-12, 2.910383045673370e-10, 1.013914453108086e+05, 2.885944040799708e+02, 1.289596824264381e+01, 1.083436461023154e-02 +20, -6.469477023227581e-01, 0.000000000000000e+00, 1.223918376036596e+00, 3.660503640661597e+00, -9.646334203030165e-03, 2.534913095515321e+05, -5.906386491005833e-14, -6.769695914954355e-12, 3.683719995706269e-12, 3.492459654808044e-10, 1.013943342334284e+05, 2.885968442547772e+02, 1.330337518380363e+01, 8.782036981737731e-03 +21, -4.845276733706831e-01, 0.000000000000000e+00, 1.223956389813042e+00, 2.879035007841546e+00, 5.261883235178921e-04, 2.534986943049626e+05, -5.906386491005833e-14, -6.769695914954355e-12, 3.683719995706269e-12, 3.492459654808044e-10, 1.013981232876404e+05, 2.885986653621836e+02, 1.383772213233614e+01, 6.906929206776113e-03 +22, -3.472127287034583e-01, 0.000000000000000e+00, 1.223940968730644e+00, 2.071797972608851e+00, -3.160060584100463e-03, 2.534951569637487e+05, -2.131628207280301e-14, -2.175370994450532e-11, 2.237654506132003e-12, 3.492459654808044e-10, 1.013973613861779e+05, 2.886001330238594e+02, 1.373027586770983e+01, 4.970388413232113e-03 +23, -2.311223821547319e-01, 0.000000000000000e+00, 1.223997012145073e+00, 1.343703595407594e+00, 6.689385944809837e-03, 2.535066068839553e+05, -2.131628207280301e-14, -2.175370994450532e-11, 2.237654506132003e-12, 3.492459654808044e-10, 1.014023477227802e+05, 2.886011104346268e+02, 1.443346816812547e+01, 3.223522152733120e-03 +24, -1.329760059234513e-01, 0.000000000000000e+00, 1.223940881442810e+00, 6.923875674245451e-01, -1.572283520979862e-02, 2.534949515474422e+05, 2.498001805406602e-13, -1.840494423532846e-11, -5.467903907430127e-12, 4.365574568510056e-10, 1.013979022413757e+05, 2.886016930039438e+02, 1.380654934081502e+01, 1.661508176163856e-03 +25, -5.000000000000000e-02, 7.692307692307693e-02, 1.224004932712833e+00, -3.947629100345879e-02, 6.240340030396374e-01, 2.535083509391398e+05, 4.951594689828198e-13, 7.652212197228891e-14, -2.396127740666998e-11, -9.604264050722122e-10, 1.014032764908129e+05, 2.886018862379059e+02, 1.456444659610021e+01, 1.500009142673747e-03 +26, -5.000000000000000e-02, 1.538461538461539e-01, 1.223941939863920e+00, -1.868251187361056e-02, 1.128501378817081e+00, 2.534953964649894e+05, 4.951594689828198e-13, 7.652212197228891e-14, -2.396127740666998e-11, -9.604264050722122e-10, 1.013979504283443e+05, 2.886015805825957e+02, 1.381334485183168e+01, 2.707712722865374e-03 +27, -5.000000000000000e-02, 2.307692307692308e-01, 1.223959189483881e+00, 7.343057125441150e-03, 1.678407127824203e+00, 2.534990442359216e+05, 8.946177132429511e-13, 5.803912905832931e-12, -1.295252793909185e-11, -5.529727786779404e-10, 1.013991573678428e+05, 2.886009484102336e+02, 1.398355208613676e+01, 4.026584449831492e-03 +28, -5.000000000000000e-02, 3.076923076923077e-01, 1.223961647752314e+00, 5.568027900083252e-03, 2.326777511305952e+00, 2.534996153436196e+05, 8.946177132429511e-13, 5.803912905832931e-12, -1.295252793909185e-11, -5.529727786779404e-10, 1.013989614815274e+05, 2.885998112410959e+02, 1.395592744710553e+01, 5.582020472485027e-03 +29, -5.000000000000000e-02, 3.846153846153846e-01, 1.223949024946715e+00, -2.573849030204297e-04, 3.029734756950693e+00, 2.534970367549214e+05, 8.073541835074138e-13, 1.067740340587875e-11, 1.180211484097526e-11, -2.153683453798294e-09, 1.013973147550628e+05, 2.885981006925259e+02, 1.372369976911861e+01, 7.268515159307221e-03 +30, -5.000000000000000e-02, 4.615384615384615e-01, 1.223943737190015e+00, -6.088524396581517e-03, 3.766938009719254e+00, 2.534960004118487e+05, 8.073541835074138e-13, 1.067740340587875e-11, 1.180211484097526e-11, -2.153683453798294e-09, 1.013960814537386e+05, 2.885958372613882e+02, 1.354977488910135e+01, 9.037196173600163e-03 +31, -5.000000000000000e-02, 5.384615384615384e-01, 1.223904272448178e+00, -6.935524251261995e-03, 4.529132437498036e+00, 2.534880975799079e+05, -2.209121774399136e-12, 1.576727637342401e-11, 3.005773407949164e-11, -1.338776201009750e-09, 1.013918869579162e+05, 2.885932041675007e+02, 1.295825101060475e+01, 1.086616219582331e-02 +32, -5.000000000000000e-02, 6.153846153846154e-01, 1.223913513697062e+00, -1.901007765262191e-02, 5.336779390453425e+00, 2.534909134346653e+05, -2.209121774399136e-12, 1.576727637342401e-11, 3.005773407949164e-11, -1.338776201009750e-09, 1.013917111927779e+05, 2.885905248442199e+02, 1.293346393708576e+01, 1.280387414231310e-02 +33, -5.000000000000000e-02, 6.923076923076923e-01, 1.223804992739801e+00, -9.607762678765343e-03, 6.215072151774851e+00, 2.534705576086798e+05, -1.834976615100459e-12, 2.352196215582580e-11, 9.458211991386634e-11, -2.997694537043571e-09, 1.013819104014431e+05, 2.885882172225691e+02, 1.155131877635537e+01, 1.491235831004910e-02 +34, -5.000000000000000e-02, 7.692307692307692e-01, 1.223908290741413e+00, -6.292842348785102e-02, 7.016067186812349e+00, 2.534952934057546e+05, -1.834976615100459e-12, 2.352196215582580e-11, 9.458211991386634e-11, -2.997694537043571e-09, 1.013900727793655e+05, 2.885870929624351e+02, 1.270240859759395e+01, 1.683352365654935e-02 +35, -5.000000000000000e-02, 8.461538461538461e-01, 1.223061100319389e+00, -3.403783511210857e-02, 7.415635468409019e+00, 2.533227398570597e+05, 7.534639578921087e-12, 1.828448503715663e-11, 2.157261036472846e-10, -2.270098775625229e-09, 1.013201032918500e+05, 2.885876991106301e+02, 2.835043273158868e+00, 1.780397768454164e-02 +36, -5.000000000000000e-02, 9.230769230769230e-01, 1.225006911940109e+00, -3.942224719480268e-01, 8.269215679434144e+00, 2.537261671661318e+05, 7.534639578921087e-12, 1.828448503715663e-11, 2.157261036472846e-10, -2.270098775625229e-09, 1.014792774864349e+05, 2.885819559269366e+02, 2.528239831264052e+01, 1.984427848012479e-02 +37, 6.938893903907228e-17, 1.000000000000000e+00, 1.220419195319508e+00, 3.397940998678292e+00, -4.589746106087408e-01, 2.527267606948333e+05, -1.602673549427891e-11, 7.883471653258312e-11, 1.064446308873812e-10, -5.995389074087143e-09, 1.010887776185086e+05, 2.885521140760875e+02, -2.978738985917200e+01, 8.250342680021438e-03 +38, 5.000000000000000e-02, 9.230769230769231e-01, 1.223967887977187e+00, 1.989011929509321e-01, 2.842362035880822e+00, 2.533639976908538e+05, -7.941602930827685e-11, 4.675237974538504e-11, -1.106572611320189e-10, -6.402842700481415e-10, 1.013442724755855e+05, 2.884426858329162e+02, 6.243474204694256e+00, 6.837408064670799e-03 +39, 5.000000000000000e-02, 8.461538461538461e-01, 1.223501770593328e+00, 2.742063466425996e-02, 3.715631764423770e+00, 2.532445667715527e+05, -3.932010272933439e-11, 4.865846614521274e-11, 2.400479814923528e-11, 9.633367881178856e-09, 1.012955697979027e+05, 2.884139050785244e+02, -6.247640808526865e-01, 8.920371633658018e-03 +40, 5.000000000000000e-02, 7.692307692307693e-01, 1.223597326282272e+00, 3.558230752060090e-02, 4.437301040383780e+00, 2.532627133047309e+05, -3.932010272933439e-11, 4.865846614521274e-11, 2.400479814923528e-11, 9.633367881178856e-09, 1.013018667946529e+05, 2.884093093939986e+02, 2.632625374280316e-01, 1.065223783674791e-02 +41, 5.000000000000000e-02, 6.923076923076923e-01, 1.223501107781601e+00, 7.338595991349704e-03, 4.904097593853414e+00, 2.532526433356080e+05, 1.634603563616110e-11, 3.446593010991705e-11, 3.043618690412586e-10, 5.878973752260208e-09, 1.012971259561819e+05, 2.884184920975478e+02, -4.053086755117622e-01, 1.177320828672195e-02 +42, 5.000000000000000e-02, 6.153846153846154e-01, 1.223454531171474e+00, 6.345069595597649e-03, 5.177120587743731e+00, 2.532545771562299e+05, 1.634603563616110e-11, 3.446593010991705e-11, 3.043618690412586e-10, 5.878973752260208e-09, 1.012974493971972e+05, 2.884303930711952e+02, -3.596957837765316e-01, 1.242886346600654e-02 +43, 5.000000000000000e-02, 5.384615384615385e-01, 1.223417954674421e+00, 1.519008101634436e-02, 5.276952801240473e+00, 2.532548273914949e+05, 1.307021157970212e-11, -8.108767129977323e-12, 2.973568058450837e-10, 4.540197551250458e-09, 1.012973787164581e+05, 2.884388150081056e+02, -3.696634525251049e-01, 1.266877032133308e-02 +44, 5.000000000000000e-02, 4.615384615384616e-01, 1.223419370338878e+00, 9.373894011918623e-03, 5.169716915391534e+00, 2.532580629778989e+05, 1.307021157970212e-11, -8.108767129977323e-12, 2.973568058450837e-10, 4.540197551250458e-09, 1.012988561151905e+05, 2.884426880529612e+02, -1.613150203838971e-01, 1.241119250468556e-02 +45, 5.000000000000000e-02, 3.846153846153846e-01, 1.223426910541763e+00, -2.048555209884316e-03, 4.857659430527455e+00, 2.532590677336886e+05, -9.620304552981906e-12, -6.982442402048150e-12, 1.823909911990995e-10, 2.037268131971359e-10, 1.012997695913825e+05, 2.884435113832188e+02, -3.249310639619177e-02, 1.166191416955090e-02 +46, 5.000000000000000e-02, 3.076923076923077e-01, 1.223455750012135e+00, 2.853324843215160e-03, 4.381344332782626e+00, 2.532629762064997e+05, -9.620304552981906e-12, -6.982442402048150e-12, 1.823909911990995e-10, 2.037268131971359e-10, 1.013020524555313e+05, 2.884432122839114e+02, 2.894451461371600e-01, 1.051817045920612e-02 +47, 5.000000000000000e-02, 2.307692307692308e-01, 1.223488623932494e+00, -5.844995257632352e-03, 3.720464130929277e+00, 2.532676227929472e+05, -4.038525069915977e-11, -4.497902050815128e-12, 9.627409980339507e-11, -1.949956640601158e-09, 1.013047864255211e+05, 2.884432464844082e+02, 6.750000734899242e-01, 8.931382508860528e-03 +48, 5.000000000000000e-02, 1.538461538461539e-01, 1.223431865610700e+00, 2.104430966166451e-02, 2.887653439783380e+00, 2.532543178208866e+05, -4.038525069915977e-11, -4.497902050815128e-12, 9.627409980339507e-11, -1.949956640601158e-09, 1.013003639163138e+05, 2.884440354358466e+02, 5.132087347951199e-02, 6.932616688276416e-03 +49, 5.000000000000000e-02, 7.692307692307698e-02, 1.223680614489738e+00, 7.149456332124067e-02, 1.809448906124113e+00, 2.533050157756293e+05, -5.111155942927326e-11, -2.103994756197380e-11, 5.924327695083775e-11, -1.135049387812614e-09, 1.013214703506593e+05, 2.884454872800005e+02, 3.027831146430117e+00, 4.346465798739755e-03 +50, 1.329760059234507e-01, 0.000000000000000e+00, 1.223438522793232e+00, -2.034214090974660e+00, -7.687095659165278e-03, 2.532562804027414e+05, -1.698796658899937e-11, -1.478892563966383e-10, 2.107758412250860e-12, -5.413312464952469e-09, 1.013018356929321e+05, 2.884466566389012e+02, 2.588764535428799e-01, 4.883554155655352e-03 +51, 2.311223821547306e-01, 0.000000000000000e+00, 1.223564418373943e+00, -3.638300389591804e+00, 2.563512689239940e-02, 2.532845883053351e+05, -1.698796658899937e-11, -1.478892563966383e-10, 2.107758412250860e-12, -5.413312464952469e-09, 1.013116714986874e+05, 2.884449812194581e+02, 1.645959482075791e+00, 8.733778132810356e-03 +52, 3.472127287034560e-01, 0.000000000000000e+00, 1.223473316195546e+00, -5.016478645283216e+00, 3.024440448946949e-02, 2.532682877474459e+05, 8.687051078482000e-12, -1.390283443925000e-10, -2.053768266563338e-11, -1.135049387812614e-09, 1.013032012417508e+05, 2.884423418802269e+02, 4.514513821475883e-01, 1.204298116754474e-02 +53, 4.845276733706798e-01, 0.000000000000000e+00, 1.223405486390305e+00, -6.293460198749821e+00, 1.342937328768551e-02, 2.532568306845221e+05, 8.687051078482000e-12, -1.390283443925000e-10, -2.053768266563338e-11, -1.135049387812614e-09, 1.012962572625289e+05, 2.884385613077771e+02, -5.278151841887412e-01, 1.510930713451688e-02 +54, 6.469477023227540e-01, 0.000000000000000e+00, 1.223360803222700e+00, -7.352210279189084e+00, 1.127922908908295e-02, 2.532498285945939e+05, 1.776578884005175e-12, -2.331912440922679e-11, -1.041666752854553e-11, 4.947651177644730e-10, 1.012910942864317e+05, 2.884343945236242e+02, -1.255917863254788e+00, 1.765190171751359e-02 +55, 8.390627380676476e-01, 0.000000000000000e+00, 1.223330889947577e+00, -8.129958402191736e+00, 2.375632609296409e-02, 2.532453294967302e+05, 1.776578884005175e-12, -2.331912440922679e-11, -1.041666752854553e-11, 4.947651177644730e-10, 1.012873257627246e+05, 2.884307159815399e+02, -1.787369521279687e+00, 1.951985720344842e-02 +56, 1.066301883479911e+00, 0.000000000000000e+00, 1.223237706712982e+00, -8.698758456687521e+00, 2.419010708237380e-02, 2.532273487371431e+05, -4.660716257376407e-13, 2.425615264201042e-12, -4.066136316538405e-12, -8.731149137020111e-10, 1.012785675767200e+05, 2.884277457864309e+02, -3.022482482019328e+00, 2.088722418111759e-02 +57, 1.335086820797570e+00, 0.000000000000000e+00, 1.223292660259724e+00, -8.952735764375348e+00, 1.285207313174935e-03, 2.532395067791464e+05, -4.660716257376407e-13, 2.425615264201042e-12, -4.066136316538405e-12, -8.731149137020111e-10, 1.012826984918880e+05, 2.884265526106637e+02, -2.439924991108728e+00, 2.149606350437719e-02 +58, 1.653013276730942e+00, 0.000000000000000e+00, 1.223289154652572e+00, -8.423180812269656e+00, -5.737245706858612e-02, 2.532381744436786e+05, -1.221245327087672e-14, 1.254107928616577e-12, -3.198552533945076e-13, 2.037268131971359e-10, 1.012836693694525e+05, 2.884301439736069e+02, -2.303008115562593e+00, 2.022497080268198e-02 +59, 2.029065741919597e+00, 0.000000000000000e+00, 1.223417405138189e+00, -7.570871242164661e+00, -7.682860351837315e-02, 2.532642758233826e+05, -1.221245327087672e-14, 1.254107928616577e-12, -3.198552533945076e-13, 2.037268131971359e-10, 1.012963392032338e+05, 2.884359846103367e+02, -5.162595919009123e-01, 1.817690763934325e-02 +60, 2.473871371856569e+00, 0.000000000000000e+00, 1.222948967440781e+00, -6.729715961792509e+00, -9.569820578749043e-02, 2.531688380614914e+05, 1.598721155460225e-14, 1.016964290556643e-12, -7.638334409421077e-14, -2.910383045673370e-11, 1.012601271910189e+05, 2.884433156794237e+02, -5.623016356106107e+00, 1.616416299614755e-02 +61, 3.000000000000000e+00, 5.714285714285704e-01, 1.223539817586672e+00, -1.533413934172217e+00, -5.212908455849113e-01, 2.533121498324063e+05, 2.220446049250313e-16, 7.008837954458613e-13, 1.458833054357456e-13, 2.910383045673370e-11, 1.013244311602488e+05, 2.884871095924678e+02, 3.445375863606059e+00, 3.887563242027528e-03 +62, 3.000000000000000e+00, 1.142857142857142e+00, 1.223202814944334e+00, 3.878005775905434e+00, -6.204377952023048e-01, 2.532677000937998e+05, 2.220446049250313e-16, 7.008837954458613e-13, 1.458833054357456e-13, 2.910383045673370e-11, 1.013045581545309e+05, 2.885099929493624e+02, 6.428084234778505e-01, 9.429072110239431e-03 +63, 3.000000000000000e+00, 1.714285714285711e+00, 1.222988450837668e+00, 9.386710321842157e+00, -3.073847897324130e-01, 2.532539265112063e+05, 4.440892098500626e-16, 3.446132268436486e-13, 1.252886683289489e-13, 8.731149137020111e-11, 1.012871461320331e+05, 2.885109654664259e+02, -1.812701729919100e+00, 2.255245299358548e-02 +64, 3.000000000000000e+00, 2.285714285714280e+00, 1.222856100207056e+00, 1.357177637501069e+01, 3.203785211933152e-01, 2.532574336188076e+05, 4.440892098500626e-16, 3.446132268436486e-13, 1.252886683289489e-13, 8.731149137020111e-11, 1.012728315925101e+05, 2.885014126183130e+02, -3.831392961479513e+00, 3.260314504309984e-02 +65, 3.000000000000000e+00, 2.857142857142853e+00, 1.222945118455776e+00, 1.579341962220118e+01, 6.202487704657497e-01, 2.533031919656979e+05, -2.220446049250313e-16, 2.486899575160351e-14, 1.106892355551281e-13, 0.000000000000000e+00, 1.012804218356963e+05, 2.885020337469933e+02, -2.760987773754032e+00, 3.795601226742020e-02 +66, 3.000000000000000e+00, 3.428571428571426e+00, 1.223081652575294e+00, 1.647079647109887e+01, 4.070339669003665e-01, 2.533508775838600e+05, -2.220446049250313e-16, 2.486899575160351e-14, 1.106892355551281e-13, 0.000000000000000e+00, 1.012959626948797e+05, 2.885140918324742e+02, -5.693562431620811e-01, 3.956028044196403e-02 +67, 2.400000000000000e+00, 4.000000000000000e+00, 1.223099827036691e+00, 1.577942279872363e+01, 1.714299567131941e-02, 2.533580977925412e+05, -2.220446049250313e-16, -8.348877145181177e-14, -7.771561172376096e-15, -5.820766091346741e-11, 1.013025244554264e+05, 2.885284938207932e+02, 3.560083805416584e-01, 3.788665515043516e-02 +68, 1.800000000000000e+00, 4.000000000000000e+00, 1.223220053200953e+00, 1.489702270449715e+01, 6.783645456963873e-03, 2.533726891955301e+05, -2.220446049250313e-16, -8.348877145181177e-14, -7.771561172376096e-15, -5.820766091346741e-11, 1.013127909016674e+05, 2.885293732111808e+02, 1.803821981023614e+00, 3.576441051220497e-02 +69, 1.200000000000000e+00, 4.000000000000000e+00, 1.223262219994822e+00, 1.391428808462400e+01, -3.188238824968804e-03, 2.533725358368414e+05, 0.000000000000000e+00, -1.296740492762183e-13, 1.110223024625157e-14, -2.910383045673370e-11, 1.013173600549097e+05, 2.885324394542099e+02, 2.448181484934937e+00, 3.340375351251300e-02 +70, 6.000000000000001e-01, 4.000000000000000e+00, 1.223349557188793e+00, 1.307187560018032e+01, -3.702570956563547e-02, 2.533862989426374e+05, 0.000000000000000e+00, -1.296740492762183e-13, 1.110223024625157e-14, -2.910383045673370e-11, 1.013265839307622e+05, 2.885381065449570e+02, 3.748967813033808e+00, 3.137896720462322e-02 +71, 0.000000000000000e+00, 4.000000000000000e+00, 1.223410160075302e+00, 1.234209437730548e+01, -2.334148708810666e-02, 2.533979985581998e+05, 0.000000000000000e+00, 1.243449787580175e-14, -9.109379917049409e-14, 0.000000000000000e+00, 1.013342972533594e+05, 2.885457769211294e+02, 4.836730131063474e+00, 2.962520405619784e-02 +72, -6.000000000000001e-01, 4.000000000000000e+00, 1.223495301000652e+00, 1.166477629347413e+01, -2.875841698754635e-03, 2.534155966849660e+05, 0.000000000000000e+00, 1.243449787580175e-14, -9.109379917049409e-14, 0.000000000000000e+00, 1.013439963304096e+05, 2.885533133709095e+02, 6.204531153514693e+00, 2.799704812656940e-02 +73, -1.200000000000000e+00, 4.000000000000000e+00, 1.223554398937438e+00, 1.104587691005608e+01, -5.035250169728712e-03, 2.534271321705886e+05, -2.220446049250313e-16, 1.225686219186173e-13, -3.319566843629218e-14, 2.910383045673370e-11, 1.013509091007704e+05, 2.885590577299490e+02, 7.179396526643131e+00, 2.651006306972257e-02 +74, -1.800000000000000e+00, 4.000000000000000e+00, 1.223592127979970e+00, 1.053524804143388e+01, 5.108381190693863e-03, 2.534337606075003e+05, -2.220446049250313e-16, 1.225686219186173e-13, -3.319566843629218e-14, 2.910383045673370e-11, 1.013553623352758e+05, 2.885628386503734e+02, 7.807408725960496e+00, 2.528361076687625e-02 +75, -2.400000000000000e+00, 4.000000000000000e+00, 1.223594370121131e+00, 1.018752621252583e+01, -1.309768862935442e-03, 2.534331827367243e+05, 4.440892098500626e-16, 2.646771690706373e-13, 8.443246102274315e-14, 8.731149137020111e-11, 1.013563090264362e+05, 2.885650051447953e+02, 7.940914742101246e+00, 2.444897161960892e-02 +76, -1.095548164805289e-01, 8.878076174406992e-01, 1.223594622425178e+00, 3.502152679783135e-01, 8.300837659479948e+00, 2.534345596601870e+05, 7.534639578921087e-12, 1.828448503715663e-11, 2.157261036472846e-10, -2.270098775625229e-09, 1.013625412782710e+05, 2.885826890812301e+02, 8.819810784230073e+00, 1.993822816992968e-02 +77, 1.209364589843588e-01, 8.883063748384306e-01, 1.223663596748324e+00, 7.467379231271701e-01, 3.875431862824232e+00, 2.532863954625994e+05, -3.932010272933439e-11, 4.865846614521274e-11, 2.400479814923528e-11, 9.633367881178856e-09, 1.013120122909410e+05, 2.884225728427822e+02, 1.694019311942434e+00, 9.473504827547255e-03 +78, -1.483858789698155e+00, 2.494192115114299e-01, 1.223816320534533e+00, 6.605936104535863e+00, 5.176259376888152e-01, 2.534733917384995e+05, -3.774758283725532e-15, 5.773159728050814e-13, 5.567768468495160e-14, 2.910383045673370e-11, 1.013821813819656e+05, 2.885863173656912e+02, 1.158953348830629e+01, 1.589866311697236e-02 +79, 1.500258948630349e+00, 2.278351458257136e-01, 1.223227198228799e+00, -6.144979301997917e+00, -2.794535821136875e-01, 2.532239235464876e+05, -1.221245327087672e-14, 1.254107928616577e-12, -3.198552533945076e-13, 2.037268131971359e-10, 1.012833826913899e+05, 2.884439365248267e+02, -2.343436554798374e+00, 1.477006372101127e-02 +80, 1.151375566677099e-01, 5.734187430161577e-01, 1.223472855544427e+00, 4.452984650279733e-02, 4.984754960135978e+00, 2.532584284707206e+05, 1.307021157970212e-11, -8.108767129977323e-12, 2.973568058450837e-10, 4.540197551250458e-09, 1.012993092197150e+05, 2.884313686567231e+02, -9.741648356919468e-02, 1.196731474750654e-02 +81, -1.166173387526489e-01, 5.769230769230791e-01, 1.223892095125297e+00, 7.019227204184725e-01, 4.762272443027877e+00, 2.534858751217173e+05, -2.209121774399136e-12, 1.576727637342401e-11, 3.005773407949164e-11, -1.338776201009750e-09, 1.013905634510907e+05, 2.885923084205152e+02, 1.277160500503202e+01, 1.154906414525376e-02 +82, -7.468484100845061e-01, 1.615795309733068e-01, 1.223876396331284e+00, 4.242150319597413e+00, 7.176166180626214e-01, 2.534830558367938e+05, -5.906386491005833e-14, -6.769695914954355e-12, 3.683719995706269e-12, 3.492459654808044e-10, 1.013901973866100e+05, 2.885949682666642e+02, 1.271998118882908e+01, 1.032243042795870e-02 +83, 7.467659569647780e-01, 1.592204984801166e-01, 1.223331881375800e+00, -5.986879798838864e+00, 6.607848138550863e-01, 2.532375156350158e+05, 1.776578884005175e-12, -2.331912440922679e-11, -1.041666752854553e-11, 4.947651177644730e-10, 1.012890750154196e+05, 2.884354634808710e+02, -1.540683201301613e+00, 1.446146792958726e-02 +84, -2.588893537538057e+00, 2.076201888273092e+00, 1.223656783455797e+00, 9.149579275689579e+00, 4.664597733209856e-01, 2.534440560299182e+05, 2.220446049250313e-16, 4.281019982954604e-13, -1.296740492762183e-13, 1.164153218269348e-10, 1.013639041231829e+05, 2.885719091235996e+02, 9.012004397526388e+00, 2.198514276241241e-02 +85, 2.516144394223813e+00, 1.947580703292078e+00, 1.223307130838489e+00, 1.206388200775215e+01, 7.492333609218632e-02, 2.533456975399796e+05, 4.440892098500626e-16, 3.446132268436486e-13, 1.252886683289489e-13, 8.731149137020111e-11, 1.013144840328785e+05, 2.885136566051185e+02, 2.042593834231533e+00, 2.896195779193501e-02 +86, -9.330139280107341e-01, 3.509249751650770e+00, 1.223526263833988e+00, 1.114957916196169e+01, 5.371025682894208e-01, 2.534213526872218e+05, -2.220446049250313e-16, 1.225686219186173e-13, -3.319566843629218e-14, 2.910383045673370e-11, 1.013481734541288e+05, 2.885579042565659e+02, 6.793605151429678e+00, 2.679064510212000e-02 +87, 9.096046446550892e-01, 3.461623237161129e+00, 1.223301630710585e+00, 1.389258934660657e+01, 8.510767481923803e-01, 2.533830832260611e+05, 0.000000000000000e+00, -1.296740492762183e-13, 1.110223024625157e-14, -2.910383045673370e-11, 1.013215602564774e+05, 2.885351048816555e+02, 3.040510009501143e+00, 3.341295478543647e-02 +88, 1.171757894551490e-01, 3.453095229188376e-01, 1.223452440288169e+00, -4.204545111283494e-01, 4.244085185902976e+00, 2.532603925983910e+05, -9.620304552981906e-12, -6.982442402048150e-12, 1.823909911990995e-10, 2.037268131971359e-10, 1.013011836436669e+05, 2.884415187648908e+02, 1.669219668468395e-01, 1.023858825398337e-02 +89, -1.176381462141406e-01, 3.461538461538470e-01, 1.223943210647000e+00, 6.004773146295672e-01, 2.590066632574460e+00, 2.534957084867264e+05, 8.073541835074138e-13, 1.067740340587875e-11, 1.180211484097526e-11, -2.153683453798294e-09, 1.013971282727690e+05, 2.885989408973984e+02, 1.369740132125197e+01, 6.378551548014329e-03 +90, -4.145464039623574e-01, 1.102721012490148e-01, 1.223939176257936e+00, 2.443717357914361e+00, 6.618056936378736e-01, 2.534948841825701e+05, -2.131628207280301e-14, -2.175370994450532e-11, 2.237654506132003e-12, 3.492459654808044e-10, 1.013969062776303e+05, 2.885992603368599e+02, 1.366609471587567e+01, 6.073848606790980e-03 +91, 4.158702010370665e-01, 1.097277098231973e-01, 1.223448297738540e+00, -4.517934943953776e+00, 9.485650028787292e-01, 2.532600328935486e+05, 8.687051078482000e-12, -1.390283443925000e-10, -2.053768266563338e-11, -1.135049387812614e-09, 1.013005293139645e+05, 2.884406322946766e+02, 7.464588414995200e-02, 1.108267105125206e-02 +92, 1.211038805102060e-01, 7.285624374591277e-01, 1.223593912713315e+00, 3.747601817997721e-01, 4.695806724944773e+00, 2.532657192767548e+05, 1.634603563616110e-11, 3.446593010991705e-11, 3.043618690412586e-10, 5.878973752260208e-09, 1.013026605193991e+05, 2.884123737584824e+02, 3.751966435035353e-01, 1.130826010655149e-02 +93, -1.166173387526489e-01, 7.307692307692339e-01, 1.223765411935546e+00, 7.334352537246367e-01, 6.362440622506461e+00, 2.534631155079574e+05, -1.834976615100459e-12, 2.352196215582580e-11, 9.458211991386634e-11, -2.997694537043571e-09, 1.013785425363615e+05, 2.885879640720860e+02, 1.107636953341745e+01, 1.536753367006252e-02 +94, 1.217258964167516e-01, 1.951646785258570e-01, 1.223547827554396e+00, -7.638324920761816e-01, 2.968135199844550e+00, 2.532781832968114e+05, -4.038525069915977e-11, -4.497902050815128e-12, 9.627409980339507e-11, -1.949956640601158e-09, 1.013097379040184e+05, 2.884433871961465e+02, 1.373276550331735e+00, 7.357126719249530e-03 +95, -1.219004047400346e-01, 1.949408832841948e-01, 1.223967509879390e+00, 5.183493398005028e-01, 1.396280090038403e+00, 2.535005979774416e+05, 8.946177132429511e-13, 5.803912905832931e-12, -1.295252793909185e-11, -5.529727786779404e-10, 1.013998767166283e+05, 2.886010339201017e+02, 1.408499740914726e+01, 3.573064941808281e-03 +96, 2.523336268769782e+00, 8.167528709988477e-01, 1.223074561414927e+00, 5.953503786006601e-01, -8.705526105749370e-01, 2.532210751182096e+05, 2.220446049250313e-16, 7.008837954458613e-13, 1.458833054357456e-13, 2.910383045673370e-11, 1.012882481607568e+05, 2.884937916971869e+02, -1.657289415199713e+00, 2.532454898828083e-03 +97, -2.505449625832122e+00, 7.859658538255800e-01, 1.223761602242189e+00, 8.135925358548159e+00, 3.913764894644802e-01, 2.534645781547368e+05, -2.220446049250313e-16, 3.144151605738443e-13, 4.219402605087907e-13, 1.164153218269348e-10, 1.013749882256571e+05, 2.885787446097922e+02, 1.057512701411648e+01, 1.954479099202814e-02 +98, -2.060813475054502e+00, 3.451225315686373e+00, 1.223617497335771e+00, 1.014034785619874e+01, 3.142267635745736e-01, 2.534378803852676e+05, 4.440892098500626e-16, 2.646771690706373e-13, 8.443246102274315e-14, 8.731149137020111e-11, 1.013583290221515e+05, 2.885653019578898e+02, 8.225782280571773e+00, 2.434695701112650e-02 +99, 2.063560732056683e+00, 3.439799321923422e+00, 1.223106393712503e+00, 1.563105494603155e+01, 7.792542762894503e-01, 2.533551961505036e+05, -2.220446049250313e-16, -8.348877145181177e-14, -7.771561172376096e-15, -5.820766091346741e-11, 1.013020268151095e+05, 2.885255273894634e+02, 2.858292355855285e-01, 3.757699928815844e-02 +100, -1.839749246134713e-01, 7.462932951544454e-02, 1.223964737567087e+00, 9.338694174643483e-01, 4.865034780024067e-01, 2.534998794699485e+05, 2.498001805406602e-13, -1.840494423532846e-11, -5.467903907430127e-12, 4.365574568510056e-10, 1.013997706066612e+05, 2.886013856016052e+02, 1.407003337486557e+01, 2.526150411332199e-03 +101, 1.839180544321666e-01, 7.485312475710859e-02, 1.223545053349631e+00, -2.190419950643731e+00, 1.088105564058585e+00, 2.532780231718585e+05, -1.698796658899937e-11, -1.478892563966383e-10, 2.107758412250860e-12, -5.413312464952469e-09, 1.013102314684961e+05, 2.884454464504389e+02, 1.442880904821248e+00, 5.871098976752956e-03 +102, 2.223383454569839e+00, 3.988647227833714e-01, 1.223334761988542e+00, -3.518977985503417e+00, -6.499796625380193e-01, 2.532559112627847e+05, 1.598721155460225e-14, 1.016964290556643e-12, -7.638334409421077e-14, -2.910383045673370e-11, 1.013002709359581e+05, 2.884666662427073e+02, 3.820842731919191e-02, 8.591308942731806e-03 +103, -2.251468556888085e+00, 3.554419816404488e-01, 1.223756423345360e+00, 7.713826444879983e+00, 2.913000674642751e-01, 2.534626941231997e+05, 0.000000000000000e+00, 8.926193117986259e-13, 1.164901508587946e-13, 1.164153218269348e-10, 1.013753391142227e+05, 2.885809647254200e+02, 1.062461066459752e+01, 1.852258687200215e-02 +104, 2.464585334780322e+00, 1.408184623925035e+00, 1.223000661497174e+00, 6.908653750095108e+00, -6.171168494624276e-01, 2.532406462390118e+05, 4.440892098500626e-16, 3.446132268436486e-13, 1.252886683289489e-13, 8.731149137020111e-11, 1.012883909070810e+05, 2.885116305599308e+02, -1.637158781418635e+00, 1.665566462811873e-02 +105, 2.084360007171375e+00, 1.715536251696291e+00, 1.222988705901918e+00, 1.065007475893140e+01, -5.303929120522551e-02, 2.532671378975870e+05, -1.776356839400250e-15, 1.403321903126198e-13, 3.351763311343348e-13, 0.000000000000000e+00, 1.012883060252627e+05, 2.885142091876478e+02, -1.649129140777404e+00, 2.557426417442938e-02 +106, 2.062368340890224e+00, 2.119428018968443e+00, 1.223133201682298e+00, 1.385181744107948e+01, 7.342881576894630e-01, 2.533338612510900e+05, -1.776356839400250e-15, 1.403321903126198e-13, 3.351763311343348e-13, 0.000000000000000e+00, 1.013020823464768e+05, 2.885193618029004e+02, 2.936604818486953e-01, 3.330473818496230e-02 +107, 1.717455945079040e+00, 1.868364445049989e+00, 1.223121538345007e+00, 1.276353579550264e+01, 8.581444003432399e-01, 2.533165954259161e+05, -1.776356839400250e-15, 1.403321903126198e-13, 3.351763311343348e-13, 0.000000000000000e+00, 1.012998797080739e+05, 2.885158396271963e+02, -1.696402850059327e-02, 3.071475785142364e-02 +108, 1.703162076240365e+00, 1.478255337661386e+00, 1.223090386872932e+00, 8.853942700188229e+00, 1.141517084615438e-01, 2.532653544287227e+05, 1.998401444325282e-15, 7.345235530920036e-13, 1.295963336644945e-12, 1.746229827404022e-10, 1.012933209149453e+05, 2.885045071636865e+02, -9.419101755339616e-01, 2.126126496453044e-02 +109, 1.404436195019035e+00, 1.673942321767309e+00, 1.223063428808585e+00, 1.163556547946533e+01, 1.081797057349903e+00, 2.532865572538738e+05, -3.130828929442941e-14, -6.572520305780927e-13, 1.113553693699032e-12, 1.164153218269348e-10, 1.012922926338490e+05, 2.885079373913617e+02, -1.086922317167775e+00, 2.805948841207321e-02 +110, 1.379058826430465e+00, 2.011826412501079e+00, 1.223040561254015e+00, 1.426844795745985e+01, 1.795034237262723e+00, 2.533195440345286e+05, -1.065814103640150e-14, -3.623767952376511e-13, 2.033928581113287e-13, -5.820766091346741e-11, 1.012939984974911e+05, 2.885181905638383e+02, -8.463548877321594e-01, 3.453108739366737e-02 +111, 1.122275365517278e+00, 1.805700073576171e+00, 1.223264906063177e+00, 1.337102582045578e+01, 2.106685533421965e+00, 2.533529985517566e+05, -4.707345624410664e-14, -1.101341240428155e-12, 2.242650509742816e-13, -8.731149137020111e-11, 1.013112431202284e+05, 2.885143860688435e+02, 1.585547909795852e+00, 3.249647477856155e-02 +112, 1.133470914060752e+00, 1.514067169569643e+00, 1.222969901173794e+00, 1.037915830120766e+01, 1.469290821106409e+00, 2.532475419727753e+05, -3.130828929442941e-14, -6.572520305780927e-13, 1.113553693699032e-12, 1.164153218269348e-10, 1.012810464788918e+05, 2.884979667236179e+02, -2.672898196044694e+00, 2.517298293994588e-02 +113, 8.972873959942533e-01, 1.623761999273238e+00, 1.222978630264354e+00, 1.211355044661315e+01, 2.479966711613957e+00, 2.532777485284729e+05, 1.729727472365994e-13, -3.856470698337944e-12, 3.357314426466473e-12, 2.910383045673370e-10, 1.012860967931046e+05, 2.885102932131657e+02, -1.960683527771214e+00, 2.969195624980021e-02 +114, 9.058741208622765e-01, 1.383675780550798e+00, 1.223016874440074e+00, 8.881559691320557e+00, 1.993860752421350e+00, 2.532351235139387e+05, 1.729727472365994e-13, -3.856470698337944e-12, 3.357314426466473e-12, 2.910383045673370e-10, 1.012804997015636e+05, 2.884853287505160e+02, -2.750006830682175e+00, 2.185863160674720e-02 +115, 6.842001226671564e-01, 1.452796046264117e+00, 1.223175199343134e+00, 1.040848664285766e+01, 2.969815215875337e+00, 2.532989090976426e+05, 1.729727472365994e-13, -3.856470698337944e-12, 3.357314426466473e-12, 2.910383045673370e-10, 1.013004075285221e+05, 2.885046856045448e+02, 5.747123425118515e-02, 2.598777244019490e-02 +116, 6.646868037142452e-01, 1.702928282639411e+00, 1.222923572901489e+00, 1.331937892404309e+01, 3.555729514805805e+00, 2.532943808264264e+05, 1.729727472365994e-13, -3.856470698337944e-12, 3.357314426466473e-12, 2.910383045673370e-10, 1.012866712276274e+05, 2.885249185960691e+02, -1.879674569538184e+00, 3.310495836658905e-02 +117, 4.770905360411068e-01, 1.555424094371977e+00, 1.223212228370681e+00, 1.223659073404961e+01, 4.136960142827821e+00, 2.533495326313635e+05, 6.001865671123596e-13, -4.394706820676220e-12, -1.468158927764307e-12, -1.018634065985680e-09, 1.013125326529310e+05, 2.885304834468125e+02, 1.767402754331934e+00, 3.101092796124330e-02 +118, 4.540791467468551e-01, 1.782959503762570e+00, 1.223140403949195e+00, 1.388503202572376e+01, 4.474896281198897e+00, 2.533574370575204e+05, 1.088018564132653e-14, -1.497468815614411e-12, -1.857181075592962e-12, -1.746229827404022e-10, 1.013081760688511e+05, 2.885350183854251e+02, 1.153020568480966e+00, 3.502519678792024e-02 +119, 2.815546078401769e-01, 1.663644338896494e+00, 1.223244850240297e+00, 1.328877171100090e+01, 5.100040822935667e+00, 2.533781007636370e+05, -5.129230373768223e-14, -8.082423619271140e-13, -2.394529019511538e-12, -6.111804395914078e-10, 1.013181149879939e+05, 2.885386864742008e+02, 2.554645042158733e+00, 3.417098189083641e-02 +120, 2.468385344486442e-01, 1.874144764255479e+00, 1.223199672429255e+00, 1.377399568628848e+01, 4.863412706656640e+00, 2.533728158617640e+05, -5.129230373768223e-14, -8.082423619271140e-13, -2.394529019511538e-12, -6.111804395914078e-10, 1.013142382156240e+05, 2.885383025285963e+02, 2.007927742779465e+00, 3.506909696945337e-02 +121, 8.495255255236976e-02, 1.739613249766467e+00, 1.223240571526339e+00, 1.311061728528103e+01, 5.583396520740954e+00, 2.533788025049799e+05, -5.129230373768223e-14, -8.082423619271140e-13, -2.394529019511538e-12, -6.111804395914078e-10, 1.013183202388656e+05, 2.885402802652217e+02, 2.583590306814401e+00, 3.420983873415286e-02 +122, 3.220583930626938e-02, 1.963776890424456e+00, 1.223467327728925e+00, 1.298920702313592e+01, 4.656330355136823e+00, 2.534220656806991e+05, -1.498801083243961e-13, -3.588240815588506e-13, -9.610090501155355e-13, -1.455191522836685e-10, 1.013377014670395e+05, 2.885419872736221e+02, 5.316805392682933e+00, 3.311988200671466e-02 +123, -1.420447253181170e-01, 1.783980800848851e+00, 1.223347605863603e+00, 1.203625338830440e+01, 5.360616501768229e+00, 2.533942127697496e+05, -2.338129689860580e-13, 5.861977570020827e-14, -1.101341240428155e-12, -2.910383045673370e-10, 1.013293027243362e+05, 2.885463088465119e+02, 4.132382504045502e+00, 3.162844858035750e-02 +124, 7.288711212566362e-01, 1.245863903150906e+00, 1.223209183423684e+00, 7.071449552548317e+00, 2.381458330074001e+00, 2.532499472080986e+05, 7.263079027097774e-13, -4.449773882697627e-12, 1.301891927596444e-11, -2.910383045673370e-10, 1.012908754946602e+05, 2.884695235750350e+02, -1.286772717507432e+00, 1.791584771961238e-02 +125, 1.077857235892557e+00, 2.136340724706990e+00, 1.223022776157473e+00, 1.495365435938911e+01, 2.582269852872746e+00, 2.533301903463923e+05, -1.065814103640150e-14, -3.623767952376511e-13, 2.033928581113287e-13, -5.820766091346741e-11, 1.012944186393210e+05, 2.885235828893407e+02, -7.871048764636031e-01, 3.643795240137165e-02 +126, 2.551297964713150e-01, 2.138444957371775e+00, 1.223267023467836e+00, 1.368152815281458e+01, 4.027277965902226e+00, 2.533840556417271e+05, -1.079136779935652e-13, -4.209965709378594e-13, -8.713030297258229e-13, -1.746229827404022e-10, 1.013203665281362e+05, 2.885398682836744e+02, 2.872165863241888e+00, 3.423779928116884e-02 +127, 8.954242699595698e-01, 1.142526874339367e+00, 1.222998554341584e+00, 5.381884573952041e+00, 1.795202376246093e+00, 2.531856245063578e+05, -3.685940441755520e-14, 2.735589532676386e-13, 4.471756298585206e-12, 5.820766091346741e-10, 1.012689861114251e+05, 2.884568545929523e+02, -4.373697443929464e+00, 1.362473146920629e-02 +128, 7.229084912274972e-01, 1.059814071449071e+00, 1.223221034179612e+00, 4.203328756877213e+00, 2.419476023697204e+00, 2.532134153020286e+05, 1.296740492762183e-13, 6.381561945545400e-13, 1.117816950113593e-11, 6.402842700481415e-10, 1.012815202358552e+05, 2.884400859547474e+02, -2.606087173154499e+00, 1.164538961188998e-02 +129, -2.030321336534212e-01, 2.067608555445848e+00, 1.223433062753504e+00, 1.198814527397334e+01, 3.965825819265275e+00, 2.534075002207239e+05, -1.498801083243961e-13, -3.588240815588506e-13, -9.610090501155355e-13, -1.455191522836685e-10, 1.013369351720480e+05, 2.885478865797682e+02, 5.208739535754274e+00, 3.030855759438236e-02 +130, -4.089796826970965e-01, 1.894293988032145e+00, 1.223532744436097e+00, 1.100714695578676e+01, 4.137403688105896e+00, 2.534248653603395e+05, -2.338129689860580e-13, 5.861977570020827e-14, -1.101341240428155e-12, -2.910383045673370e-10, 1.013473434971672e+05, 2.885540128357661e+02, 6.676561439464045e+00, 2.822243298620722e-02 +131, -3.445145036416716e-01, 1.614441837110963e+00, 1.223551010551464e+00, 1.061187112611882e+01, 5.568185929706598e+00, 2.534309504576045e+05, -2.338129689860580e-13, 5.861977570020827e-14, -1.101341240428155e-12, -2.910383045673370e-10, 1.013489048228636e+05, 2.885541503855277e+02, 6.896745573774981e+00, 2.876190095746690e-02 +132, -6.150362610797229e-01, 1.721607514830304e+00, 1.223496044730627e+00, 9.970634560532710e+00, 4.006487383315902e+00, 2.534140276937302e+05, -2.338129689860580e-13, 5.861977570020827e-14, -1.101341240428155e-12, -2.910383045673370e-10, 1.013467363953564e+05, 2.885609396561700e+02, 6.590945615066212e+00, 2.579027206599301e-02 +133, -5.614455783408865e-01, 1.469072776422268e+00, 1.223649174552302e+00, 9.225226077326084e+00, 4.865829915528373e+00, 2.534453391225810e+05, -2.104982854689297e-13, 4.991562718714704e-13, -8.881784197001252e-15, -2.910383045673370e-10, 1.013603558639098e+05, 2.885636019558789e+02, 8.511615274267903e+00, 2.502938479114575e-02 +134, -8.152712794659158e-01, 1.551780103823788e+00, 1.223701146980932e+00, 9.103937650304271e+00, 3.559073919915126e+00, 2.534542106839838e+05, -2.104982854689297e-13, 4.991562718714704e-13, -8.881784197001252e-15, -2.910383045673370e-10, 1.013660679299881e+05, 2.885676072612078e+02, 9.317152727129056e+00, 2.345656221048292e-02 +135, -8.412689611033113e-01, 1.795758041769261e+00, 1.223596708437095e+00, 9.685450404932840e+00, 3.082257475134095e+00, 2.534332967938614e+05, 2.509104035652854e-14, 1.046274178406748e-12, -1.176836406102666e-13, -2.910383045673370e-11, 1.013564327190817e+05, 2.885648058484017e+02, 7.958358353074995e+00, 2.439263394921628e-02 +136, -7.621667971560324e-01, 1.289715022252111e+00, 1.223702613011195e+00, 8.133979061817044e+00, 4.029616200518537e+00, 2.534531243766417e+05, -2.104982854689297e-13, 4.991562718714704e-13, -8.881784197001252e-15, -2.910383045673370e-10, 1.013677825207553e+05, 2.885721426179778e+02, 9.558950889199060e+00, 2.178262165864529e-02 +137, -1.026165735795321e+00, 1.376678594632030e+00, 1.223681569454032e+00, 8.425788418020653e+00, 2.918186915268143e+00, 2.534488294132545e+05, -2.104982854689297e-13, 4.991562718714704e-13, -8.881784197001252e-15, -2.910383045673370e-10, 1.013665365993497e+05, 2.885735582411201e+02, 9.383246276930015e+00, 2.139757686891767e-02 +138, 5.786314857088577e-01, 1.133180962863563e+00, 1.223295627383238e+00, 5.117140534321930e+00, 2.850986620280346e+00, 2.532462015808033e+05, 7.263079027097774e-13, -4.449773882697627e-12, 1.301891927596444e-11, -2.910383045673370e-10, 1.012928706634489e+05, 2.884548206329082e+02, -1.005406367386459e+00, 1.406409432412194e-02 +139, 5.729768582378089e-01, 9.679372228709939e-01, 1.223295060305510e+00, 2.750954169475162e+00, 3.139730668737799e+00, 2.532145073649903e+05, 9.552358903874847e-13, 2.050981606771529e-11, 1.596500709410975e-12, 1.979060471057892e-09, 1.012829539755260e+05, 2.884267142806520e+02, -2.403895709202023e+00, 1.002297803336094e-02 +140, 7.172900438489473e-01, 8.817741672289483e-01, 1.223335987863955e+00, 1.917467678318542e+00, 2.597206250773087e+00, 2.532174975880213e+05, 1.296740492762183e-13, 6.381561945545400e-13, 1.117816950113593e-11, 6.402842700481415e-10, 1.012852951431119e+05, 2.884237315587418e+02, -2.073735282491002e+00, 7.751197977789346e-03 +141, -4.706077298431066e-01, 2.183860243462431e+00, 1.223552311741529e+00, 1.118015676038229e+01, 3.082696204971045e+00, 2.534275293823373e+05, -6.661338147750939e-16, 4.032330025438569e-13, -7.260858581048524e-13, -2.037268131971359e-10, 1.013490267638522e+05, 2.885541907040754e+02, 6.913942159379752e+00, 2.783391650823615e-02 +142, 5.679375225064280e-01, 7.985284675323945e-01, 1.223378915238331e+00, 1.014361660761420e+00, 3.336197230177695e+00, 2.532196314056328e+05, 4.045652701734070e-13, 1.464961485453387e-11, -2.183142555622908e-12, 1.455191522836685e-09, 1.012858647657681e+05, 2.884152330253270e+02, -1.993404912124021e+00, 8.372063684791285e-03 +143, 1.228545897275954e-01, 1.518204411007442e+00, 1.223238692233775e+00, 1.254901420263509e+01, 5.805334136193674e+00, 2.533748746420525e+05, 2.648326002940848e-12, -6.021849685566849e-13, 4.043876344894670e-12, -3.492459654808044e-10, 1.013186919080487e+05, 2.885417820199750e+02, 2.636004519624175e+00, 3.319375886971936e-02 +144, 2.279691104226475e-02, 1.047289318951331e+00, 1.222600331890601e+00, 4.244303824298967e+00, 1.384452579001388e+00, 2.531783265542671e+05, -7.941602930827685e-11, 4.675237974538504e-11, -1.106572611320189e-10, -6.402842700481415e-10, 1.012680702228052e+05, 2.885482003810811e+02, -4.502859567740473e+00, 1.072309334032684e-02 +145, 8.320520847035189e-02, 1.041062627419661e+00, 1.222414441408251e+00, 2.290636169249627e+00, 1.911718193649013e+00, 2.531030914845985e+05, -7.941602930827685e-11, 4.675237974538504e-11, -1.106572611320189e-10, -6.402842700481415e-10, 1.012397801842601e+05, 2.885114589283930e+02, -8.492429239870997e+00, 7.167820994696240e-03 +146, 5.033468097355830e-02, 1.101912704021267e+00, 1.222782706533651e+00, 5.729493818650133e+00, 2.931833966767532e+00, 2.532257594260783e+05, 1.743938327081196e-12, 3.372235823917435e-11, 3.684608174125970e-11, 4.132743924856186e-09, 1.012835286092182e+05, 2.885492040064286e+02, -2.322858663348993e+00, 1.545650823021496e-02 +147, 1.219691092352662e-01, 1.104508613472716e+00, 1.223153665511836e+00, 4.380128915102540e+00, 2.805408092240319e+00, 2.532719451560307e+05, -9.706901948902669e-12, 3.870015419238371e-11, -1.913447178480965e-11, 3.870809450745583e-09, 1.013043541139518e+05, 2.885210048963195e+02, 6.140338389295282e-01, 1.248854829657348e-02 +148, -2.270250029283606e-01, 2.375087425618713e+00, 1.223426066559938e+00, 1.199215706896613e+01, 2.872823195761975e+00, 2.534038197513637e+05, -2.486899575160351e-14, -2.486899575160351e-13, -4.964917366123700e-13, -8.731149137020111e-11, 1.013366690311071e+05, 2.885487788313806e+02, 5.171207320132008e+00, 2.959908995876041e-02 +149, -9.617589588715749e-01, 1.108784078846753e+00, 1.223746136958774e+00, 7.522959557957561e+00, 3.017291276480250e+00, 2.534607941874953e+05, -9.148237722911290e-14, -1.048050535246148e-13, 1.509903313490213e-12, 1.455191522836685e-10, 1.013735803226709e+05, 2.885783837162545e+02, 1.037657913847482e+01, 1.944944413435184e-02 +150, -1.245186884247811e+00, 1.191051459180861e+00, 1.223745652201467e+00, 7.974783114671674e+00, 2.285988836127629e+00, 2.534613591337824e+05, 1.065814103640150e-14, 6.039613253960852e-13, 3.224087663511455e-13, -5.820766091346741e-11, 1.013732957425502e+05, 2.885776879200839e+02, 1.033644655904603e+01, 1.990651045089005e-02 +151, -7.079931238432895e-01, 1.027578520420090e+00, 1.223805725303890e+00, 6.860509325349530e+00, 4.120704762503681e+00, 2.534725814091700e+05, -9.148237722911290e-14, -1.048050535246148e-13, 1.509903313490213e-12, 1.455191522836685e-10, 1.013785657396258e+05, 2.885785237488545e+02, 1.107964174669341e+01, 1.920239392041211e-02 +152, -9.221294756512569e-01, 8.266544364717542e-01, 1.223796252385997e+00, 6.450030782429589e+00, 2.720220435865398e+00, 2.534694738569376e+05, -9.148237722911290e-14, -1.048050535246148e-13, 1.509903313490213e-12, 1.455191522836685e-10, 1.013797812658714e+05, 2.885842175953548e+02, 1.125105991698659e+01, 1.679634745802295e-02 +153, -6.775201745578521e-01, 7.984571876326989e-01, 1.223827491121206e+00, 5.618674108861084e+00, 3.607436909961445e+00, 2.534751689004165e+05, -1.549871342376719e-13, 4.947153797729698e-13, 1.068034549689401e-12, -6.693881005048752e-10, 1.013827817130804e+05, 2.885853921086015e+02, 1.167419448320247e+01, 1.602060485762452e-02 +154, -1.312202388587856e+00, 1.494831781495654e+00, 1.223701627726749e+00, 8.668366369314160e+00, 2.183117426376279e+00, 2.534533463295181e+05, 3.108624468950438e-15, 6.092903959142859e-13, 1.361133428190442e-13, -1.164153218269348e-10, 1.013682787179769e+05, 2.885737875340682e+02, 9.628926523324347e+00, 2.145055045465125e-02 +155, 7.101722960520571e-01, 7.094472459229380e-01, 1.223266830692221e+00, 2.164375399861330e-02, 2.569854661829309e+00, 2.531992349995270e+05, 4.045652701734070e-13, 1.464961485453387e-11, -2.183142555622908e-12, 1.455191522836685e-09, 1.012786141664875e+05, 2.884210114725525e+02, -3.015912214422197e+00, 6.170785808008380e-03 +156, 8.684596806079874e-01, 7.881515540614404e-01, 1.223108516357945e+00, 7.954913057955147e-01, 1.870813402042371e+00, 2.531744060424806e+05, -2.864375403532904e-13, 4.761468996861140e-12, 7.106537580625627e-12, 5.529727786779404e-10, 1.012690866389811e+05, 2.884312075653281e+02, -4.359520662659212e+00, 4.881851515825535e-03 +157, 5.583553281419923e-01, 6.419675377813394e-01, 1.223364815639761e+00, -3.925371152047123e-01, 3.189107591376050e+00, 2.532180428627847e+05, 4.045652701734070e-13, 1.464961485453387e-11, -2.183142555622908e-12, 1.455191522836685e-09, 1.012855292606032e+05, 2.884176017117766e+02, -2.040719136484679e+00, 7.714692981693909e-03 +158, -3.558236263487662e-01, 1.362627108302694e+00, 1.223547558284065e+00, 9.423519477726984e+00, 6.801435742516096e+00, 2.534295787599088e+05, 1.139088823265411e-13, 2.895461648222408e-13, -3.487876654162392e-12, 7.566995918750763e-10, 1.013497543486307e+05, 2.885573832701691e+02, 7.016548953699367e+00, 2.789209853591327e-02 +159, 1.348529036501956e+00, 2.364475593243117e+00, 1.223195139981248e+00, 1.536957051053784e+01, 2.048694524031208e+00, 2.533707863096756e+05, -1.065814103640150e-14, -3.623767952376511e-13, 2.033928581113287e-13, -5.820766091346741e-11, 1.013090042226643e+05, 2.885244654562464e+02, 1.269809993561105e+00, 3.722632347236482e-02 +160, -2.630234157565177e-02, 1.090301567367884e+00, 1.222325955165377e+00, 7.571379311239252e+00, 5.811734292458228e+00, 2.531617331674771e+05, 1.743938327081196e-12, 3.372235823917435e-11, 3.684608174125970e-11, 4.132743924856186e-09, 1.012497869255561e+05, 2.885608638717925e+02, -7.081240226184796e+00, 2.293028526888340e-02 +161, 1.117829397432080e-02, 1.167717052011154e+00, 1.223127938797662e+00, 8.748473602002344e+00, 5.579787828466275e+00, 2.533311115795474e+05, 1.743938327081196e-12, 3.372235823917435e-11, 3.684608174125970e-11, 4.132743924856186e-09, 1.013148389800861e+05, 2.885569356842906e+02, 2.092649849969431e+00, 2.491210974100199e-02 +162, 1.571133394729228e-01, 1.029942657862055e+00, 1.223253189327440e+00, 2.068606550666488e+00, 3.136620198433441e+00, 2.532461117249591e+05, -9.706901948902669e-12, 3.870015419238371e-11, -1.913447178480965e-11, 3.870809450745583e-09, 1.012961364974600e+05, 2.884741284715425e+02, -5.448459371074605e-01, 9.021122050869097e-03 +163, 2.071369935753511e-01, 1.104064697813123e+00, 1.223143976159958e+00, 4.060853582891020e+00, 3.401776847318429e+00, 2.532422192661443e+05, -9.706901948902669e-12, 3.870015419238371e-11, -1.913447178480965e-11, 3.870809450745583e-09, 1.012922991023215e+05, 2.884889567832066e+02, -1.086010108372717e+00, 1.271958863782125e-02 +164, 1.597518876437562e-01, 1.182733926626084e+00, 1.222880126406504e+00, 6.866944895857077e+00, 3.752781475204316e+00, 2.532361295592865e+05, 3.690381333854020e-12, 7.325695605686633e-12, 2.441069568703824e-11, -1.309672370553017e-09, 1.012844364019768e+05, 2.885288029676444e+02, -2.194838248929631e+00, 1.879248651378112e-02 +165, 2.496705213675713e-01, 1.015521401385580e+00, 1.223367911101766e+00, 2.336518205050595e+00, 3.788095672197513e+00, 2.532468166051912e+05, -9.706901948902669e-12, 3.870015419238371e-11, -1.913447178480965e-11, 3.870809450745583e-09, 1.012954882072664e+05, 2.884452306575708e+02, -6.362703051247489e-01, 1.068546713536184e-02 +166, 8.544827103668783e-01, 6.108495908208534e-01, 1.223277106775767e+00, -1.382798843451995e+00, 1.672038611945468e+00, 2.532090094522318e+05, -2.864375403532904e-13, 4.761468996861140e-12, 7.106537580625627e-12, 5.529727786779404e-10, 1.012828340704591e+05, 2.884306059371633e+02, -2.420805181341125e+00, 5.209748382866398e-03 +167, 1.047555138763969e+00, 6.998654549675014e-01, 1.223187655075057e+00, -6.077691456343656e-01, 9.317625522610724e-01, 2.531997101275738e+05, -2.864375403532904e-13, 4.761468996861140e-12, 7.106537580625627e-12, 5.529727786779404e-10, 1.012796817002646e+05, 2.884427209705277e+02, -2.865364509293685e+00, 2.671235917675980e-03 +168, -7.847309697407640e-02, 1.158032711170834e+00, 1.222990123241424e+00, 9.252913372129365e+00, 8.435055332288133e+00, 2.533194948532250e+05, 1.743938327081196e-12, 3.372235823917435e-11, 3.684608174125970e-11, 4.132743924856186e-09, 1.013021613377963e+05, 2.885533408801857e+02, 3.048001405072258e-01, 3.006366143086141e-02 +169, -5.171347807433394e-01, 9.204151529388280e-01, 1.223789983079576e+00, 5.665710225861378e+00, 5.158109396889729e+00, 2.534689287143416e+05, 1.310063169057685e-14, 1.474376176702208e-12, -1.637801005927031e-11, 3.492459654808044e-10, 1.013779772962555e+05, 2.885805608277842e+02, 1.099665720709553e+01, 1.838456333377446e-02 +170, -4.863658484551759e-01, 7.410580809794332e-01, 1.223793491894556e+00, 4.441476788712112e+00, 4.408034955563267e+00, 2.534675267515137e+05, 1.310063169057685e-14, 1.474376176702208e-12, -1.637801005927031e-11, 3.492459654808044e-10, 1.013806113385410e+05, 2.885872314119650e+02, 1.136811994654567e+01, 1.501453451749251e-02 +171, -6.210221496382942e-01, 6.162068906991468e-01, 1.223860092091709e+00, 4.634659100515317e+00, 3.100624857515649e+00, 2.534805675849271e+05, -1.549871342376719e-13, 4.947153797729698e-13, 1.068034549689401e-12, -6.693881005048752e-10, 1.013871457440937e+05, 2.885901266749544e+02, 1.228962686414676e+01, 1.337878028308510e-02 +172, -4.304165203637109e-01, 5.790980463991446e-01, 1.223844502944215e+00, 3.402339699306582e+00, 3.597478737034153e+00, 2.534765241126198e+05, -1.016964290556643e-13, 3.896882816434299e-12, -3.108624468950438e-12, -8.149072527885437e-10, 1.013866029646839e+05, 2.885922576962631e+02, 1.221308203128724e+01, 1.188018072135322e-02 +173, -1.561645375245433e+00, 1.283922173949084e+00, 1.223706435256561e+00, 8.301140270164712e+00, 1.698944408089978e+00, 2.534536856952889e+05, 1.065814103640150e-14, 6.039613253960852e-13, 3.224087663511455e-13, -5.820766091346741e-11, 1.013697401987942e+05, 2.885768143316494e+02, 9.835030150075424e+00, 2.033252558466253e-02 +174, 2.721982469121679e-01, 1.192937096600493e+00, 1.223011376998610e+00, 6.387515342284970e+00, 3.575347326342366e+00, 2.532396529870646e+05, 1.354472090042691e-12, 1.073985345101391e-11, 1.641531355289771e-11, 3.230525180697441e-09, 1.012870986498881e+05, 2.885054218888749e+02, -1.819397844020304e+00, 1.757757857236323e-02 +175, -5.279950742000670e-01, 2.507900149576392e+00, 1.223506603484608e+00, 1.128666910298955e+01, 2.220254067707113e+00, 2.534175709101599e+05, 7.771561172376096e-15, 3.925748615074554e-13, -3.519406988061746e-13, -5.820766091346741e-11, 1.013453989871258e+05, 2.885546414789500e+02, 6.402339180056404e+00, 2.760838296294697e-02 +176, -2.485215532191837e-01, 2.731250297044676e+00, 1.223482942799100e+00, 1.197451982413432e+01, 1.935930885297548e+00, 2.534144637676896e+05, 3.774758283725532e-15, 3.907985046680551e-14, -2.684519273543629e-13, 0.000000000000000e+00, 1.013417333608195e+05, 2.885497846594230e+02, 5.885398507904057e+00, 2.911412472746918e-02 +177, 4.318698220099755e-01, 7.203269979419185e-01, 1.223486626509749e+00, 4.587433391071883e-01, 3.952428013064955e+00, 2.532405750247969e+05, 5.078604203845316e-12, 3.287115024619425e-11, -5.817657466877790e-11, 2.677552402019501e-09, 1.012936419746584e+05, 2.884119859462453e+02, -8.966331041561404e-01, 9.552454674623781e-03 +178, 4.233758145620952e-01, 5.725090652495957e-01, 1.223415409010843e+00, -5.883923237734842e-01, 3.675219265847030e+00, 2.532320119918334e+05, 2.074118654604717e-12, 2.376188135144730e-11, -3.356426248046773e-11, 1.979060471057892e-09, 1.012905400807462e+05, 2.884199425006981e+02, -1.334074073310452e+00, 8.936005221531481e-03 +179, -3.335264779592149e-02, 1.251950363545254e+00, 1.223126451958472e+00, 1.054384432434869e+01, 7.446347621871450e+00, 2.533491523550271e+05, 5.723865825757457e-12, 2.428279799460142e-12, 1.374367286643974e-11, -1.455191522836685e-09, 1.013124158855778e+05, 2.885503851805699e+02, 1.750935774610651e+00, 3.099085117215360e-02 +180, 5.424961911931495e-01, 4.927148811222654e-01, 1.223355833995674e+00, -1.641743919957167e+00, 2.822621491171842e+00, 2.532231859627123e+05, 2.074118654604717e-12, 2.376188135144730e-11, -3.356426248046773e-11, 1.979060471057892e-09, 1.012875312266538e+05, 2.884254199982067e+02, -1.758394210434434e+00, 7.839916222270468e-03 +181, 4.112126129078422e-01, 4.303539620537629e-01, 1.223412057857352e+00, -1.577482511015410e+00, 3.202863408580643e+00, 2.532392916085375e+05, 2.074118654604717e-12, 2.376188135144730e-11, -3.356426248046773e-11, 1.979060471057892e-09, 1.012936328344473e+05, 2.884295390282167e+02, -8.979220917641502e-01, 8.571540117435317e-03 +182, 1.018241381731687e+00, 2.500118167976530e+00, 1.223266909649696e+00, 1.514675118749787e+01, 2.446831862689911e+00, 2.533878142301998e+05, -1.065814103640150e-14, -3.623767952376511e-13, 2.033928581113287e-13, -5.820766091346741e-11, 1.013166367808140e+05, 2.885292735652763e+02, 2.346182599630046e+00, 3.683396024946278e-02 +183, -1.633551517174799e+00, 1.628891394038448e+00, 1.223687667724547e+00, 8.859231444644214e+00, 1.592691356176972e+00, 2.534506536395797e+05, 3.108624468950438e-15, 6.092903959142859e-13, 1.361133428190442e-13, -1.164153218269348e-10, 1.013670190820329e+05, 2.885734936699366e+02, 9.451287834283001e+00, 2.160009036545867e-02 +184, 1.309393265514833e+00, 2.745135355921620e+00, 1.223140385813775e+00, 1.528958250379056e+01, 1.854517648912479e+00, 2.533618508704632e+05, -2.220446049250313e-16, -2.540190280342358e-13, 5.329070518200751e-14, -5.820766091346741e-11, 1.013059532111401e+05, 2.885286917598803e+02, 8.395446537973129e-01, 3.697833589000147e-02 +185, 5.177840774687827e-01, 3.509865812084266e-01, 1.223454155307852e+00, -2.769088966537071e+00, 2.266782555355132e+00, 2.532509283060605e+05, 2.382760655450511e-12, 1.601296872877356e-11, -2.550160083103492e-11, 2.444721758365631e-09, 1.012982778795596e+05, 2.884328406703546e+02, -2.428600254414016e-01, 8.591134325040849e-03 +186, 1.029849935373504e+00, 4.328609144905191e-01, 1.223115881630507e+00, -3.537165489750328e+00, 7.040867255183213e-01, 2.531872040204213e+05, -4.669598041573408e-13, 1.236211133459619e-11, -3.220534949832654e-12, 1.164153218269348e-10, 1.012727546996696e+05, 2.884399178949271e+02, -3.842236684589674e+00, 8.660621843135579e-03 +187, -1.477415711000033e+00, 9.899497318244764e-01, 1.223767063155210e+00, 7.688805814079272e+00, 1.668524597690950e+00, 2.534652372025359e+05, 1.065814103640150e-14, 6.039613253960852e-13, 3.224087663511455e-13, -5.820766091346741e-11, 1.013759782973861e+05, 2.885802752334658e+02, 1.071475072430638e+01, 1.887862644892159e-02 +188, -5.601504263292794e-01, 4.553761410494602e-01, 1.223892600125479e+00, 3.867710296680378e+00, 2.465050241249837e+00, 2.534863617037210e+05, -1.016964290556643e-13, 3.896882816434299e-12, -3.108624468950438e-12, -8.149072527885437e-10, 1.013911071812324e+05, 2.885937369838981e+02, 1.284828391375506e+01, 1.100379323233913e-02 +189, -7.270539287649238e-01, 4.819427585024506e-01, 1.223900543488208e+00, 4.710590223461862e+00, 2.144616440395087e+00, 2.534887309704796e+05, 4.085620730620576e-14, -4.627409566637652e-13, 3.983036123145212e-12, 8.731149137020111e-11, 1.013911147383783e+05, 2.885918854620993e+02, 1.284934965143485e+01, 1.241771088482229e-02 +190, -4.090902420275128e-01, 4.203457284590574e-01, 1.223916443803127e+00, 2.873620232989534e+00, 2.592055837089475e+00, 2.534906337879968e+05, -1.016964290556643e-13, 3.896882816434299e-12, -3.108624468950438e-12, -8.149072527885437e-10, 1.013938062163194e+05, 2.885957969834010e+02, 1.322891218720080e+01, 9.284505478582188e-03 +191, -3.522791235847302e-01, 8.700652946529656e-01, 1.223810261541307e+00, 4.170447462808806e+00, 6.434603551558981e+00, 2.534739566933966e+05, 1.310063169057685e-14, 1.474376176702208e-12, -1.637801005927031e-11, 3.492459654808044e-10, 1.013799738749562e+05, 2.885814623929887e+02, 1.127822238841121e+01, 1.839837761005817e-02 +192, -3.889332458633063e-01, 1.027066376143749e+00, 1.223687986990472e+00, 5.944731110428177e+00, 7.137954775835907e+00, 2.534519235113518e+05, 1.310063169057685e-14, 1.474376176702208e-12, -1.637801005927031e-11, 3.492459654808044e-10, 1.013666660992416e+05, 2.885724135021230e+02, 9.401508848054767e+00, 2.229122094449538e-02 +193, -1.995353373029602e+00, 1.406582575650807e+00, 1.223723123273659e+00, 8.551419429492316e+00, 1.118039403095051e+00, 2.534573517411934e+05, -4.440892098500626e-16, 2.664535259100376e-13, 2.009503674571533e-14, 5.820766091346741e-11, 1.013707848770846e+05, 2.885758529081003e+02, 9.982354686877269e+00, 2.069458392931223e-02 +194, 3.058598464504097e-01, 6.525575555187799e-01, 1.223453134287036e+00, 1.907324308534171e-01, 4.383220585691741e+00, 2.532373568542259e+05, 5.078604203845316e-12, 3.287115024619425e-11, -5.817657466877790e-11, 2.677552402019501e-09, 1.012917960741109e+05, 2.884146253189163e+02, -1.156949074752885e+00, 1.053317454961366e-02 +195, 3.242700014127765e-01, 7.890325527887988e-01, 1.223478925577931e+00, 9.561997909041141e-01, 4.424135489084544e+00, 2.532377470588633e+05, 5.078604203845316e-12, 3.287115024619425e-11, -5.817657466877790e-11, 2.677552402019501e-09, 1.012917498009447e+05, 2.884084137011197e+02, -1.163474694026628e+00, 1.086658262931658e-02 +196, 6.642582024938881e-01, 4.078662111765557e-01, 1.223298859063736e+00, -2.891229597768347e+00, 1.937322071756333e+00, 2.532168142495384e+05, -4.669598041573408e-13, 1.236211133459619e-11, -3.220534949832654e-12, 1.164153218269348e-10, 1.012847454109747e+05, 2.884309201300959e+02, -2.151260615608579e+00, 8.356284814525302e-03 +197, -3.050954973077148e-01, 5.085933240950496e-01, 1.223947932663415e+00, 2.314995524369598e+00, 3.446945553849801e+00, 2.534971745199068e+05, -2.378097718747085e-13, 1.745470434855179e-11, -1.421129880441185e-11, 5.529727786779404e-10, 1.013960525904212e+05, 2.885947658556087e+02, 1.354570447344072e+01, 9.961406255760275e-03 +198, 6.073746695537923e-01, 1.962519239688037e+00, 1.223328207099454e+00, 1.445484852575908e+01, 3.822396560346133e+00, 2.533991992312185e+05, 1.088018564132653e-14, -1.497468815614411e-12, -1.857181075592962e-12, -1.746229827404022e-10, 1.013231313058697e+05, 2.885333103612062e+02, 3.262065416676656e+00, 3.589225859546610e-02 +199, 1.224428718576002e+00, 6.011520172932576e-01, 1.223073435443254e+00, -1.914037802452994e+00, 2.222080137325875e-01, 2.531834349648645e+05, -3.641531520770513e-14, 2.678302024605728e-12, 6.171729793891245e-13, 6.111804395914078e-10, 1.012727668405360e+05, 2.884499626465614e+02, -3.840524533067777e+00, 4.627229122493397e-03 +200, 1.250183707851625e+00, 8.250911191047126e-01, 1.223201544044743e+00, 8.431143173069331e-01, 3.047251400540758e-01, 2.532165946766271e+05, -3.685940441755520e-14, 2.735589532676386e-13, 4.471756298585206e-12, 5.820766091346741e-10, 1.012865064615357e+05, 2.884588823947929e+02, -1.902910515349991e+00, 2.152573224971589e-03 +201, 1.457536437954968e+00, 6.770895640547033e-01, 1.222982697215760e+00, -1.114383987335182e+00, -2.081535899776307e-01, 2.531750701349643e+05, -3.641531520770513e-14, 2.678302024605728e-12, 6.171729793891245e-13, 6.111804395914078e-10, 1.012698178826413e+05, 2.884629639750642e+02, -4.256397878819438e+00, 2.722498950331104e-03 +202, 1.491338168940908e+00, 9.566090442564132e-01, 1.222988052271887e+00, 2.341189312119818e+00, -2.405537838406852e-01, 2.531897737952660e+05, 1.754152378907747e-14, 1.334043986389588e-12, 1.635802604482706e-12, 4.365574568510056e-10, 1.012750036983794e+05, 2.884764724129793e+02, -3.525074266057901e+00, 5.651851439057600e-03 +203, 1.773625119394877e+00, 8.129377661713433e-01, 1.223078780189859e+00, 5.032479268605365e-01, -7.452121418700741e-01, 2.532093774004747e+05, 1.754152378907747e-14, 1.334043986389588e-12, 1.635802604482706e-12, 4.365574568510056e-10, 1.012836187365547e+05, 2.884796109024325e+02, -2.310148560901108e+00, 2.159264904055244e-03 +204, 2.073827885059466e-01, 1.286702088478706e+00, 1.223017166471504e+00, 9.335388735188303e+00, 4.327979408916120e+00, 2.532883136973671e+05, 3.690381333854020e-12, 7.325695605686633e-12, 2.441069568703824e-11, -1.309672370553017e-09, 1.012980107769943e+05, 2.885351380476291e+02, -2.805278530048723e-01, 2.470745629984608e-02 +205, 3.329951734218924e-01, 1.291809694684708e+00, 1.222997784351271e+00, 8.891548935678324e+00, 3.773837352767785e+00, 2.532682790897891e+05, 1.810551708558705e-12, -7.689848757763684e-12, 9.936496070395151e-12, -3.783497959375381e-10, 1.012920538011044e+05, 2.885227427700063e+02, -1.120603426261073e+00, 2.319421882513623e-02 +206, -5.121868363353708e-01, 3.061386653791769e-01, 1.223970703664590e+00, 3.264720565358203e+00, 1.736732329035828e+00, 2.535019243125866e+05, 7.283063041541027e-14, 4.791722574282176e-13, 3.598676912019982e-12, -2.328306436538696e-10, 1.013985352533252e+05, 2.885964628356306e+02, 1.389581911227918e+01, 8.871408423178798e-03 +207, -5.380611626941773e-01, 1.261513802504850e+00, 1.223634946207487e+00, 8.110119158939076e+00, 5.492958339646279e+00, 2.534408650825605e+05, 1.139088823265411e-13, 2.895461648222408e-13, -3.487876654162392e-12, 7.566995918750763e-10, 1.013606638028965e+05, 2.885678340381651e+02, 8.555042010511771e+00, 2.350661923560606e-02 +208, -7.924607737753986e-01, 2.286933038382841e+00, 1.223549679167087e+00, 1.058148762624935e+01, 2.346927036424900e+00, 2.534250407437995e+05, -6.661338147750939e-16, 4.032330025438569e-13, -7.260858581048524e-13, -2.037268131971359e-10, 1.013508138165909e+05, 2.885598995420614e+02, 7.165959186415868e+00, 2.601273612249283e-02 +209, -8.696866263323156e-01, 2.652326082461821e+00, 1.223536028645783e+00, 1.080422569393029e+01, 1.688230867879028e+00, 2.534226199586989e+05, 7.771561172376096e-15, 3.925748615074554e-13, -3.519406988061746e-13, -5.820766091346741e-11, 1.013495011269082e+05, 2.885593814417081e+02, 6.980838655795526e+00, 2.624512465211949e-02 +210, -1.158130598609815e+00, 2.423025941094124e+00, 1.223606398710237e+00, 1.020411436059703e+01, 1.750809527405559e+00, 2.534360916109501e+05, 5.107025913275720e-15, 5.844214001626824e-13, -2.113864638886298e-13, -2.910383045673370e-11, 1.013569164215374e+05, 2.885638976822557e+02, 8.026571927423536e+00, 2.484643603202778e-02 +211, -1.242245566303975e+00, 2.799469271362501e+00, 1.223576672291078e+00, 1.042247631298822e+01, 1.232144150061105e+00, 2.534303465518733e+05, -4.440892098500626e-16, 4.014566457044566e-13, -1.649791414592983e-13, -2.910383045673370e-11, 1.013541346502265e+05, 2.885629883373581e+02, 7.634275874564504e+00, 2.518746128337388e-02 +212, -1.611715627250874e+00, 2.457963492172043e+00, 1.223647267869039e+00, 9.826529720763169e+00, 1.230849962269588e+00, 2.534437181322378e+05, 0.000000000000000e+00, 4.352074256530614e-13, -3.130828929442941e-14, 1.164153218269348e-10, 1.013614571957768e+05, 2.885671869900844e+02, 8.666929315590099e+00, 2.376578131264785e-02 +213, -2.704601976619734e-01, 3.766037471832779e-01, 1.223944143902120e+00, 1.841375028143593e+00, 2.540018433544312e+00, 2.534959381542330e+05, 5.149214388211476e-13, 1.453082099089897e-11, -7.374101329560290e-12, 2.910383045673370e-10, 1.013967669602546e+05, 2.885976924656769e+02, 1.364644764554983e+01, 7.526492889470966e-03 +214, -1.427840104692362e-01, 1.240183338149669e+00, 1.223215229735281e+00, 9.958872879453720e+00, 8.857388075719761e+00, 2.533708513136693e+05, 6.312061984203865e-12, 1.282707273730921e-11, 7.775113886054896e-12, -9.895302355289459e-10, 1.013192969903261e+05, 2.885490397662383e+02, 2.721335541682036e+00, 3.199629107367254e-02 +215, -1.014268222518224e-01, 1.353311527901559e+00, 1.223459667969355e+00, 1.115494611890374e+01, 7.892591341500652e+00, 2.534230815342492e+05, 5.723865825757457e-12, 2.428279799460142e-12, 1.374367286643974e-11, -1.455191522836685e-09, 1.013387083837821e+05, 2.885466608024915e+02, 5.458804651267949e+00, 3.279862671200125e-02 +216, -1.763545657120722e-01, 1.137806309061353e+00, 1.223473858021597e+00, 8.139560718251898e+00, 9.845670775114231e+00, 2.534217904477341e+05, 6.312061984203865e-12, 1.282707273730921e-11, 7.775113886054896e-12, -9.895302355289459e-10, 1.013420397314314e+05, 2.885527995896579e+02, 5.928604065910886e+00, 3.066127159693585e-02 +217, 8.783724505170246e-02, 2.565589914973986e+00, 1.223360419140911e+00, 1.284144727187138e+01, 2.614501629642029e+00, 2.533940920865928e+05, -2.486899575160351e-14, -2.486899575160351e-13, -4.964917366123700e-13, -8.731149137020111e-11, 1.013295603358195e+05, 2.885440202288644e+02, 4.168711862853342e+00, 3.145751265711066e-02 +218, 1.029681136959673e-01, 3.019180182362054e+00, 1.223384594295152e+00, 1.267249932001871e+01, 1.486854545299304e+00, 2.533961779546267e+05, 3.330669073875470e-15, -1.101341240428155e-13, -1.603162047558726e-13, 0.000000000000000e+00, 1.013318560068331e+05, 2.885448553230365e+02, 4.492456188562818e+00, 3.062757759752030e-02 +219, 4.272248514546800e-01, 2.781425804206446e+00, 1.223408888499724e+00, 1.363420871051744e+01, 2.193045701652048e+00, 2.534077436335573e+05, 3.330669073875470e-15, -1.101341240428155e-13, -1.603162047558726e-13, 0.000000000000000e+00, 1.013319220878678e+05, 2.885393136216312e+02, 4.501775189373308e+00, 3.314771692303030e-02 +220, -1.361637633612153e+00, 1.838641552920317e+00, 1.223654897617526e+00, 9.270932554697595e+00, 1.977523173653763e+00, 2.534446063856633e+05, 3.108624468950438e-15, 6.092903959142859e-13, 1.361133428190442e-13, -1.164153218269348e-10, 1.013631552778917e+05, 2.885702219731582e+02, 8.906399364223702e+00, 2.274843673303472e-02 +221, 4.419214930604602e-01, 1.044946977378091e+00, 1.223232472423286e+00, 3.456921484968524e+00, 3.438657949772926e+00, 2.532164532595752e+05, 9.552358903874847e-13, 2.050981606771529e-11, 1.596500709410975e-12, 1.979060471057892e-09, 1.012826941155507e+05, 2.884407318652885e+02, -2.440542158979090e+00, 1.170768826312109e-02 +222, -3.108847414648100e-01, 3.147482464027496e+00, 1.223412810152403e+00, 1.189991056429775e+01, 1.137667056824339e+00, 2.533991957928268e+05, 3.774758283725532e-15, 3.907985046680551e-14, -2.684519273543629e-13, 0.000000000000000e+00, 1.013363170842607e+05, 2.885509032756607e+02, 5.121574426837809e+00, 2.869368361830677e-02 +223, -3.376796078707282e-01, 7.131311903008986e-01, 1.223901597427953e+00, 3.145741539846699e+00, 5.058241085541938e+00, 2.534896235674531e+05, -7.656097977815080e-13, 1.175282093868191e-11, -2.835243151366740e-11, -1.076841726899147e-09, 1.013900513313190e+05, 2.885886101490354e+02, 1.269938391186247e+01, 1.429111128508922e-02 +224, 3.905654080811393e-01, 2.971765411788073e-01, 1.223419928994763e+00, -2.435877862372229e+00, 2.558736258179039e+00, 2.532468321612604e+05, 2.382760655450511e-12, 1.601296872877356e-11, -2.550160083103492e-11, 2.444721758365631e-09, 1.012966925785968e+05, 2.884363957963863e+02, -4.664252437146160e-01, 8.481425789813720e-03 +225, 2.782915014818332e-01, 3.728022855707656e-01, 1.223427896642847e+00, -1.279522069776054e+00, 3.551412616843323e+00, 2.532485363953473e+05, -2.716937785862683e-12, 8.986145161316017e-13, -1.527045156990425e-11, 3.463355824351311e-09, 1.012970850856230e+05, 2.884356349704103e+02, -4.110723983950301e-01, 9.062568569789641e-03 +226, 2.712444240024384e-01, 2.590314194740348e-01, 1.223455710378257e+00, -1.867503916455088e+00, 2.823295977449392e+00, 2.532569182557643e+05, -2.303490731492275e-12, -2.044497904307718e-11, -3.232658585261561e-11, 1.105945557355881e-09, 1.013008941538203e+05, 2.884399235282542e+02, 1.260969990540909e-01, 8.126442142627054e-03 +227, -1.115763530067029e-01, 1.077711656348167e+00, 1.223599605599820e+00, 7.384655889121318e+00, 9.810580498306134e+00, 2.534452615855157e+05, 1.743938327081196e-12, 3.372235823917435e-11, 3.684608174125970e-11, 4.132743924856186e-09, 1.013534592139847e+05, 2.885556569644701e+02, 7.539023266780043e+00, 2.946929933860801e-02 +228, -1.918796759167143e-01, 1.038576667448197e+00, 1.222992087330306e+00, 5.557921386920689e+00, 1.035198050875524e+01, 2.533181766787329e+05, 3.420153049660257e-12, 2.840661039726911e-11, 5.654143819810997e-12, -2.095475792884827e-09, 1.013046942391471e+05, 2.885600922833592e+02, 6.619995976703179e-01, 2.821199875261590e-02 +229, 1.672004922332889e+00, 2.603574249061359e+00, 1.223078120239319e+00, 1.555647565065773e+01, 1.615255486437624e+00, 2.533496813601218e+05, 8.881784197001252e-16, 1.776356839400250e-15, 1.736388810513745e-13, 2.910383045673370e-11, 1.012998729755979e+05, 2.885260624883906e+02, -1.791346807217288e-02, 3.755296105420595e-02 +230, 1.351135975602813e+00, 1.368437490892540e+00, 1.222952422674300e+00, 8.065688177063402e+00, 6.004521149768707e-01, 2.532198606514972e+05, -3.130828929442941e-14, -6.572520305780927e-13, 1.113553693699032e-12, 1.164153218269348e-10, 1.012772462371436e+05, 2.884912648492557e+02, -3.208822853808865e+00, 1.942302258181947e-02 +231, 2.442785479435215e+00, 2.509529940319502e+00, 1.223306246112836e+00, 1.510782608906922e+01, 8.416673465823902e-01, 2.533797026861713e+05, -2.220446049250313e-16, 2.486899575160351e-14, 1.106892355551281e-13, 0.000000000000000e+00, 1.013144489410534e+05, 2.885137653342048e+02, 2.037645050547135e+00, 3.632516377891806e-02 +232, 8.886710406810556e-01, 2.913112520269885e+00, 1.223288026021577e+00, 1.444885226078403e+01, 1.850590814191031e+00, 2.533866536071680e+05, -2.220446049250313e-16, -2.540190280342358e-13, 5.329070518200751e-14, -5.820766091346741e-11, 1.013199690378895e+05, 2.885337824089382e+02, 2.816110265052657e+00, 3.496959993448545e-02 +233, -1.697169288107256e+00, 2.000053102954223e+00, 1.223672090393080e+00, 9.333301426601569e+00, 1.418632321856779e+00, 2.534481043117242e+05, 3.108624468950438e-15, 6.092903959142859e-13, 1.361133428190442e-13, -1.164153218269348e-10, 1.013646752352054e+05, 2.885704946159685e+02, 9.120749570639219e+00, 2.265453317999490e-02 +234, 2.897750158364199e-01, 5.099331872603539e-01, 1.223472038388088e+00, -5.824843951794115e-01, 4.103542662977502e+00, 2.532511449843964e+05, 7.977618565746525e-12, -2.157163336846679e-12, -9.386269539390923e-12, 4.423782229423523e-09, 1.012976498624865e+05, 2.884268365786612e+02, -3.314254002995071e-01, 9.950158582523214e-03 +235, 1.971068415722504e-01, 4.461399405127404e-01, 1.223410994668434e+00, -5.322189517473117e-01, 4.356935477207071e+00, 2.532467861830455e+05, 7.977618565746525e-12, -2.157163336846679e-12, -9.386269539390923e-12, 4.423782229423523e-09, 1.012955648948918e+05, 2.884352911531060e+02, -6.254555222360423e-01, 1.053784910765878e-02 +236, 1.204570258808671e+00, 2.088855945327932e-01, 1.223059895298654e+00, -6.394427610525546e+00, 1.035984930756608e-01, 2.531853602785604e+05, -4.660716257376407e-13, 2.425615264201042e-12, -4.066136316538405e-12, -8.731149137020111e-10, 1.012674560600423e+05, 2.884380294054499e+02, -4.589471154654792e+00, 1.535804142643457e-02 +237, -2.509004448386861e-01, 7.997219214914368e-01, 1.223836201630584e+00, 2.573285580772557e+00, 6.575956598282623e+00, 2.534786120557668e+05, 1.521005543736464e-13, 2.898126183481509e-11, -1.520206183158734e-11, 6.140908226370811e-09, 1.013832958553459e+05, 2.885848016282271e+02, 1.174670079620482e+01, 1.694295120385627e-02 +238, -2.031816024027223e-01, 4.612449409209909e-01, 1.223954086568388e+00, 1.453690555083913e+00, 3.399908175576075e+00, 2.534981595047124e+05, -2.378097718747085e-13, 1.745470434855179e-11, -1.421129880441185e-11, 5.529727786779404e-10, 1.013970296344464e+05, 2.885960956946859e+02, 1.368349096691382e+01, 8.870870246934637e-03 +239, 3.587496042646438e-01, 3.516319950884396e+00, 1.223405550676942e+00, 1.293199931625086e+01, 6.912970857463946e-01, 2.533997513686316e+05, 0.000000000000000e+00, 1.243449787580175e-14, -9.109379917049409e-14, 0.000000000000000e+00, 1.013324829020310e+05, 2.885416977489501e+02, 4.580863352281492e+00, 3.108577649234626e-02 +240, -3.683081841986262e-01, 2.897439343472671e-01, 1.223898821117542e+00, 2.391668522951256e+00, 1.818358165978339e+00, 2.534865923462394e+05, 7.283063041541027e-14, 4.791722574282176e-13, 3.598676912019982e-12, -2.328306436538696e-10, 1.013931618974895e+05, 2.885981184769768e+02, 1.313804787610376e+01, 7.208065061446598e-03 +241, -2.513200276683212e-01, 2.632514534643786e-01, 1.223963903233761e+00, 1.539853856206832e+00, 1.750248032887521e+00, 2.534998443237918e+05, 1.925126724700021e-13, 3.311351193246992e-12, -4.203970505045618e-12, 2.037268131971359e-10, 1.013990497101787e+05, 2.885995305328749e+02, 1.396836978969789e+01, 5.592619253929506e-03 +242, 4.269021533663883e-01, 8.903973250739604e-01, 1.223359478647514e+00, 1.709773870119181e+00, 3.935922602352103e+00, 2.532191143430970e+05, 9.552358903874847e-13, 2.050981606771529e-11, 1.596500709410975e-12, 1.979060471057892e-09, 1.012846352053812e+05, 2.884163140583170e+02, -2.166802230827718e+00, 1.030316877118741e-02 +243, 2.109340235135059e+00, 1.080851787285738e+00, 1.222997133598142e+00, 3.450592156780311e+00, -9.286036925135659e-01, 2.532127152085733e+05, 7.993605777301127e-15, 7.274181257344026e-13, 3.308464613382966e-13, 1.455191522836685e-10, 1.012829979524436e+05, 2.884971013794076e+02, -2.397693915719241e+00, 8.580875075272162e-03 +244, -1.676617144067250e+00, 3.018022054164006e+00, 1.223570364468777e+00, 1.015445575962078e+01, 7.606156278557352e-01, 2.534283193091884e+05, 0.000000000000000e+00, 4.352074256530614e-13, -3.130828929442941e-14, 1.164153218269348e-10, 1.013543787175669e+05, 2.885651708363439e+02, 7.668695186419201e+00, 2.443834798195241e-02 +245, -2.026846095570201e+00, 2.666902796243940e+00, 1.223608231733967e+00, 9.734427424499366e+00, 7.217215762246286e-01, 2.534351135339756e+05, 0.000000000000000e+00, 4.352074256530614e-13, -3.130828929442941e-14, 1.164153218269348e-10, 1.013584718081101e+05, 2.885678935902675e+02, 8.245918503747390e+00, 2.342532050772969e-02 +246, 2.607158247090192e-01, 1.407889830760782e+00, 1.222756208974147e+00, 1.121903692619848e+01, 4.714650841629777e+00, 2.532551323773071e+05, 2.648326002940848e-12, -6.021849685566849e-13, 4.043876344894670e-12, -3.492459654808044e-10, 1.012778298521525e+05, 2.885392212848984e+02, -3.126519228243058e+00, 2.922662322620500e-02 +247, -2.493719312723984e+00, 1.295471787030074e+00, 1.223704432577967e+00, 8.543489959252074e+00, 5.501153726567768e-01, 2.534533587966491e+05, -2.220446049250313e-16, 3.144151605738443e-13, 4.219402605087907e-13, 1.164153218269348e-10, 1.013693645071180e+05, 2.885762170966364e+02, 9.782048669858060e+00, 2.054367396609064e-02 +248, 5.091525299545712e-01, 1.363901608901377e+00, 1.223133808243276e+00, 9.517404776111256e+00, 3.347585340907663e+00, 2.532921369857741e+05, 1.810551708558705e-12, -7.689848757763684e-12, 9.936496070395151e-12, -3.783497959375381e-10, 1.013002111007741e+05, 2.885138892151566e+02, 2.977024031313906e-02, 2.422371032096286e-02 +249, -1.195527190969014e+00, 2.199189128512326e-01, 1.223848002864650e+00, 5.915893548884410e+00, 6.035233441268352e-01, 2.534790225544063e+05, -1.110223024625157e-14, -6.155076448521868e-13, 1.096234214514880e-12, 2.910383045673370e-10, 1.013858301935378e+05, 2.885892327386815e+02, 1.210410288221233e+01, 1.426764339674271e-02 +250, -1.314128489153983e+00, 4.697507427083824e-01, 1.223882859968874e+00, 6.496903704394425e+00, 1.123068636700152e+00, 2.534871634152903e+05, 2.065014825802791e-14, 1.776356839400250e-14, 8.406608742461685e-13, 5.820766091346741e-11, 1.013877615750052e+05, 2.885865109156824e+02, 1.237647369979142e+01, 1.581879172710267e-02 +251, -1.599290321363435e+00, 5.224037598800917e-01, 1.223745412745041e+00, 7.110176131272594e+00, 9.169143283679141e-01, 2.534595902644929e+05, 1.110223024625157e-15, 4.876099524153688e-13, 1.540989558179717e-13, 2.910383045673370e-11, 1.013754364278955e+05, 2.885838382423680e+02, 1.063833421175189e+01, 1.720227682624029e-02 +252, -1.044962389785528e+00, 4.332832988115769e-01, 1.223847567000700e+00, 5.758618457873729e+00, 1.360519422137558e+00, 2.534788694993964e+05, 2.065014825802791e-14, 1.776356839400250e-14, 8.406608742461685e-13, 5.820766091346741e-11, 1.013858260578381e+05, 2.885893237454819e+02, 1.210351964999725e+01, 1.419699713987815e-02 +253, -1.153998973877246e+00, 6.810761986464705e-01, 1.223792629176800e+00, 6.511086023491894e+00, 1.803124504858792e+00, 2.534686567563791e+05, 2.065014825802791e-14, 1.776356839400250e-14, 8.406608742461685e-13, 5.820766091346741e-11, 1.013800030238288e+05, 2.885857032397678e+02, 1.128233307414648e+01, 1.621081673773317e-02 +254, 1.631869036830395e+00, 3.047538019448268e+00, 1.223256111085219e+00, 1.536579356719406e+01, 1.368921015605008e+00, 2.533856600099516e+05, 8.881784197001252e-16, 1.776356839400250e-15, 1.736388810513745e-13, 2.910383045673370e-11, 1.013153544813484e+05, 2.885281688598383e+02, 2.165347813899368e+00, 3.703491067464806e-02 +255, -1.479043584819183e-01, 1.589819470732850e+00, 1.223505847049748e+00, 1.171179650383359e+01, 6.455077145667279e+00, 2.534292935713486e+05, 3.983480212355062e-13, -1.787014980436652e-12, -7.140954494389007e-13, 5.529727786779404e-10, 1.013424843523371e+05, 2.885465212094595e+02, 5.991306210283980e+00, 3.209685426760764e-02 +256, 3.069712538179610e-01, 9.091069837799941e-01, 1.223451351016189e+00, 1.573845846664182e+00, 4.279038869948222e+00, 2.532396788716404e+05, -9.376277532169297e-12, 6.534128793589389e-11, -5.442490902396457e-11, 1.047737896442413e-09, 1.012924734299843e+05, 2.884169743861862e+02, -1.061425753160298e+00, 1.094590481023180e-02 +257, -2.594272056651777e-01, 1.222157888648843e+00, 1.223415451134738e+00, 8.838877610630227e+00, 8.699650860761755e+00, 2.534066653399703e+05, 6.312061984203865e-12, 1.282707273730921e-11, 7.775113886054896e-12, -9.895302355289459e-10, 1.013375218266904e+05, 2.885537108279329e+02, 5.291471822077833e+00, 2.976841418711973e-02 +258, -2.468801529624325e-01, 8.922654704161819e-01, 1.223774668507464e+00, 3.044879977512021e+00, 8.070593268784158e+00, 2.534698620065954e+05, 3.420153049660257e-12, 2.840661039726911e-11, 5.654143819810997e-12, -2.095475792884827e-09, 1.013757847585218e+05, 2.885779308722763e+02, 1.068745713183069e+01, 2.069766936527057e-02 +259, 2.148670476212021e-01, 8.375986992568234e-01, 1.223596884501530e+00, 9.968668981586633e-01, 4.433463843407425e+00, 2.532640085132095e+05, -9.376277532169297e-12, 6.534128793589389e-11, -5.442490902396457e-11, 1.047737896442413e-09, 1.013022282176668e+05, 2.884104425064556e+02, 3.142317961976782e-01, 1.090838468052304e-02 +260, -2.166457481094871e-01, 6.824955517119308e-01, 1.223861144511559e+00, 1.817111799599209e+00, 5.440287801325901e+00, 2.534810812268882e+05, -1.659783421814609e-12, 3.073608034753761e-11, -1.073452438049571e-11, 1.193257048726082e-09, 1.013870562882668e+05, 2.885896238828038e+02, 1.227701146054974e+01, 1.376155582502979e-02 +261, -5.613393115846008e-01, 1.604002166982958e-01, 1.223955391938938e+00, 3.329758926824950e+00, 8.243020633891099e-01, 2.534987046306829e+05, -5.906386491005833e-14, -6.769695914954355e-12, 3.683719995706269e-12, 3.492459654808044e-10, 1.013975591076241e+05, 2.885972948860053e+02, 1.375815930392608e+01, 8.229397489096287e-03 +262, 5.664728369832607e-01, 1.255854681930802e-01, 1.223398663450327e+00, -5.404632411391574e+00, 8.027347237759732e-01, 2.532505832110725e+05, 1.776578884005175e-12, -2.331912440922679e-11, -1.041666752854553e-11, 4.947651177644730e-10, 1.012953527110834e+05, 2.884375942383898e+02, -6.553784962028381e-01, 1.311781934767886e-02 +263, 9.638303562097048e-01, 2.045636585114985e-01, 1.223287573714988e+00, -6.186551371477776e+00, 4.541384001463842e-01, 2.532294152585815e+05, -4.660716257376407e-13, 2.425615264201042e-12, -4.066136316538405e-12, -8.731149137020111e-10, 1.012854749155900e+05, 2.884356584745377e+02, -2.048383078547337e+00, 1.489408150863258e-02 +264, -9.533785029373294e-01, 1.895011240521854e-01, 1.223878453157560e+00, 5.118764087404823e+00, 6.752410851207958e-01, 2.534843745655474e+05, -1.110223024625157e-14, -6.155076448521868e-13, 1.096234214514880e-12, 2.910383045673370e-10, 1.013893935608992e+05, 2.885921952704933e+02, 1.260662260600397e+01, 1.238744910013046e-02 +265, 1.826954383404142e+00, 2.785964409612013e-01, 1.223041048679058e+00, -5.229293030930860e+00, -4.831514415513831e-01, 2.531888890661021e+05, -1.221245327087672e-14, 1.254107928616577e-12, -3.198552533945076e-13, 2.037268131971359e-10, 1.012710457302360e+05, 2.884526986729591e+02, -4.083242104639548e+00, 1.261135091977572e-02 +266, 2.921697762485485e-01, 9.086345747310812e-02, 1.223557911203786e+00, -3.426125377171091e+00, 1.095883245596490e+00, 2.532817509280471e+05, 8.687051078482000e-12, -1.390283443925000e-10, -2.053768266563338e-11, -1.135049387812614e-09, 1.013105853433857e+05, 2.884434228232471e+02, 1.492785698166315e+00, 8.634786731417972e-03 +267, -2.840612497166274e-01, 9.229685029849616e-02, 1.223986609796781e+00, 1.622102981873913e+00, 6.000455895024532e-01, 2.535044656605933e+05, -2.131628207280301e-14, -2.175370994450532e-11, 2.237654506132003e-12, 3.492459654808044e-10, 1.014012974888260e+05, 2.886005740863431e+02, 1.428536015033237e+01, 4.149100010180264e-03 +268, -1.490751359523496e+00, 3.525633643165054e+00, 1.223564578080332e+00, 1.058315943103788e+01, 4.090261328333600e-01, 2.534281495532032e+05, -2.220446049250313e-16, 1.225686219186173e-13, -3.319566843629218e-14, 2.910383045673370e-11, 1.013529247749862e+05, 2.885623959699174e+02, 7.463654630692520e+00, 2.541814465045241e-02 +269, 2.972107302077515e-02, 1.367431664789270e+00, 1.223100261768492e+00, 1.167668268509265e+01, 6.688590241782411e+00, 2.533459678147221e+05, 5.723865825757457e-12, 2.428279799460142e-12, 1.374367286643974e-11, -1.455191522836685e-09, 1.013087767720019e+05, 2.885461990258951e+02, 1.237734029315277e+00, 3.230868242316861e-02 +270, 2.519001428607403e+00, 3.105668206200260e+00, 1.223154298469429e+00, 1.612889379965915e+01, 8.987571869460794e-01, 2.533635901122416e+05, -2.220446049250313e-16, 2.486899575160351e-14, 1.106892355551281e-13, 0.000000000000000e+00, 1.013027678418730e+05, 2.885163377948452e+02, 3.903316701400211e-01, 3.878488472691008e-02 +271, 2.275446086009151e-01, 5.821960655612490e-01, 1.223509167174972e+00, -2.306555869294934e-02, 4.616602335736113e+00, 2.532563567997767e+05, 1.361910584307680e-11, 1.941050098430708e-11, 3.944400361888256e-12, -3.288732841610909e-09, 1.012990587167306e+05, 2.884220952732920e+02, -1.327433746166965e-01, 1.108300555137872e-02 +272, -1.832465309828025e+00, 2.953505897451886e-01, 1.223810281019786e+00, 7.231822194085406e+00, 4.287360743860680e-01, 2.534730734670702e+05, -3.774758283725532e-15, 5.773159728050814e-13, 5.567768468495160e-14, 2.910383045673370e-11, 1.013806523928802e+05, 2.885833892236248e+02, 1.137390958682502e+01, 1.738245026050168e-02 +273, -1.977201710885593e+00, 6.768975172846343e-01, 1.223750006917219e+00, 7.723272191481980e+00, 7.459114613222418e-01, 2.534615093091306e+05, 1.110223024625157e-15, 4.876099524153688e-13, 1.540989558179717e-13, 2.910383045673370e-11, 1.013747642438710e+05, 2.885808413596604e+02, 1.054354024411058e+01, 1.861839005552224e-02 +274, 1.295564655360226e+00, 1.090381241457529e+00, 1.223056558731181e+00, 4.382335545055875e+00, 4.675021200241331e-01, 2.532065013336907e+05, -3.685940441755520e-14, 2.735589532676386e-13, 4.471756298585206e-12, 5.820766091346741e-10, 1.012794243233618e+05, 2.884729053339858e+02, -2.901660786656593e+00, 1.058315079998700e-02 +275, 2.060326253729301e-01, 6.790669324470844e-01, 1.223473136741905e+00, 3.712561138390923e-01, 4.726265486533933e+00, 2.532432488888272e+05, 1.361910584307680e-11, 1.941050098430708e-11, 3.944400361888256e-12, -3.288732841610909e-09, 1.012936255203802e+05, 2.884151190680302e+02, -8.989535495376662e-01, 1.138155443789376e-02 +276, 1.924196542891585e-01, 9.403357631102240e-01, 1.223327465814871e+00, 1.342019493856508e+00, 3.977361504225551e+00, 2.532258651687444e+05, -9.376277532169297e-12, 6.534128793589389e-11, -5.442490902396457e-11, 1.047737896442413e-09, 1.012874653309248e+05, 2.884319207506485e+02, -1.767687078716087e+00, 1.007847692598613e-02 +277, 7.418664808058120e-01, 2.245467777927978e+00, 1.223213297066190e+00, 1.480689998004467e+01, 3.210724154137710e+00, 2.533762238247909e+05, -1.998401444325282e-14, -4.565237077258644e-13, -1.447730824111204e-13, -8.731149137020111e-11, 1.013129567403099e+05, 2.885314391317966e+02, 1.827209182042399e+00, 3.637423861591559e-02 +278, -2.532268608009307e+00, 2.524420249508491e+00, 1.223651488200771e+00, 9.462619979707011e+00, 4.353841786628891e-01, 2.534433421604141e+05, 2.220446049250313e-16, 4.281019982954604e-13, -1.296740492762183e-13, 1.164153218269348e-10, 1.013626708032604e+05, 2.885696467540691e+02, 8.838076894714703e+00, 2.273205529634743e-02 +279, 1.437226083359274e+00, 3.516627295399946e+00, 1.223225807778256e+00, 1.474830894119224e+01, 7.612320944466765e-01, 2.533729757707688e+05, 0.000000000000000e+00, -1.296740492762183e-13, 1.110223024625157e-14, -2.910383045673370e-11, 1.013135317913698e+05, 2.885301258204223e+02, 1.908305086702732e+00, 3.545429835611160e-02 +280, -2.189186497044876e-01, 5.745802665553107e-01, 1.223844761128943e+00, 1.615437123191478e+00, 4.333233371506097e+00, 2.534760602392724e+05, -2.378097718747085e-13, 1.745470434855179e-11, -1.421129880441185e-11, 5.529727786779404e-10, 1.013869291183670e+05, 2.885931251953849e+02, 1.225907747384203e+01, 1.109563551763532e-02 +281, 1.089457768694654e-01, 9.704540577178821e-01, 1.223427922884353e+00, 8.167015093611315e-01, 3.074479191671862e+00, 2.532676899953974e+05, -7.941602930827685e-11, 4.675237974538504e-11, -1.106572611320189e-10, -6.402842700481415e-10, 1.013054217243818e+05, 2.884593667189133e+02, 7.645923539352357e-01, 7.636745764243552e-03 +282, -2.461547386786075e+00, 3.076565038207188e+00, 1.223635612704389e+00, 9.795450041827046e+00, 3.269895238522497e-01, 2.534406386458812e+05, 8.881784197001252e-16, 5.293543381412746e-13, 8.951173136040325e-14, 2.037268131971359e-10, 1.013605550712972e+05, 2.885673673070888e+02, 8.539708263596090e+00, 2.352023592742613e-02 +283, -1.130174033369460e-01, 8.082243464965300e-01, 1.223959069010472e+00, 6.827282906381715e-01, 7.353821096474117e+00, 2.535066933052698e+05, 7.534639578921087e-12, 1.828448503715663e-11, 2.157261036472846e-10, -2.270098775625229e-09, 1.013937644746085e+05, 2.885856276336937e+02, 1.322302561113277e+01, 1.771836314275958e-02 +284, 8.204452252862828e-01, 3.206647418893417e-01, 1.223279575671754e+00, -4.316384526040222e+00, 1.154699072368883e+00, 2.532197957379725e+05, -4.669598041573408e-13, 1.236211133459619e-11, -3.220534949832654e-12, 1.164153218269348e-10, 1.012846541999288e+05, 2.884352071159066e+02, -2.164123546924507e+00, 1.072829166340693e-02 +285, 4.156693094969811e-01, 2.424845942635086e+00, 1.223334833514274e+00, 1.391739950032797e+01, 3.164401642369847e+00, 2.533971197717046e+05, -1.998401444325282e-14, -4.565237077258644e-13, -1.447730824111204e-13, -8.731149137020111e-11, 1.013255442797774e+05, 2.885386187479709e+02, 3.602352246143173e+00, 3.426157243367070e-02 +286, -8.275684052373742e-01, 3.222250016769964e-01, 1.223880801799876e+00, 4.859577778984154e+00, 1.367788708204708e+00, 2.534846595069758e+05, 4.085620730620576e-14, -4.627409566637652e-13, 3.983036123145212e-12, 8.731149137020111e-11, 1.013896989622106e+05, 2.885925107433898e+02, 1.264969146955363e+01, 1.211220628278497e-02 +287, -1.166173387526489e-01, 6.538461538461565e-01, 1.223929469443363e+00, 7.323770467868111e-01, 5.495067249852230e+00, 2.534947476637719e+05, -1.834976615100459e-12, 2.352196215582580e-11, 9.458211991386634e-11, -2.997694537043571e-09, 1.013928771845938e+05, 2.885900813474138e+02, 1.309789657224894e+01, 1.329996401126401e-02 +288, 1.240438945497961e-01, 8.065138160282931e-01, 1.223644140308060e+00, 5.242659568391754e-01, 4.329637067101465e+00, 2.532720820532601e+05, -3.932010272933439e-11, 4.865846614521274e-11, 2.400479814923528e-11, 9.633367881178856e-09, 1.013057239743280e+05, 2.884092565470251e+02, 8.072167998903469e-01, 1.046896299978312e-02 +289, -2.154303597601279e+00, 1.044184926369161e+00, 1.223723781128859e+00, 8.197762537959465e+00, 8.139425393005574e-01, 2.534568986682346e+05, 1.110223024625157e-15, 4.876099524153688e-13, 1.540989558179717e-13, 2.910383045673370e-11, 1.013716677790987e+05, 2.885782111616446e+02, 1.010686491308721e+01, 1.976794457393813e-02 +290, 1.166173387526495e-01, 6.538461538461509e-01, 1.223543362045303e+00, 1.971645056082238e-01, 4.910243974857183e+00, 2.532647969460566e+05, 1.634603563616110e-11, 3.446593010991705e-11, 3.043618690412586e-10, 5.878973752260208e-09, 1.013019713303004e+05, 2.884223272819805e+02, 2.780045551255808e-01, 1.179696392968747e-02 +291, -1.258891549354179e-01, 5.059708679127181e-01, 1.223914881510631e+00, 7.604944141672703e-01, 4.014776252371414e+00, 2.534901336654265e+05, -2.209121774399136e-12, 1.576727637342401e-11, 3.005773407949164e-11, -1.338776201009750e-09, 1.013933250443885e+05, 2.885947958129166e+02, 1.316105547715066e+01, 9.803294640636220e-03 +292, 1.175713774237592e-01, 4.975747777955429e-01, 1.223448748602447e+00, -1.300573695446643e-01, 4.886580215057720e+00, 2.532581077179812e+05, 1.307021157970212e-11, -8.108767129977323e-12, 2.973568058450837e-10, 4.540197551250458e-09, 1.012993368212136e+05, 2.884371305256324e+02, -9.352401443709835e-02, 1.173541869298070e-02 +293, 1.048700903686888e+00, 9.459876133664289e-01, 1.223128752390197e+00, 2.732207001886199e+00, 1.203567741144961e+00, 2.531988781355914e+05, -3.685940441755520e-14, 2.735589532676386e-13, 4.471756298585206e-12, 5.820766091346741e-10, 1.012780937575680e+05, 2.884520889681411e+02, -3.089302274990318e+00, 7.169139158127452e-03 +294, 1.186418472121878e-01, 4.187835261370506e-01, 1.223454342093234e+00, -2.819033819875230e-01, 4.631567988782955e+00, 2.532610418438265e+05, -9.620304552981906e-12, -6.982442402048150e-12, 1.823909911990995e-10, 2.037268131971359e-10, 1.013008970489226e+05, 2.884402543566634e+02, 1.265052774730257e-01, 1.113951954928085e-02 +295, -1.166173387526493e-01, 2.692307692307706e-01, 1.223963666592346e+00, 5.391729168233161e-01, 1.965927964168927e+00, 2.534998770920515e+05, 8.946177132429511e-13, 5.803912905832931e-12, -1.295252793909185e-11, -5.529727786779404e-10, 1.013992718002923e+05, 2.886002184384229e+02, 1.399968978878953e+01, 4.890464773683962e-03 +296, 1.166173387526491e-01, 2.692307692307641e-01, 1.223467786423994e+00, -5.624845123444226e-01, 3.702918957891497e+00, 2.532625093111347e+05, -4.038525069915977e-11, -4.497902050815128e-12, 9.627409980339507e-11, -1.949956640601158e-09, 1.013027105708799e+05, 2.884422484663160e+02, 3.822550951778733e-01, 8.991393853966268e-03 +297, 1.911632660896294e-01, 3.076923076923028e-01, 1.223452386215372e+00, -1.022779056893553e+00, 3.606961658821923e+00, 2.532575075862386e+05, -2.716937785862683e-12, 8.986145161316017e-13, -1.527045156990425e-11, 3.463355824351311e-09, 1.013007052336875e+05, 2.884401693048698e+02, 9.945475779238816e-02, 9.000589168725303e-03 +298, -1.230149159648566e-01, 4.240231476261316e-01, 1.223918889908167e+00, 6.864324267149707e-01, 3.256618375909802e+00, 2.534907510401637e+05, 8.073541835074138e-13, 1.067740340587875e-11, 1.180211484097526e-11, -2.153683453798294e-09, 1.013944903692047e+05, 2.885971674914427e+02, 1.332539404945206e+01, 7.984702054374208e-03 +299, 2.168732385972242e-01, 1.650969093553036e-01, 1.223425339193453e+00, -1.943599280335920e+00, 2.206504378106859e+00, 2.532523265514989e+05, -2.303490731492275e-12, -2.044497904307718e-11, -3.232658585261561e-11, 1.105945557355881e-09, 1.012995171727240e+05, 2.884431631113799e+02, -6.809015315683198e-02, 7.059227777758018e-03 +300, -2.130152561769370e-01, 1.684054772635885e-01, 1.223980581980363e+00, 1.127656683482018e+00, 1.143473603687007e+00, 2.535032066640370e+05, 1.925126724700021e-13, 3.311351193246992e-12, -4.203970505045618e-12, 2.037268131971359e-10, 1.014008612305829e+05, 2.886007537255020e+02, 1.422383734069347e+01, 3.852702540861419e-03 +301, -8.055870777406892e-01, 6.334176827913882e-01, 1.223865182615734e+00, 5.448264530110551e+00, 2.559273736214401e+00, 2.534823667324326e+05, -1.549871342376719e-13, 4.947153797729698e-13, 1.068034549689401e-12, -6.693881005048752e-10, 1.013870255394078e+05, 2.885885841668144e+02, 1.227267513859583e+01, 1.444218672131471e-02 +302, -2.811059592027251e-01, 1.101705201479985e+00, 1.223664750337638e+00, 6.906186995766385e+00, 9.048818151392132e+00, 2.534545885892394e+05, 6.312061984203865e-12, 1.282707273730921e-11, 7.775113886054896e-12, -9.895302355289459e-10, 1.013606569995723e+05, 2.885607861817539e+02, 8.554082579653889e+00, 2.731701364438411e-02 +303, 2.114261813512476e+00, 7.400841022648551e-01, 1.223038515913368e+00, -2.541000612825725e-01, -9.372026396459915e-01, 2.532039846143933e+05, 7.993605777301127e-15, 7.274181257344026e-13, 3.308464613382966e-13, 1.455191522836685e-10, 1.012814396534540e+05, 2.884829013408012e+02, -2.617451212238929e+00, 2.331779067483563e-03 +304, 4.281373388717647e-01, 1.193305780143569e+00, 1.223144153731307e+00, 6.277996030773011e+00, 3.242605981298617e+00, 2.532468382150782e+05, 1.354472090042691e-12, 1.073985345101391e-11, 1.641531355289771e-11, 3.230525180697441e-09, 1.012905714522656e+05, 2.884839944100599e+02, -1.329649941385639e+00, 1.696615968016410e-02 +305, 1.771809142125662e+00, 1.153906331968584e+00, 1.223342298437861e+00, 4.715737235047131e+00, -5.474115205412203e-01, 2.532851913116700e+05, 1.998401444325282e-15, 7.345235530920036e-13, 1.295963336644945e-12, 1.746229827404022e-10, 1.013103918916635e+05, 2.884937097892623e+02, 1.465504394798436e+00, 1.139701462630681e-02 +306, -2.499999999999528e-02, 1.043301270189219e+00, 1.222589238795385e+00, 6.451356677235815e+00, 3.948247465411103e+00, 2.532067154439499e+05, -1.602673549427891e-11, 7.883471653258312e-11, 1.064446308873812e-10, -5.995389074087143e-09, 1.012733275705827e+05, 2.885657986681530e+02, -3.761448232597278e+00, 1.816682569766346e-02 +307, 6.913395267550965e-01, 5.556831550679813e-01, 1.223342236808860e+00, -1.555198324349904e+00, 2.322254754212896e+00, 2.532188811603731e+05, 4.045652701734070e-13, 1.464961485453387e-11, -2.183142555622908e-12, 1.455191522836685e-09, 1.012862753875084e+05, 2.884250496294731e+02, -1.935497460380000e+00, 6.710488932213975e-03 +308, -6.558578863893423e-01, 3.146103857132814e-01, 1.223949287544703e+00, 4.042874892607888e+00, 1.529645944918776e+00, 2.534980495979379e+05, 4.085620730620576e-14, -4.627409566637652e-13, 3.983036123145212e-12, 8.731149137020111e-11, 1.013961666646189e+05, 2.885947710675202e+02, 1.356179165405810e+01, 1.037017375800845e-02 +309, 1.873559801830099e-01, 7.692307692307663e-01, 1.223455802061586e+00, 6.893284567237643e-01, 4.613334121114886e+00, 2.532328992510627e+05, -9.376277532169297e-12, 6.534128793589389e-11, -5.442490902396457e-11, 1.047737896442413e-09, 1.012896028861294e+05, 2.884077516328088e+02, -1.466240850453731e+00, 1.119873958108173e-02 +310, -1.213880061531652e-01, 1.006983173321793e+00, 1.223527114079902e+00, 4.391630409326201e+00, 1.069855835070797e+01, 2.534276579651622e+05, -1.602673549427891e-11, 7.883471653258312e-11, 1.064446308873812e-10, -5.995389074087143e-09, 1.013492008886304e+05, 2.885606290369308e+02, 6.938497903031396e+00, 2.775611762173657e-02 +311, 1.155947568046216e-01, 1.153846153846089e-01, 1.223481535121155e+00, -9.232566541081247e-01, 2.059523542506481e+00, 2.532640595915079e+05, -5.111155942927326e-11, -2.103994756197380e-11, 5.924327695083775e-11, -1.135049387812614e-09, 1.013047911243921e+05, 2.884449310940749e+02, 6.756627262843837e-01, 5.418180366889786e-03 +312, -1.169920994634274e-01, 1.167516047826436e-01, 1.223958933334947e+00, 4.707291669410571e-01, 8.567694969850899e-01, 2.534987478700813e+05, 4.951594689828198e-13, 7.652212197228891e-14, -2.396127740666998e-11, -9.604264050722122e-10, 1.013993429924796e+05, 2.886015371308702e+02, 1.400972958392842e+01, 2.345212120018102e-03 +313, -1.947654651598528e+00, 1.778423252900096e+00, 1.223669069880110e+00, 9.004333425487221e+00, 1.156810042625305e+00, 2.534468384923422e+05, -4.440892098500626e-16, 2.664535259100376e-13, 2.009503674571533e-14, 5.820766091346741e-11, 1.013652650507557e+05, 2.885728860485926e+02, 9.203927620323205e+00, 2.178541225423792e-02 +314, -2.086024201840096e+00, 2.166614733419356e+00, 1.223671181115396e+00, 9.330325533358877e+00, 8.963056946706502e-01, 2.534475646223658e+05, -4.440892098500626e-16, 2.664535259100376e-13, 2.009503674571533e-14, 5.820766091346741e-11, 1.013646660536332e+05, 2.885706829064486e+02, 9.119454750134761e+00, 2.249322937962707e-02 +315, -5.187852954598429e-01, 1.093552794342578e+00, 1.223736296562358e+00, 6.914791712083555e+00, 5.667770118836851e+00, 2.534600171817133e+05, 1.139088823265411e-13, 2.895461648222408e-13, -3.487876654162392e-12, 7.566995918750763e-10, 1.013709422994163e+05, 2.885731945788584e+02, 1.000455498749781e+01, 2.145417688609627e-02 +316, -9.145482066455091e-01, 3.061228621458711e+00, 1.223531373379239e+00, 1.097576025624915e+01, 1.103651662856631e+00, 2.534220890228811e+05, -4.440892098500626e-16, 4.014566457044566e-13, -1.649791414592983e-13, -2.910383045673370e-11, 1.013489447648564e+05, 2.885588952823575e+02, 6.902378346698387e+00, 2.647512246035987e-02 +317, 6.700572183150456e-02, 1.250201740119510e+00, 1.222887824270100e+00, 9.752843379317010e+00, 5.297623082091749e+00, 2.532798670039630e+05, 5.723865825757457e-12, 2.428279799460142e-12, 1.374367286643974e-11, -1.455191522836685e-09, 1.012918005932648e+05, 2.885479649568509e+02, -1.156311766358736e+00, 2.665204260649057e-02 +318, 1.105028473255420e+00, 1.240846028362717e+00, 1.223154782559960e+00, 6.662201857750612e+00, 1.208455879662204e+00, 2.532396844932206e+05, -3.685940441755520e-14, 2.735589532676386e-13, 4.471756298585206e-12, 5.820766091346741e-10, 1.012883775588955e+05, 2.884752392383069e+02, -1.639041193699892e+00, 1.625784099306084e-02 +319, -5.835849087710454e-01, 2.893561030953141e+00, 1.223484740103887e+00, 1.137967723974360e+01, 1.491742815302309e+00, 2.534130952625470e+05, 7.771561172376096e-15, 3.925748615074554e-13, -3.519406988061746e-13, -5.820766091346741e-11, 1.013437057807666e+05, 2.885549768311406e+02, 6.163556729171500e+00, 2.754660296507543e-02 +320, 8.505566778661779e-01, 9.636508560890513e-01, 1.223119684931812e+00, 2.925947389084096e+00, 1.989647743542808e+00, 2.531838315624642e+05, 1.296740492762183e-13, 6.381561945545400e-13, 1.117816950113593e-11, 6.402842700481415e-10, 1.012714854228318e+05, 2.884354059098903e+02, -4.021234969428091e+00, 8.496846237686552e-03 +321, 6.983346128340429e-01, 2.572994042603186e+00, 1.223233601354937e+00, 1.453708208385141e+01, 2.634235354500039e+00, 2.533784823043737e+05, -1.998401444325282e-14, -4.565237077258644e-13, -1.447730824111204e-13, -8.731149137020111e-11, 1.013157062056269e+05, 2.885344799714441e+02, 2.214949319832903e+00, 3.546793382037867e-02 +322, 5.374436509502867e-01, 3.138332338976782e+00, 1.223291695827841e+00, 1.347972868642255e+01, 1.397502550485104e+00, 2.533802437205548e+05, 3.330669073875470e-15, -1.101341240428155e-13, -1.603162047558726e-13, 0.000000000000000e+00, 1.013220709459892e+05, 2.885389025113511e+02, 3.112529401949531e+00, 3.253281300440704e-02 +323, -1.194510535185721e+00, 9.174718985692929e-01, 1.223824666195773e+00, 7.217347242913152e+00, 2.143882094728399e+00, 2.534764590963026e+05, -9.148237722911290e-14, -1.048050535246148e-13, 1.509903313490213e-12, 1.455191522836685e-10, 1.013813198390199e+05, 2.885818970193314e+02, 1.146803539978788e+01, 1.806494265911084e-02 +324, 2.057507704413069e+00, 2.866259616705931e+00, 1.223301677879997e+00, 1.575896911405986e+01, 1.292014873052860e+00, 2.533956928138903e+05, 8.881784197001252e-16, 1.776356839400250e-15, 1.736388810513745e-13, 2.910383045673370e-11, 1.013174017773912e+05, 2.885232515858849e+02, 2.454065349203997e+00, 3.795855703898859e-02 +325, 1.249515107534523e+00, 3.141692841272405e+00, 1.223229052445873e+00, 1.478624722215003e+01, 1.371676486308351e+00, 2.533755681568757e+05, -2.220446049250313e-16, -2.540190280342358e-13, 5.329070518200751e-14, -5.820766091346741e-11, 1.013141727555659e+05, 2.885311858746484e+02, 1.998696314469292e+00, 3.565050325140034e-02 +326, -1.913805922368587e-01, 3.846153846153842e-01, 1.223948932904111e+00, 1.178956976216154e+00, 2.781381913896267e+00, 2.534969079366810e+05, 5.149214388211476e-13, 1.453082099089897e-11, -7.374101329560290e-12, 2.910383045673370e-10, 1.013972719319159e+05, 2.885980005117916e+02, 1.371766068479257e+01, 7.247396511853272e-03 +327, -6.969522967381462e-01, 1.995783864462872e+00, 1.223599637315919e+00, 1.034103323909580e+01, 3.094649324752502e+00, 2.534352704276519e+05, -6.661338147750939e-16, 4.032330025438569e-13, -7.260858581048524e-13, -2.037268131971359e-10, 1.013550637353904e+05, 2.885602175946761e+02, 7.765299025588181e+00, 2.590492342316901e-02 +328, -4.483359765628624e-01, 3.566026573728412e+00, 1.223517120677523e+00, 1.179461195729150e+01, 5.223306848702273e-01, 2.534203167868950e+05, 0.000000000000000e+00, 1.243449787580175e-14, -9.109379917049409e-14, 0.000000000000000e+00, 1.013453422848204e+05, 2.885519996573801e+02, 6.394342803613157e+00, 2.833597567089714e-02 +329, 1.699206949741733e+00, 2.243186113684460e+00, 1.223071004636230e+00, 1.489265607094694e+01, 1.472139513687336e+00, 2.533363175307319e+05, -1.776356839400250e-15, 1.403321903126198e-13, 3.351763311343348e-13, 0.000000000000000e+00, 1.012979047068426e+05, 2.885221349513513e+02, -2.954862723794864e-01, 3.593300960213088e-02 +330, -1.046284642815941e+00, 2.022280731051820e+00, 1.223595964769038e+00, 9.845372261346469e+00, 2.348686839931401e+00, 2.534333288980267e+05, 2.509104035652854e-14, 1.046274178406748e-12, -1.176836406102666e-13, -2.910383045673370e-11, 1.013565862138865e+05, 2.885654182347552e+02, 7.980004778800716e+00, 2.429081302048368e-02 +331, 3.235721193844368e-01, 1.092279671091064e+00, 1.223231806609479e+00, 3.909828269856925e+00, 3.555483051004106e+00, 2.532367465883355e+05, 1.354472090042691e-12, 1.073985345101391e-11, 1.641531355289771e-11, 3.230525180697441e-09, 1.012901323353615e+05, 2.884620720179287e+02, -1.391575890360022e+00, 1.268877317831709e-02 +332, 8.679888158548368e-01, 1.871223101036811e+00, 1.223180332184478e+00, 1.426205040237527e+01, 3.042274666816849e+00, 2.533560718052910e+05, -4.707345624410664e-14, -1.101341240428155e-12, 2.242650509742816e-13, -8.731149137020111e-11, 1.013076568227925e+05, 2.885241209339908e+02, 1.079794499013083e+00, 3.501176911293997e-02 +333, -3.319209300457331e-01, 1.889573220486007e-01, 1.223912759895031e+00, 1.958002100530780e+00, 1.218379807065999e+00, 2.534892753604094e+05, 1.925126724700021e-13, 3.311351193246992e-12, -4.203970505045618e-12, 2.037268131971359e-10, 1.013948410917682e+05, 2.885996112010378e+02, 1.337485428968570e+01, 5.532686156397756e-03 +334, 4.774795668577059e-01, 2.179871082576428e-01, 1.223356515643170e+00, -3.771103698290878e+00, 1.651764337855361e+00, 2.532366812294827e+05, 2.382760655450511e-12, 1.601296872877356e-11, -2.550160083103492e-11, 2.444721758365631e-09, 1.012919015009471e+05, 2.884377040341394e+02, -1.142081378217400e+00, 9.884419478679756e-03 +335, 4.915538825077176e-01, 2.160904596168906e+00, 1.223346785327388e+00, 1.437769876041544e+01, 3.840843578780607e+00, 2.534058231502780e+05, -1.079136779935652e-13, -4.209965709378594e-13, -8.713030297258229e-13, -1.746229827404022e-10, 1.013261219796085e+05, 2.885374448576471e+02, 3.683821690665079e+00, 3.572384751402235e-02 +336, 3.440337691373537e-01, 1.899805242603490e-01, 1.223414073203189e+00, -3.036935333621839e+00, 1.925539150116452e+00, 2.532494876601952e+05, -2.303490731492275e-12, -2.044497904307718e-11, -3.232658585261561e-11, 1.105945557355881e-09, 1.012976811964150e+05, 2.884405914231352e+02, -3.270065695895957e-01, 8.632967975846065e-03 +337, -1.415168263499680e-03, 2.206407225351385e+00, 1.223371363932642e+00, 1.279139314761204e+01, 3.616715602682938e+00, 2.533979743596709e+05, -2.486899575160351e-14, -2.486899575160351e-13, -4.964917366123700e-13, -8.731149137020111e-11, 1.013303022979763e+05, 2.885435515710440e+02, 4.273346210164354e+00, 3.190846318756355e-02 +338, -1.814471533605498e+00, 1.030452233995191e+00, 1.223789079701701e+00, 8.003571756891443e+00, 1.209083872998793e+00, 2.534701960711103e+05, 1.110223024625157e-15, 4.876099524153688e-13, 1.540989558179717e-13, 2.910383045673370e-11, 1.013773708570551e+05, 2.885790475732757e+02, 1.091113482655617e+01, 1.942208997229581e-02 +339, 6.322009776757828e-01, 2.637184348675269e-01, 1.223299000192240e+00, -4.222415000861841e+00, 1.423115035402920e+00, 2.532239549344721e+05, 2.382760655450511e-12, 1.601296872877356e-11, -2.550160083103492e-11, 2.444721758365631e-09, 1.012863359897996e+05, 2.884354163823575e+02, -1.926951092997570e+00, 1.069839775702287e-02 +340, -5.206850238724661e-02, 1.484120870446531e+00, 1.223304619380453e+00, 1.201466267451704e+01, 6.939473587520186e+00, 2.533914257028261e+05, 3.983480212355062e-13, -1.787014980436652e-12, -7.140954494389007e-13, 5.529727786779404e-10, 1.013250967773433e+05, 2.885444709432786e+02, 3.539243737598028e+00, 3.330696168370299e-02 +341, -1.067138440230083e+00, 1.679995134282146e+00, 1.223661203435676e+00, 9.163056512688568e+00, 2.658930093770007e+00, 2.534457534331867e+05, 2.509104035652854e-14, 1.046274178406748e-12, -1.176836406102666e-13, -2.910383045673370e-11, 1.013634228245975e+05, 2.885694965753047e+02, 8.944129826191594e+00, 2.289605373979809e-02 +342, 3.498075081993633e-01, 9.904504717417373e-01, 1.223299732092588e+00, 2.411581950359235e+00, 3.927153283878850e+00, 2.532188030061710e+05, 9.552358903874847e-13, 2.050981606771529e-11, 1.596500709410975e-12, 1.979060471057892e-09, 1.012840489119313e+05, 2.884287308513441e+02, -2.249483580405804e+00, 1.106518006274203e-02 +343, -1.409051090758434e+00, 7.213554735703285e-01, 1.223778270143671e+00, 7.085070667316867e+00, 1.462721510813410e+00, 2.534665130184441e+05, 2.065014825802791e-14, 1.776356839400250e-14, 8.406608742461685e-13, 5.820766091346741e-11, 1.013780517329687e+05, 2.885835347607810e+02, 1.100715455771298e+01, 1.735882376927667e-02 +344, 1.636158649805557e+00, 4.868502268896326e-01, 1.223367622580789e+00, -3.154460445827009e+00, -5.334635347727227e-01, 2.532566257380434e+05, -3.641531520770513e-14, 2.678302024605728e-12, 6.171729793891245e-13, 6.111804395914078e-10, 1.013009770117564e+05, 2.884609284023157e+02, 1.377819428074474e-01, 7.680666825247181e-03 +345, 2.644118219039237e+00, 3.574092330421587e-01, 1.222546862093284e+00, -3.732597176207666e+00, -4.736735454771790e-01, 2.530960924806156e+05, 2.220446049250313e-16, 7.008837954458613e-13, 1.458833054357456e-13, 2.910383045673370e-11, 1.012361210649396e+05, 2.884697821180890e+02, -9.008452271947050e+00, 9.038902416420096e-03 +346, -2.650653541240063e+00, 3.515194932500502e-01, 1.223803409321957e+00, 7.927504795728984e+00, 1.339087643386405e-01, 2.534727847366870e+05, 0.000000000000000e+00, 8.926193117986259e-13, 1.164901508587946e-13, 1.164153218269348e-10, 1.013788404694882e+05, 2.885798519001987e+02, 1.111838520494060e+01, 1.902413660713424e-02 +347, -1.769996485580073e-01, 8.499134075174017e-01, 1.223798022868267e+00, 1.592619051406297e+00, 7.907236403339704e+00, 2.534742841066959e+05, 3.420153049660257e-12, 2.840661039726911e-11, 5.654143819810997e-12, -2.095475792884827e-09, 1.013790810347209e+05, 2.885818068461862e+02, 1.115231063614298e+01, 1.935382054147448e-02 +348, -1.700985799513217e-01, 9.422303200287888e-01, 1.223462161909156e+00, 2.494978617113519e+00, 9.696768652144991e+00, 2.534102925883355e+05, 3.420153049660257e-12, 2.840661039726911e-11, 5.654143819810997e-12, -2.095475792884827e-09, 1.013477287490897e+05, 2.885717566958005e+02, 6.730891142256855e+00, 2.403149253604892e-02 +349, -2.128909221839912e-01, 1.330097089303026e+00, 1.223451082371909e+00, 1.019253509619985e+01, 8.208393145680503e+00, 2.534174423505167e+05, 1.111111203044857e-12, 2.751576744230988e-12, 9.023892744153272e-13, 1.455191522836685e-10, 1.013389798274183e+05, 2.885494585858004e+02, 5.497084673283597e+00, 3.141154831065096e-02 +350, 8.210760892265832e-02, 1.162070301911011e+00, 1.222919623585753e+00, 7.288628568088392e+00, 3.840876233069861e+00, 2.532634064620272e+05, 3.690381333854020e-12, 7.325695605686633e-12, 2.441069568703824e-11, -1.309672370553017e-09, 1.012942618656250e+05, 2.885474731022142e+02, -8.092137039892210e-01, 1.978354524427928e-02 +351, -3.903560825389988e-01, 1.178103861903783e+00, 1.223673873768799e+00, 7.698966523132535e+00, 7.259932274752884e+00, 2.534522230082647e+05, 1.139088823265411e-13, 2.895461648222408e-13, -3.487876654162392e-12, 7.566995918750763e-10, 1.013625868264130e+05, 2.885641286673152e+02, 8.826234157803157e+00, 2.539427911848234e-02 +352, 3.869380291099325e-01, 1.422993055924091e+00, 1.223167603002235e+00, 1.090290609774637e+01, 4.094571116310522e+00, 2.533314859247179e+05, 1.810551708558705e-12, -7.689848757763684e-12, 9.936496070395151e-12, -3.783497959375381e-10, 1.013104160725435e+05, 2.885349819510631e+02, 1.468914475174600e+00, 2.796134356158157e-02 +353, -1.374987558079208e+00, 2.148392964038505e+00, 1.223630300899640e+00, 9.708359859844350e+00, 1.721269690072001e+00, 2.534401954644673e+05, 5.107025913275720e-15, 5.844214001626824e-13, -2.113864638886298e-13, -2.910383045673370e-11, 1.013601885791888e+05, 2.885675765986837e+02, 8.488024141695339e+00, 2.366158602565090e-02 +354, -4.602744585515295e-01, 2.097741156688599e-01, 1.223909107751299e+00, 2.737016601957775e+00, 1.241828123389687e+00, 2.534888147448246e+05, 7.283063041541027e-14, 4.791722574282176e-13, 3.598676912019982e-12, -2.328306436538696e-10, 1.013940497430568e+05, 2.885982199635703e+02, 1.326325526115297e+01, 7.210754537013746e-03 +355, -1.002082805170027e-01, 9.520196067736426e-01, 1.224977861717568e+00, 1.331103712039439e+00, 1.009664874030586e+01, 2.537247093101128e+05, -1.602673549427891e-11, 7.883471653258312e-11, 1.064446308873812e-10, -5.995389074087143e-09, 1.014729504951079e+05, 2.885708067934764e+02, 2.439014174416658e+01, 2.441269527369345e-02 +356, -1.812136075426863e-01, 3.076923076923094e-01, 1.223964275236052e+00, 1.118734570901009e+00, 2.201385383604276e+00, 2.534999827566136e+05, 5.149214388211476e-13, 1.453082099089897e-11, -7.374101329560290e-12, 2.910383045673370e-10, 1.013989967231316e+05, 2.885992920077423e+02, 1.396089735321195e+01, 5.924020464765692e-03 +357, -1.703879196379263e+00, 7.830078159447229e-01, 1.223779182639035e+00, 7.534463719344497e+00, 1.168502248836818e+00, 2.534673739595964e+05, 1.110223024625157e-15, 4.876099524153688e-13, 1.540989558179717e-13, 2.910383045673370e-11, 1.013774489252445e+05, 2.885816036263605e+02, 1.092214430186229e+01, 1.829477872795188e-02 +358, 1.820474168448716e-01, 2.368220779738162e-01, 1.223425672652358e+00, -1.227938766938893e+00, 3.089073295925200e+00, 2.532522465426117e+05, -2.303490731492275e-12, -2.044497904307718e-11, -3.232658585261561e-11, 1.105945557355881e-09, 1.012990921799738e+05, 2.884418743565698e+02, -1.280242598004139e-01, 7.980491258112800e-03 +359, 1.451983063683895e-01, 1.383788091478695e+00, 1.223285069289393e+00, 1.147383994937680e+01, 5.440626280994358e+00, 2.533740977236589e+05, 2.648326002940848e-12, -6.021849685566849e-13, 4.043876344894670e-12, -3.492459654808044e-10, 1.013232757467625e+05, 2.885438965051467e+02, 3.282435025038613e+00, 3.048362503486962e-02 +360, -2.565450988694428e+00, 3.554499160178211e+00, 1.223575676271665e+00, 9.973485039825441e+00, 1.340423273205414e-01, 2.534286259918514e+05, 8.881784197001252e-16, 5.293543381412746e-13, 8.951173136040325e-14, 2.037268131971359e-10, 1.013551884894283e+05, 2.885662235978334e+02, 7.782892318194036e+00, 2.393777233445176e-02 +361, -5.950060001341283e-02, 3.449801834200471e+00, 1.223431687971947e+00, 1.229593804796450e+01, 7.060367634391901e-01, 2.534035070999142e+05, 0.000000000000000e+00, 1.243449787580175e-14, -9.109379917049409e-14, 0.000000000000000e+00, 1.013366056106831e+05, 2.885472724260561e+02, 5.162263528858886e+00, 2.956237941944700e-02 +362, -3.017512046712255e-01, 6.115796758124670e-01, 1.223917467094295e+00, 2.518800989389447e+00, 4.312299118413522e+00, 2.534915420457442e+05, -7.656097977815080e-13, 1.175282093868191e-11, -2.835243151366740e-11, -1.076841726899147e-09, 1.013925413339972e+05, 2.885919554804813e+02, 1.305053363378933e+01, 1.198140068880464e-02 +363, 2.556268831004126e+00, 3.563367986840045e+00, 1.223028544559321e+00, 1.617493673443250e+01, 4.512796980588781e-01, 2.533436754674489e+05, -2.220446049250313e-16, -8.348877145181177e-14, -7.771561172376096e-15, -5.820766091346741e-11, 1.012946531598720e+05, 2.885228900679836e+02, -7.540318894430460e-01, 3.885402170042469e-02 +364, -1.768133269761258e-01, 2.407041781870481e-01, 1.223951443036087e+00, 9.645070416358195e-01, 1.679017505459845e+00, 2.534972559003579e+05, 1.925126724700021e-13, 3.311351193246992e-12, -4.203970505045618e-12, 2.037268131971359e-10, 1.013982896930903e+05, 2.886003053994726e+02, 1.386118926672155e+01, 4.645344559673272e-03 +365, 1.332919996948298e+00, 4.027190194984381e-01, 1.223212360657791e+00, -3.990626507147903e+00, -7.158962982237284e-02, 2.532167510614464e+05, -3.641531520770513e-14, 2.678302024605728e-12, 6.171729793891245e-13, 6.111804395914078e-10, 1.012840957705533e+05, 2.884494661466516e+02, -2.242875397927961e+00, 9.583527180140909e-03 +366, 1.912691117079100e+00, 5.622886953580213e-01, 1.223133114344291e+00, -2.311312053175386e+00, -8.181538576829973e-01, 2.532140488845353e+05, 2.287059430727822e-14, 1.333599897179738e-12, -5.107025913275720e-15, 1.746229827404022e-10, 1.012846365799952e+05, 2.884696949584271e+02, -2.166608377487977e+00, 5.887354303405663e-03 +367, -2.056408591974881e+00, 3.063513596531352e+00, 1.223606606695892e+00, 9.936727269780306e+00, 5.349740301928464e-01, 2.534351278870140e+05, 0.000000000000000e+00, 4.352074256530614e-13, -3.130828929442941e-14, 1.164153218269348e-10, 1.013578654386604e+05, 2.885665504912453e+02, 8.160405959717862e+00, 2.388131385437042e-02 +368, 8.120751200551289e-01, 4.655849226890503e-01, 1.223231214695901e+00, -2.790157582045818e+00, 1.545915321234842e+00, 2.532027076035755e+05, -4.669598041573408e-13, 1.236211133459619e-11, -3.220534949832654e-12, 1.164153218269348e-10, 1.012794194420401e+05, 2.884317025608517e+02, -2.902349169348856e+00, 7.659223787718128e-03 +369, -1.257900489223991e+00, 3.180601830968487e+00, 1.223593729592280e+00, 1.062974529579342e+01, 8.143002521460643e-01, 2.534343422709743e+05, -4.440892098500626e-16, 4.014566457044566e-13, -1.649791414592983e-13, -2.910383045673370e-11, 1.013551597340866e+05, 2.885618841254995e+02, 7.778837129687456e+00, 2.558514491034126e-02 +370, -2.181473187793706e-01, 1.469379732890009e+00, 1.223333231966407e+00, 1.092806019514326e+01, 7.155109421002757e+00, 2.533924332144266e+05, 1.111111203044857e-12, 2.751576744230988e-12, 9.023892744153272e-13, 1.455191522836685e-10, 1.013290793177173e+05, 2.885490630200243e+02, 4.100876846326842e+00, 3.135516464573753e-02 +371, -8.806214129375030e-01, 4.952915088252127e-01, 1.223857444954859e+00, 5.329181881730046e+00, 1.883336557321455e+00, 2.534804802028994e+05, 5.639932965095795e-14, -1.545430450278218e-13, 2.074118654604717e-12, 1.746229827404022e-10, 1.013869713528391e+05, 2.885902544882866e+02, 1.226503354097746e+01, 1.356111679136667e-02 +372, -2.762092659133550e-01, 9.906537173428704e-01, 1.223887812087404e+00, 4.721426779216753e+00, 8.803442167301297e+00, 2.534967178157738e+05, 3.420153049660257e-12, 2.840661039726911e-11, 5.654143819810997e-12, -2.095475792884827e-09, 1.013823796733160e+05, 2.885700244401974e+02, 1.161749729460260e+01, 2.396805604591133e-02 +373, -2.346523406301626e+00, 1.725836861120980e+00, 1.223724476788128e+00, 8.904688433310570e+00, 7.267389547864525e-01, 2.534579478710265e+05, -4.440892098500626e-16, 2.664535259100376e-13, 2.009503674571533e-14, 5.820766091346741e-11, 1.013701334625365e+05, 2.885736793223428e+02, 9.890489710411376e+00, 2.143874870331807e-02 +374, 1.799970748219663e-01, 3.775230694413451e-01, 1.223407880267667e+00, -7.037859954951364e-01, 4.113833561194322e+00, 2.532485264766059e+05, -2.716937785862683e-12, 8.986145161316017e-13, -1.527045156990425e-11, 3.463355824351311e-09, 1.012965629808504e+05, 2.884388674353318e+02, -4.847016146621204e-01, 1.001991109697190e-02 +375, 1.865009515760742e-01, 5.226431793787458e-01, 1.223397739581857e+00, -1.786105134748714e-01, 4.664367566011500e+00, 2.532405286499101e+05, 7.977618565746525e-12, -2.157163336846679e-12, -9.386269539390923e-12, 4.423782229423523e-09, 1.012926495396169e+05, 2.884301147947329e+02, -1.036590097747045e+00, 1.120660644018496e-02 +376, -1.068861446456477e-01, 5.507133030401616e-02, 1.223986831100145e+00, 4.006958780826265e-01, 3.920099898360850e-01, 2.535044886925571e+05, 2.498001805406602e-13, -1.840494423532846e-11, -5.467903907430127e-12, 4.365574568510056e-10, 1.014017441318595e+05, 2.886017931066367e+02, 1.434834746290780e+01, 1.344770091937748e-03 +377, 1.068861446456453e-01, 5.507133030401115e-02, 1.223611116478726e+00, -1.024706870765778e+00, 1.043747551055868e+00, 2.532908959828543e+05, -1.698796658899937e-11, -1.478892563966383e-10, 2.107758412250860e-12, -5.413312464952469e-09, 1.013160087014639e+05, 2.884463209567323e+02, 2.257608442240649e+00, 3.510949609933743e-03 +378, -5.144035332251840e-03, 1.610891551864297e+00, 1.223485081812751e+00, 1.256574756227486e+01, 6.343831097196376e+00, 2.534289030290521e+05, 3.983480212355062e-13, -1.787014980436652e-12, -7.140954494389007e-13, 5.529727786779404e-10, 1.013391714084701e+05, 2.885419855683851e+02, 5.524102167553719e+00, 3.378597560355467e-02 +379, 4.156095974604680e-01, 1.981857019398038e+00, 1.223133747791486e+00, 1.420717262241304e+01, 4.327406934570273e+00, 2.533619865198574e+05, -1.079136779935652e-13, -4.209965709378594e-13, -8.713030297258229e-13, -1.746229827404022e-10, 1.013087281998173e+05, 2.885381610892925e+02, 1.230884193671915e+00, 3.565734467316083e-02 +380, -1.748361167191548e-01, 7.742248915973065e-01, 1.223660413866388e+00, 1.454900075604717e+00, 6.683752030733215e+00, 2.534422898223822e+05, 1.521005543736464e-13, 2.898126183481509e-11, -1.520206183158734e-11, 6.140908226370811e-09, 1.013692685008089e+05, 2.885863247245053e+02, 9.768509492155378e+00, 1.641441958106347e-02 +381, 3.271812471232078e-01, 1.522804422762236e+00, 1.222931970766132e+00, 1.232929624817845e+01, 4.746744980929930e+00, 2.533036807802670e+05, 6.001865671123596e-13, -4.394706820676220e-12, -1.468158927764307e-12, -1.018634065985680e-09, 1.012929272845727e+05, 2.885407581609601e+02, -9.974214394773100e-01, 3.172463662836761e-02 +382, -6.317515947883354e-01, 1.168090034879908e+00, 1.223495519081269e+00, 7.510393355158552e+00, 4.773916699853312e+00, 2.534095511920582e+05, -2.104982854689297e-13, 4.991562718714704e-13, -8.881784197001252e-15, -2.910383045673370e-10, 1.013508745709705e+05, 2.885728461149246e+02, 7.174527001907401e+00, 2.135863313538308e-02 +383, 2.015824627215827e+00, 2.491447963282769e+00, 1.223159213682278e+00, 1.537950055268367e+01, 1.269358529589758e+00, 2.533612750753557e+05, 8.881784197001252e-16, 1.776356839400250e-15, 1.736388810513745e-13, 2.910383045673370e-11, 1.013055714674984e+05, 2.885231632655841e+02, 7.857097022188374e-01, 3.705051738977645e-02 +384, 1.710410742965300e-01, 6.153846153846130e-01, 1.223419141022972e+00, 1.275256423759556e-01, 4.822531450016275e+00, 2.532407374466413e+05, 1.361910584307680e-11, 1.941050098430708e-11, 3.944400361888256e-12, -3.288732841610909e-09, 1.012924903835516e+05, 2.884246160587762e+02, -1.059034896123678e+00, 1.158208058463472e-02 +385, -6.328616988425948e-01, 3.251824022029469e+00, 1.223490149269168e+00, 1.143737589244622e+01, 9.197433238791282e-01, 2.534143590775664e+05, 3.774758283725532e-15, 3.907985046680551e-14, -2.684519273543629e-13, 0.000000000000000e+00, 1.013442216767769e+05, 2.885551700017339e+02, 6.236310361997994e+00, 2.753989882504730e-02 +386, -9.718814080443171e-01, 6.115572471762436e-01, 1.223812115885198e+00, 5.901097572925424e+00, 2.050413462013718e+00, 2.534718729046853e+05, 5.639932965095795e-14, -1.545430450278218e-13, 2.074118654604717e-12, 1.746229827404022e-10, 1.013823711979001e+05, 2.885878491777843e+02, 1.161630205895924e+01, 1.498928071223319e-02 +387, 2.019071083615632e+00, 1.395191541566999e+00, 1.223034376111571e+00, 7.291085325859715e+00, -5.528628868550496e-01, 2.532443573594430e+05, 1.998401444325282e-15, 7.345235530920036e-13, 1.295963336644945e-12, 1.746229827404022e-10, 1.012889998399618e+05, 2.885054117897477e+02, -1.551284732505251e+00, 1.755790361213565e-02 +388, 2.518952413106084e-01, 7.355832393909363e-01, 1.223537432268177e+00, 6.843453137502689e-01, 4.613313870157516e+00, 2.532497539145600e+05, 5.078604203845316e-12, 3.287115024619425e-11, -5.817657466877790e-11, 2.677552402019501e-09, 1.012963461382907e+05, 2.884077092315647e+02, -5.152815835931769e-01, 1.119618355504266e-02 +389, 1.534483417028177e+00, 1.190366264331290e+00, 1.222854720807530e+00, 5.577054749437055e+00, -2.541436161726267e-02, 2.531828208541186e+05, 1.998401444325282e-15, 7.345235530920036e-13, 1.295963336644945e-12, 1.746229827404022e-10, 1.012680411984180e+05, 2.884880913814087e+02, -4.506952698074768e+00, 1.339435367629963e-02 +390, 1.829099336969591e-01, 2.351285139077383e+00, 1.223317448071067e+00, 1.328846082381331e+01, 3.356811726832294e+00, 2.533894288907525e+05, -2.486899575160351e-14, -2.486899575160351e-13, -4.964917366123700e-13, -8.731149137020111e-11, 1.013250597608743e+05, 2.885413396228380e+02, 3.534023533250994e+00, 3.290145871304229e-02 +391, -6.913598222214584e-02, 1.042498198107496e+00, 1.222876256432757e+00, 7.032262932836409e+00, 8.433038884055474e+00, 2.532876392211631e+05, -1.602673549427891e-11, 7.883471653258312e-11, 1.064446308873812e-10, -5.995389074087143e-09, 1.012953367894937e+05, 2.885607680737268e+02, -6.576238198205105e-01, 2.636741708041083e-02 +392, -1.682914522547730e-01, 6.170965705268767e-01, 1.223754747729807e+00, 1.231669956173198e+00, 4.939940315727536e+00, 2.534577316522490e+05, -1.659783421814609e-12, 3.073608034753761e-11, -1.073452438049571e-11, 1.193257048726082e-09, 1.013788565145227e+05, 2.885913727133599e+02, 1.112064793720059e+01, 1.221610534985062e-02 +393, 5.961237982554469e-01, 1.268226813633758e+00, 1.223039982964709e+00, 7.706281463973058e+00, 2.822335250708385e+00, 2.532337558925546e+05, 7.263079027097774e-13, -4.449773882697627e-12, 1.301891927596444e-11, -2.910383045673370e-10, 1.012824884325046e+05, 2.884855425666623e+02, -2.469548370521844e+00, 1.970719666874278e-02 +EXT_ITER=, 600 +AOA=, 0.000000000000000e+00 +SIDESLIP_ANGLE=, 0.000000000000000e+00 +INITIAL_BCTHRUST=, 4.000000000000000e+03 +DCD_DCL_VALUE=, 0.000000000000000e+00 +DCMX_DCL_VALUE=, 0.000000000000000e+00 +DCMY_DCL_VALUE=, 0.000000000000000e+00 +DCMZ_DCL_VALUE=, 0.000000000000000e+00 diff --git a/perpendicular-flap/fluid-su2/run.sh b/perpendicular-flap/fluid-su2/run.sh index a827818b5..2272c4efd 100755 --- a/perpendicular-flap/fluid-su2/run.sh +++ b/perpendicular-flap/fluid-su2/run.sh @@ -1,8 +1,9 @@ -#!/bin/sh +#!/bin/bash set -e -u -if [ "${1:-}" = "-parallel" ]; then - mpirun -n 2 SU2_CFD euler_config_coupled.cfg -else - SU2_CFD euler_config_coupled.cfg -fi +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +SU2_preCICE_FSI.py -f euler_config_unsteady.cfg --parallel + +close_log diff --git a/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-all-watchpoints.png b/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-all-watchpoints.png deleted file mode 100644 index 7fc01ef55..000000000 Binary files a/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-all-watchpoints.png and /dev/null differ diff --git a/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-fake-watchpoints.png b/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-fake-watchpoints.png new file mode 100644 index 000000000..ce6e9550b Binary files /dev/null and b/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-fake-watchpoints.png differ diff --git a/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-flow-comparison-watchpoints.png b/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-flow-comparison-watchpoints.png new file mode 100644 index 000000000..d977bd92a Binary files /dev/null and b/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-flow-comparison-watchpoints.png differ diff --git a/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-nutils-watchpoints.png b/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-nutils-watchpoints.png new file mode 100644 index 000000000..ac6f0d2d5 Binary files /dev/null and b/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-nutils-watchpoints.png differ diff --git a/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-openfoam-watchpoints.png b/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-openfoam-watchpoints.png new file mode 100644 index 000000000..96be9c77c Binary files /dev/null and b/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-openfoam-watchpoints.png differ diff --git a/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-selected-watchpoints.png b/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-selected-watchpoints.png new file mode 100644 index 000000000..eedf4bc65 Binary files /dev/null and b/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-selected-watchpoints.png differ diff --git a/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-su2-watchpoints.png b/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-su2-watchpoints.png new file mode 100644 index 000000000..d44b6f913 Binary files /dev/null and b/perpendicular-flap/images/tutorials-perpendicular-flap-displacement-su2-watchpoints.png differ diff --git a/perpendicular-flap/images/tutorials-perpendicular-flap-precice-config.png b/perpendicular-flap/images/tutorials-perpendicular-flap-precice-config.png new file mode 100644 index 000000000..80439cdce Binary files /dev/null and b/perpendicular-flap/images/tutorials-perpendicular-flap-precice-config.png differ diff --git a/perpendicular-flap/metadata.yaml b/perpendicular-flap/metadata.yaml new file mode 100644 index 000000000..bde575268 --- /dev/null +++ b/perpendicular-flap/metadata.yaml @@ -0,0 +1,64 @@ +name: Perpendicular flap +path: perpendicular-flap +url: https://precice.org/tutorials-perpendicular-flap.html + +participants: + - Fluid + - Solid + +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 + + fluid-su2: + participant: Fluid + directory: ./fluid-su2 + run: ./run.sh + component: su2-adapter + + solid-calculix: + participant: Solid + directory: ./solid-calculix + run: ./run.sh + component: calculix-adapter + + # solid-dealii: + # participant: Solid + # directory: ./solid-dealii + # run: ./run.sh + # component: dealii-adapter + + # solid-dune: + # participant: Solid + # directory: ./solid-dune + # run: ./run.sh + # component: dune-adapter + + solid-fenics: + participant: Solid + directory: ./solid-fenics + run: ./run.sh + component: fenics-adapter + + solid-openfoam: + participant: Solid + directory: ./solid-openfoam + run: ./run.sh + component: openfoam-adapter + + # solid-solids4foam: + # participant: Solid + # directory: ./solid-solids4foam + # run: ./run.sh + # component: openfoam-adapter + + diff --git a/perpendicular-flap/plot-all-displacements.sh b/perpendicular-flap/plot-all-displacements.sh index bd18f6125..5b9b2f1bd 100755 --- a/perpendicular-flap/plot-all-displacements.sh +++ b/perpendicular-flap/plot-all-displacements.sh @@ -1,19 +1,109 @@ #!/bin/sh - -gnuplot -p << EOF - set grid - set title 'x-displacement of the flap tip' - set xlabel 'time [s]' - set ylabel 'x-displacement [m]' - set term pngcairo enhanced size 900,654 - set output "images/tutorials-perpendicular-flap-displacement-all-watchpoints.png" - plot "watchpoints/openfoam-calculix.log" using 1:4 with lines title "OpenFOAM-CalculiX", \ - "watchpoints/openfoam-dealii.log" using 1:4 with lines title "OpenFOAM-deal.II", \ - "watchpoints/openfoam-fenics.log" using 1:4 with lines title "OpenFOAM-FEniCS", \ - "watchpoints/su2-calculix.log" using 1:4 with lines title "SU2-CalculiX", \ - "watchpoints/su2-dealii.log" using 1:4 with lines title "SU2-deal.II", \ - "watchpoints/su2-fenics.log" using 1:4 with lines title "SU2-FEniCS", \ - "watchpoints/nutils-calculix.log" using 1:4 with lines title "Nutils-CalculiX", \ - "watchpoints/nutils-dealii.log" using 1:4 with lines title "Nutils-deal.II", \ - "watchpoints/nutils-fenics.log" using 1:4 with lines title "Nutils-FEniCS" + +# This script cannot be used as-is and is meant to generate the picture +# images/tutorials-perpendicular-flap-displacement-all-watchpoints.png +# rendered on https://precice.org/tutorials-perpendicular-flap.html. +# +# It plots watchpoints of specific combinations of Fluid and Solid participants, +# stored in `images/`. To use this script: +# 1. For each combination you want to plot: +# 1. Run the tutorial with that combination +# 2. Copy the respective watchpoint file to watchpoints/, with names -.log +# 3. Clean the tutorial +# 2. Edit the script to plot the files you want, with the corresponding titles, +# adding one line per combination. +# 3. Call the script with ./plot-all-displacements.sh, from this directory. +# +# If you are only interested in a subset of combinations, remove the respective lines. + +WATCHPOINTS_DIR="./reference-results/watchpoints/" + +gnuplot -p << EOF + set grid + set title 'x-displacement of the flap tip (selected combinations)' + set xlabel 'time [s]' + set ylabel 'x-displacement [m]' + set term pngcairo enhanced size 900,654 + set output "images/tutorials-perpendicular-flap-displacement-selected-watchpoints.png" + plot "${WATCHPOINTS_DIR}/openfoam-calculix-v2404.log" using 1:4 with lines title "OpenFOAM-CalculiX", \ + "${WATCHPOINTS_DIR}/openfoam-dealii-v2404.log" using 1:4 with lines title "OpenFOAM-deal.II", \ + "${WATCHPOINTS_DIR}/openfoam-fenics-v2404.log" using 1:4 with lines title "OpenFOAM-FEniCS", \ + "${WATCHPOINTS_DIR}/su2-calculix-v2404.log" using 1:4 with lines title "SU2-CalculiX", \ + "${WATCHPOINTS_DIR}/su2-dealii-v2404.log" using 1:4 with lines title "SU2-deal.II", \ + "${WATCHPOINTS_DIR}/su2-fenics-v2404.log" using 1:4 with lines title "SU2-FEniCS", \ + "${WATCHPOINTS_DIR}/nutils-calculix-v2404.log" using 1:4 with lines title "Nutils-CalculiX", \ + "${WATCHPOINTS_DIR}/nutils-dealii-v2404.log" using 1:4 with lines title "Nutils-deal.II" +EOF + +gnuplot -p << EOF + set grid + set title 'x-displacement of the flap tip (comparison of flow solvers)' + set xlabel 'time [s]' + set ylabel 'x-displacement [m]' + set term pngcairo enhanced size 900,654 + set output "images/tutorials-perpendicular-flap-displacement-flow-comparison-watchpoints.png" + plot "${WATCHPOINTS_DIR}/openfoam-calculix-v2404.log" using 1:4 with lines title "OpenFOAM-CalculiX", \ + "${WATCHPOINTS_DIR}/su2-calculix-v2404.log" using 1:4 with lines title "SU2-CalculiX", \ + "${WATCHPOINTS_DIR}/nutils-calculix-v2404.log" using 1:4 with lines title "Nutils-CalculiX", \ + "${WATCHPOINTS_DIR}/fake-calculix-v2404.log" using 1:4 with lines title "fake-CalculiX" +EOF + +gnuplot -p << EOF + set grid + set title 'x-displacement of the flap tip (incompressible flow with OpenFOAM)' + set xlabel 'time [s]' + set ylabel 'x-displacement [m]' + set term pngcairo enhanced size 900,654 + set output "images/tutorials-perpendicular-flap-displacement-openfoam-watchpoints.png" + plot "${WATCHPOINTS_DIR}/openfoam-calculix-v2404.log" using 1:4 with lines title "OpenFOAM-CalculiX", \ + "${WATCHPOINTS_DIR}/openfoam-dealii-v2404.log" using 1:4 with lines title "OpenFOAM-deal.II", \ + "${WATCHPOINTS_DIR}/openfoam-dune-v2404.log" using 1:4 with lines title "OpenFOAM-DUNE", \ + "${WATCHPOINTS_DIR}/openfoam-fenics-v2404.log" using 1:4 with lines title "OpenFOAM-FEniCS", \ + "${WATCHPOINTS_DIR}/openfoam-nutils-v2404.log" using 1:4 with lines title "OpenFOAM-Nutils", \ + "${WATCHPOINTS_DIR}/openfoam-solids4foam-v2404.log" using 1:4 with lines title "OpenFOAM-solids4Foam" +EOF + +gnuplot -p << EOF + set grid + set title 'x-displacement of the flap tip (compressible flow with SU2)' + set xlabel 'time [s]' + set ylabel 'x-displacement [m]' + set term pngcairo enhanced size 900,654 + set output "images/tutorials-perpendicular-flap-displacement-su2-watchpoints.png" + plot "${WATCHPOINTS_DIR}/su2-calculix-v2404.log" using 1:4 with lines title "SU2-CalculiX", \ + "${WATCHPOINTS_DIR}/su2-dealii-v2404.log" using 1:4 with lines title "SU2-deal.II", \ + "${WATCHPOINTS_DIR}/su2-dune-v2404.log" using 1:4 with lines title "SU2-DUNE", \ + "${WATCHPOINTS_DIR}/su2-fenics-v2404.log" using 1:4 with lines title "SU2-FEniCS", \ + "${WATCHPOINTS_DIR}/su2-nutils-v2404.log" using 1:4 with lines title "SU2-nutils", \ + "${WATCHPOINTS_DIR}/su2-solids4foam-v2404.log" using 1:4 with lines title "SU2-solids4Foam" +EOF + +gnuplot -p << EOF + set grid + set title 'x-displacement of the flap tip (incompressible flow with Nutils)' + set xlabel 'time [s]' + set ylabel 'x-displacement [m]' + set term pngcairo enhanced size 900,654 + set output "images/tutorials-perpendicular-flap-displacement-nutils-watchpoints.png" + plot "${WATCHPOINTS_DIR}/nutils-calculix-v2404.log" using 1:4 with lines title "Nutils-CalculiX", \ + "${WATCHPOINTS_DIR}/nutils-dealii-v2404.log" using 1:4 with lines title "Nutils-deal.II", \ + "${WATCHPOINTS_DIR}/nutils-dune-v2404.log" using 1:4 with lines title "Nutils-DUNE", \ + "${WATCHPOINTS_DIR}/nutils-fenics-v2404.log" using 1:4 with lines title "Nutils-FEniCS", \ + "${WATCHPOINTS_DIR}/nutils-nutils-v2404.log" using 1:4 with lines title "Nutils-Nutils", \ + "${WATCHPOINTS_DIR}/nutils-solids4foam-v2404.log" using 1:4 with lines title "Nutils-solids4Foam" +EOF + +gnuplot -p << EOF + set grid + set title 'x-displacement of the flap tip (dummy force data with fluid-fake)' + set xlabel 'time [s]' + set ylabel 'x-displacement [m]' + set term pngcairo enhanced size 900,654 + set output "images/tutorials-perpendicular-flap-displacement-fake-watchpoints.png" + plot "${WATCHPOINTS_DIR}/fake-calculix-v2404.log" using 1:4 with lines title "fake-CalculiX", \ + "${WATCHPOINTS_DIR}/fake-dealii-v2404.log" using 1:4 with lines title "fake-deal.II", \ + "${WATCHPOINTS_DIR}/fake-dune-v2404.log" using 1:4 with lines title "fake-DUNE", \ + "${WATCHPOINTS_DIR}/fake-fenics-v2404.log" using 1:4 with lines title "fake-FEniCS", \ + "${WATCHPOINTS_DIR}/fake-nutils-v2404.log" using 1:4 with lines title "fake-Nutils", \ + "${WATCHPOINTS_DIR}/fake-solids4foam-v2404.log" using 1:4 with lines title "fake-solids4Foam" EOF diff --git a/perpendicular-flap/precice-config.xml b/perpendicular-flap/precice-config.xml index 97ebd5afc..256d8b937 100644 --- a/perpendicular-flap/precice-config.xml +++ b/perpendicular-flap/precice-config.xml @@ -7,64 +7,58 @@ enabled="true" /> - - - + + - - - - + + + + - - - - + + + + - - - - - - - - + + + + + + + + + + + + - - - - - - + + + + + + - + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/perpendicular-flap/reference-results/fluid-openfoam_solid-calculix.tar.gz b/perpendicular-flap/reference-results/fluid-openfoam_solid-calculix.tar.gz new file mode 100644 index 000000000..cd2283654 --- /dev/null +++ b/perpendicular-flap/reference-results/fluid-openfoam_solid-calculix.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:863c5078f8068135a983b24433d8d71120c2fdd67d6ab93b9dc1a4642ee595ba +size 13532926 diff --git a/perpendicular-flap/reference-results/fluid-su2_solid-fenics.tar.gz b/perpendicular-flap/reference-results/fluid-su2_solid-fenics.tar.gz new file mode 100644 index 000000000..395091d43 --- /dev/null +++ b/perpendicular-flap/reference-results/fluid-su2_solid-fenics.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d74d72729eb88049f067eb794768948d01f58e0b8f0db7e542c2d9da0643c7b5 +size 3399058 diff --git a/perpendicular-flap/reference-results/watchpoints.tar.gz b/perpendicular-flap/reference-results/watchpoints.tar.gz new file mode 100644 index 000000000..076bd80d9 --- /dev/null +++ b/perpendicular-flap/reference-results/watchpoints.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f117eb1c0c1dcaa921442550533db8dc5077c45eb6632ede2b341470814d193c +size 337608 diff --git a/perpendicular-flap/reference_results.metadata b/perpendicular-flap/reference_results.metadata new file mode 100644 index 000000000..d9949e7ad --- /dev/null +++ b/perpendicular-flap/reference_results.metadata @@ -0,0 +1,64 @@ + + +# 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-su2_solid-fenics.tar.gz | 2024-04-13 12:00:34 | d74d72729eb88049f067eb794768948d01f58e0b8f0db7e542c2d9da0643c7b5 | +| fluid-openfoam_solid-calculix.tar.gz | 2024-04-13 12:00:34 | 863c5078f8068135a983b24433d8d71120c2fdd67d6ab93b9dc1a4642ee595ba | + +## List of arguments used to generate the files + +| name | value | +|------|------| +| PRECICE_REF | v3.1.1 | +| OPENFOAM_EXECUTABLE | openfoam2312 | +| OPENFOAM_ADAPTER_REF | v1.3.0 | +| PYTHON_BINDINGS_REF | v3.1.0 | +| FENICS_ADAPTER_REF | v2.1.0 | +| TUTORIALS_REF | 340b447 | +| PLATFORM | ubuntu_2204 | +| CALULIX_VERSION | 2.20 | +| CALULIX_ADAPTER_REF | v2.20.1 | +| SU2_VERSION | 7.5.1 | +| SU2_ADAPTER_REF | 64d4aff | +## Information about the machine + +### uname -a + +Linux precice-tests 5.15.0-101-generic #111-Ubuntu SMP Tue Mar 5 20:16:58 UTC 2024 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/solid-calculix/flap_modal.inp b/perpendicular-flap/solid-calculix/flap_modal.inp new file mode 100644 index 000000000..6a279b3f0 --- /dev/null +++ b/perpendicular-flap/solid-calculix/flap_modal.inp @@ -0,0 +1,28 @@ +*INCLUDE, INPUT=all.msh +*INCLUDE, INPUT=fix1_beam.nam +*INCLUDE, INPUT=interface_beam.nam +*MATERIAL, Name=EL +*ELASTIC + 4000000, 0.3 +*DENSITY + 3000 +*SOLID SECTION, Elset=Eall, Material=EL + +*BOUNDARY +Nfix1, 1, 3 +*BOUNDARY +Nall, 3 + +*STEP, INC=1000000 +*MODAL DYNAMIC DIRECT +1.E-2, 5.0 + +*CLOAD + Nsurface, 1, 0.0 + Nsurface, 2, 0.0 + Nsurface, 3, 0.0 +*NODE FILE + U +*EL FILE + S, E +*END STEP \ No newline at end of file diff --git a/perpendicular-flap/solid-calculix/frequency.inp b/perpendicular-flap/solid-calculix/frequency.inp new file mode 100644 index 000000000..f69e0e453 --- /dev/null +++ b/perpendicular-flap/solid-calculix/frequency.inp @@ -0,0 +1,32 @@ +*INCLUDE, INPUT=all.msh +*INCLUDE, INPUT=fix1_beam.nam +*INCLUDE, INPUT=interface_beam.nam +*MATERIAL, Name=EL +*ELASTIC + 4000000, 0.3 +*DENSITY + 3000 +*SOLID SECTION, Elset=Eall, Material=EL + +*BOUNDARY +Nfix1, 1, 3 +*BOUNDARY +Nall, 3 + +*STEP, INC=1000000 +*FREQUENCY, STORAGE=YES +10 +*END STEP +*NODE FILE + U +*EL FILE + S, E + +*CLOAD + Nsurface, 1, 0.0 + Nsurface, 2, 0.0 + Nsurface, 3, 0.0 +*NODE FILE + U +*EL FILE + S, E diff --git a/perpendicular-flap/solid-calculix/run.sh b/perpendicular-flap/solid-calculix/run.sh index 0cc701cc5..1954b6584 100755 --- a/perpendicular-flap/solid-calculix/run.sh +++ b/perpendicular-flap/solid-calculix/run.sh @@ -1,4 +1,24 @@ -#!/bin/sh +#!/bin/bash set -e -u -ccx_preCICE -i flap -precice-participant Solid +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +usage() { echo "Usage: run.sh [-modal]" 1>&2; exit 1; } + +# There must be either 0 arguments or 1, which is modal. +# Send an error otherwise +if [ $# -ge 2 ] || { [ $# -eq 1 ] && [ "$1" != "-modal" ]; }; then + usage +fi + +# No arg => regular simulation. Otherwise, it's modal +if [ $# -eq 0 ]; then + ccx_preCICE -i flap -precice-participant Solid +else + ccx_preCICE -i frequency + mv frequency.eig flap_modal.eig + ccx_preCICE -i flap_modal -precice-participant Solid +fi + +close_log diff --git a/perpendicular-flap/solid-dune/.gitignore b/perpendicular-flap/solid-dune/.gitignore new file mode 100644 index 000000000..0b3a1ebb9 --- /dev/null +++ b/perpendicular-flap/solid-dune/.gitignore @@ -0,0 +1 @@ +dune-perpendicular-flap diff --git a/perpendicular-flap/solid-dune/run.sh b/perpendicular-flap/solid-dune/run.sh index bbe2d648c..7cf8e187a 100755 --- a/perpendicular-flap/solid-dune/run.sh +++ b/perpendicular-flap/solid-dune/run.sh @@ -1,4 +1,9 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + ./dune-perpendicular-flap + +close_log diff --git a/perpendicular-flap/solid-fenics/run.sh b/perpendicular-flap/solid-fenics/run.sh index 15315c67d..6d5da4496 100755 --- a/perpendicular-flap/solid-fenics/run.sh +++ b/perpendicular-flap/solid-fenics/run.sh @@ -1,4 +1,9 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + python3 solid.py + +close_log diff --git a/perpendicular-flap/solid-fenics/solid.py b/perpendicular-flap/solid-fenics/solid.py index 8c571c0b6..dc07af7cc 100644 --- a/perpendicular-flap/solid-fenics/solid.py +++ b/perpendicular-flap/solid-fenics/solid.py @@ -1,8 +1,14 @@ +""" +This source code is based on https://gitlab.enpc.fr/jeremy.bleyer/comet-fenics/-/blob/master/examples/elastodynamics/demo_elastodynamics.py.rst + +See also: + Jeremy Bleyer. (2018). Numerical Tours of Computational Mechanics with FEniCS. Zenodo. https://doi.org/10.5281/zenodo.1287832 +""" + # Import required libs from fenics import Constant, Function, AutoSubDomain, RectangleMesh, VectorFunctionSpace, interpolate, \ - TrialFunction, TestFunction, Point, Expression, DirichletBC, nabla_grad, project, \ - Identity, inner, dx, ds, sym, grad, lhs, rhs, dot, File, solve, PointSource, assemble_system -from ufl import nabla_div + TrialFunction, TestFunction, Point, Expression, DirichletBC, project, \ + Identity, inner, dx, ds, sym, grad, div, lhs, rhs, dot, File, solve, assemble_system import numpy as np import matplotlib.pyplot as plt from fenicsprecice import Adapter @@ -52,7 +58,6 @@ def neumann_boundary(x, on_boundary): v = TestFunction(V) u_np1 = Function(V) -saved_u_old = Function(V) # function known from previous timestep u_n = Function(V) @@ -69,30 +74,43 @@ def neumann_boundary(x, on_boundary): precice = Adapter(adapter_config_filename="precice-adapter-config-fsi-s.json") # Initialize the coupling interface -precice_dt = precice.initialize(coupling_boundary, read_function_space=V, write_object=V, fixed_boundary=fixed_boundary) +precice.initialize(coupling_boundary, read_function_space=V, write_object=V, fixed_boundary=fixed_boundary) +precice_dt = precice.get_max_time_step_size() fenics_dt = precice_dt # if fenics_dt == precice_dt, no subcycling is applied -# fenics_dt = 0.02 # if fenics_dt < precice_dt, subcycling is applied +# n_substeps = 5 # number of substeps per window +# fenics_dt = precice_dt / n_substeps # if fenics_dt < precice_dt, subcycling is applied dt = Constant(np.min([precice_dt, fenics_dt])) # clamp the beam at the bottom bc = DirichletBC(V, Constant((0, 0)), fixed_boundary) # alpha method parameters -alpha_m = Constant(0) -alpha_f = Constant(0) +alpha_m = Constant(0.2) +alpha_f = Constant(0.4) +# alpha_m = Constant(0) +# alpha_f = Constant(0) + +""" +Check requirements for alpha_m and alpha_f from + Chung, J., and Hulbert, G. M. (June 1, 1993). "A Time Integration Algorithm for Structural Dynamics With Improved Numerical Dissipation: + The Generalized-α Method." ASME. J. Appl. Mech. June 1993; 60(2): 371–375. https://doi.org/10.1115/1.2900803 +""" +assert (float(alpha_m) <= float(alpha_f)) +assert (float(alpha_f) <= 0.5) + gamma = Constant(0.5 + alpha_f - alpha_m) beta = Constant((gamma + 0.5)**2 / 4.) # Define strain def epsilon(u): - return 0.5 * (nabla_grad(u) + nabla_grad(u).T) + return 0.5 * (grad(u) + grad(u).T) # Define Stress tensor def sigma(u): - return lambda_ * nabla_div(u) * Identity(dim) + 2 * mu * epsilon(u) + return lambda_ * div(u) * Identity(dim) + 2 * mu * epsilon(u) # Define Mass form @@ -174,15 +192,19 @@ def avg(x_old, x_new, alpha): u_n.rename("Displacement", "") u_np1.rename("Displacement", "") -displacement_out << u_n +displacement_out << (u_n, t) while precice.is_coupling_ongoing(): - if precice.is_action_required(precice.action_write_iteration_checkpoint()): # write checkpoint - precice.store_checkpoint(u_n, t, n) + if precice.requires_writing_checkpoint(): # write checkpoint + precice.store_checkpoint((u_n, v_n, a_n), t, n) + + precice_dt = precice.get_max_time_step_size() + dt = Constant(np.min([precice_dt, fenics_dt])) # read data from preCICE and get a new coupling expression - read_data = precice.read_data() + # sample force F at $F(t_{n+1-\alpha_f})$ (see generalized alpha paper) + read_data = precice.read_data((1 - float(alpha_f)) * dt) # Update the point sources on the coupling boundary with the new read data Forces_x, Forces_y = precice.get_point_sources(read_data) @@ -199,31 +221,32 @@ def avg(x_old, x_new, alpha): assert (b is not b_forces) solve(A, u_np1.vector(), b_forces) - dt = Constant(np.min([precice_dt, fenics_dt])) - # Write new displacements to preCICE precice.write_data(u_np1) # Call to advance coupling, also returns the optimum time step value - precice_dt = precice.advance(dt(0)) + precice.advance(float(dt)) # Either revert to old step if timestep has not converged or move to next timestep - if precice.is_action_required(precice.action_read_iteration_checkpoint()): # roll back to checkpoint - u_cp, t_cp, n_cp = precice.retrieve_checkpoint() + if precice.requires_reading_checkpoint(): # roll back to checkpoint + uva_cp, t_cp, n_cp = precice.retrieve_checkpoint() + u_cp, v_cp, a_cp = uva_cp u_n.assign(u_cp) + v_n.assign(v_cp) + a_n.assign(a_cp) t = t_cp n = n_cp else: + update_fields(u_np1, u_n, v_n, a_n) u_n.assign(u_np1) t += float(dt) n += 1 if precice.is_time_window_complete(): - update_fields(u_np1, saved_u_old, v_n, a_n) if n % 10 == 0: displacement_out << (u_n, t) # Plot tip displacement evolution -displacement_out << u_n +displacement_out << (u_n, t) precice.finalize() diff --git a/perpendicular-flap/solid-nutils/clean.sh b/perpendicular-flap/solid-nutils/clean.sh new file mode 100755 index 000000000..6893c1ea5 --- /dev/null +++ b/perpendicular-flap/solid-nutils/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_nutils . diff --git a/perpendicular-flap/solid-nutils/requirements.txt b/perpendicular-flap/solid-nutils/requirements.txt new file mode 100644 index 000000000..5b0938a20 --- /dev/null +++ b/perpendicular-flap/solid-nutils/requirements.txt @@ -0,0 +1,2 @@ +nutils>=8.5 +pyprecice==3 diff --git a/perpendicular-flap/solid-nutils/run.sh b/perpendicular-flap/solid-nutils/run.sh new file mode 100755 index 000000000..43cc739cd --- /dev/null +++ b/perpendicular-flap/solid-nutils/run.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 -m venv .venv +. .venv/bin/activate +pip install -r requirements.txt +python3 solid.py richoutput=no + +close_log diff --git a/perpendicular-flap/solid-nutils/solid.py b/perpendicular-flap/solid-nutils/solid.py new file mode 100644 index 000000000..3a76165ac --- /dev/null +++ b/perpendicular-flap/solid-nutils/solid.py @@ -0,0 +1,102 @@ +#! /usr/bin/env python3 + +from nutils import mesh, function, solver, export, cli +from nutils.expression_v2 import Namespace +import numpy +import treelog +import precice + + +def main(young=4e6, density=3e3, poisson=0.3, nelems=2, solver_dt=0.01, npoints_per_elem=3): + + topo, geom = mesh.rectilinear([numpy.linspace(-0.05, 0.05, nelems + 1), numpy.linspace(0, 1, 10 * nelems + 1)]) + wall = topo.boundary['left,top,right'].sample('uniform', npoints_per_elem) + + ns = Namespace() + ns.X = geom + ns.δ = function.eye(2) + ns.define_for('X', gradient='∇', normal='n', jacobians=('dV', 'dS')) + ns.add_field('dt') + ns.add_field(('u', 'u0', 'testu', 'v', 'v0', 'testv'), topo.basis('std', degree=1), shape=(2,)) + ns.add_field('F', wall.basis(), shape=(2,)) + ns.qw = 1 / npoints_per_elem # quadrature weight + ns.t_i = 'F_i / qw dS' + ns.dudt_i = '(u_i - u0_i) / dt' + ns.dvdt_i = '(v_i - v0_i) / dt' + ns.ρ = density + ns.λ = young * poisson / ((1 + poisson) * (1 - 2 * poisson)) + ns.μ = young / (2 * (1 + poisson)) + ns.σ_ij = 'λ ∇_k(u_k) δ_ij + μ (∇_j(u_i) + ∇_i(u_j))' + + # make sure we correctly scale point forces to tractions + test_force = numpy.random.normal(size=(wall.npoints, 2)) + numpy.testing.assert_almost_equal( + actual=wall.integrate('t_i dS' @ ns, F=test_force), + desired=test_force.sum(0), + decimal=10, + err_msg='nutils error: failed to recover net force', + ) + + # continuum equations: ρ v' = ∇·σ + F, u' = v + res = topo.integral('testv_i (dudt_i - v_i) dV' @ ns, degree=2) + res += topo.integral('(testu_i ρ dvdt_i + ∇_j(testu_i) σ_ij) dV' @ ns, degree=2) + res -= wall.integral('testu_i t_i dS' @ ns) + + # boundary conditions: fully constrained at y=0 + sqr = topo.boundary['bottom'].integral('u_k u_k' @ ns, degree=2) + cons = solver.optimize('u,', sqr, droptol=1e-10) + + # initial conditions: undeformed and unmoving + sqr = topo.integral('u_k u_k + v_k v_k' @ ns, degree=2) + arguments = solver.optimize('u,v', sqr, constrain=cons) + + # preCICE setup + solver_process_index = 0 + solver_process_size = 1 + participant = precice.Participant("Solid", "../precice-config.xml", solver_process_index, solver_process_size) + mesh_name = "Solid-Mesh" + vertex_ids = participant.set_mesh_vertices(mesh_name, wall.eval(ns.X)) + write_data_name = "Displacement" + read_data_name = "Force" + + # initialize preCICE + participant.initialize() + + timestep = 0 + force = numpy.zeros((wall.npoints, 2)) + + while participant.is_coupling_ongoing(): + with treelog.context(f'timestep {timestep}'): + + # save checkpoint + if participant.requires_writing_checkpoint(): + checkpoint = timestep, arguments + + precice_dt = participant.get_max_time_step_size() + dt = min(precice_dt, solver_dt) + + # read forces from participant at the end of the timestep + force = participant.read_data(mesh_name, read_data_name, vertex_ids, dt) + + # advance variables + timestep += 1 + + arguments = dict(dt=dt, u0=arguments['u'], v0=arguments['v'], F=force) + arguments = solver.solve_linear('u:testu,v:testv', res, arguments=arguments, constrain=cons) + + # write displacements to participant + write_data = wall.eval(ns.u, **arguments) + participant.write_data(mesh_name, write_data_name, vertex_ids, write_data) + + # do the coupling + participant.advance(dt) + + # read checkpoint if required + if participant.requires_reading_checkpoint(): + timestep, arguments = checkpoint + + participant.finalize() + + +if __name__ == '__main__': + cli.run(main) diff --git a/perpendicular-flap/solid-openfoam/0/D b/perpendicular-flap/solid-openfoam/0/D new file mode 100644 index 000000000..ee1780d12 --- /dev/null +++ b/perpendicular-flap/solid-openfoam/0/D @@ -0,0 +1,33 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + location "0"; + object D; +} + +dimensions [0 1 0 0 0 0 0]; + +internalField uniform (0 0 0); + +boundaryField +{ + interface + { + type solidDisplacementFoamForce; + forceField solidForce; + value uniform (0 0 0); + } + bottom + { + type fixedValue; + value uniform (0 0 0); + } + frontAndBack + { + type empty; + } +} + + diff --git a/perpendicular-flap/solid-openfoam/0/solidForce b/perpendicular-flap/solid-openfoam/0/solidForce new file mode 100644 index 000000000..0cb4e7ce8 --- /dev/null +++ b/perpendicular-flap/solid-openfoam/0/solidForce @@ -0,0 +1,32 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + location "0"; + object solidForce; +} + +dimensions [1 2 2 0 0 0 0]; + +internalField uniform (0 0 0); + +boundaryField +{ + interface + { + type calculated; + value uniform (0 0 0); + } + bottom + { + type calculated; + value uniform (0 0 0); + } + frontAndBack + { + type empty; + } +} + + diff --git a/perpendicular-flap/solid-openfoam/clean.sh b/perpendicular-flap/solid-openfoam/clean.sh new file mode 100755 index 000000000..c31d9fc76 --- /dev/null +++ b/perpendicular-flap/solid-openfoam/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . diff --git a/perpendicular-flap/solid-openfoam/constant/mechanicalProperties b/perpendicular-flap/solid-openfoam/constant/mechanicalProperties new file mode 100644 index 000000000..62109031b --- /dev/null +++ b/perpendicular-flap/solid-openfoam/constant/mechanicalProperties @@ -0,0 +1,29 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object mechanicalProperties; +} + +rho +{ + type uniform; + value 3000; +} + +nu +{ + type uniform; + value 0.3; +} + +E +{ + type uniform; + value 4e+6; +} + +planeStress no; + diff --git a/perpendicular-flap/solid-openfoam/constant/thermalProperties b/perpendicular-flap/solid-openfoam/constant/thermalProperties new file mode 100644 index 000000000..bce2052e9 --- /dev/null +++ b/perpendicular-flap/solid-openfoam/constant/thermalProperties @@ -0,0 +1,10 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object thermalProperties; +} + +thermalStress no; diff --git a/perpendicular-flap/solid-openfoam/run.sh b/perpendicular-flap/solid-openfoam/run.sh new file mode 100755 index 000000000..7996753e3 --- /dev/null +++ b/perpendicular-flap/solid-openfoam/run.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh + +# Compile boundary condition +(cd solidDisplacementFoamForce && wmake libso) + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/.gitignore b/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/.gitignore new file mode 100644 index 000000000..1729c7850 --- /dev/null +++ b/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/.gitignore @@ -0,0 +1,4 @@ +Make/* +!Make/files +!Make/options +lnInclude/ diff --git a/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/Make/files b/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/Make/files new file mode 100644 index 000000000..20cf11c08 --- /dev/null +++ b/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/Make/files @@ -0,0 +1,3 @@ +solidDisplacementFoamForceFvPatchVectorField.C + +LIB = $(FOAM_USER_LIBBIN)/libsolidDisplacementFoamForce diff --git a/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/Make/options b/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/Make/options new file mode 100644 index 000000000..ac23a670e --- /dev/null +++ b/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/Make/options @@ -0,0 +1,15 @@ +VERSION_SPECIFIC_INC = -DOPENFOAMESIORFOUNDATION +ifneq (,$(findstring v,$(WM_PROJECT_VERSION))) + VERSION_SPECIFIC_INC += -DOPENFOAMESI +else + VERSION_SPECIFIC_INC += -DOPENFOAMFOUNDATION +endif + +EXE_INC = \ + $(VERSION_SPECIFIC_INC) \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude + +LIB_LIBS = \ + -lfiniteVolume \ + -lmeshTools diff --git a/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/solidDisplacementFoamForceFvPatchVectorField.C b/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/solidDisplacementFoamForceFvPatchVectorField.C new file mode 100644 index 000000000..88c2cb44e --- /dev/null +++ b/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/solidDisplacementFoamForceFvPatchVectorField.C @@ -0,0 +1,250 @@ +#include "addToRunTimeSelectionTable.H" +#include "solidDisplacementFoamForceFvPatchVectorField.H" +#include "volFields.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam { + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +solidDisplacementFoamForceFvPatchVectorField:: + solidDisplacementFoamForceFvPatchVectorField( + const fvPatch &p, + const DimensionedField &iF) + : fixedGradientFvPatchVectorField(p, iF), + force_(p.size(), vector::zero), + forceFieldPtr_(), + curTimeIndex_(-1) +{ + fvPatchVectorField::operator=(patchInternalField()); + gradient() = vector::zero; +} + +solidDisplacementFoamForceFvPatchVectorField:: + solidDisplacementFoamForceFvPatchVectorField( + const fvPatch &p, + const DimensionedField &iF, + const dictionary &dict) + : fixedGradientFvPatchVectorField(p, iF), + force_(p.size(), vector::zero), + forceFieldPtr_(), + curTimeIndex_(-1) +{ + Info << "Creating " << type() << " boundary condition" << endl; + + if (dict.found("gradient")) { + gradient() = vectorField("gradient", dict, p.size()); + } else { + gradient() = vector::zero; + } + + if (dict.found("value")) { + Field::operator=(vectorField("value", dict, p.size())); + } else { + fvPatchVectorField::operator=(patchInternalField()); + } + + // Check how force is defined + if (dict.found("force") && dict.found("forceField")) { + FatalErrorIn( + "solidDisplacementFoamForceFvPatchVectorField::solidDisplacementFoamForceFvPatchVectorField") + << "Only force or forceField can be " + << "specified, not both!" + << abort(FatalError); + } else if (dict.found("forceField")) { + Info << " force is specified as a field" << endl; + forceFieldPtr_.reset( + new volVectorField( + IOobject( + word(dict.lookup("forceField")), + patch().boundaryMesh().mesh().time().timeName(), + patch().boundaryMesh().mesh(), + IOobject::MUST_READ, + IOobject::AUTO_WRITE), + patch().boundaryMesh().mesh())); + } else { + force_ = vectorField("force", dict, p.size()); + } +} + +solidDisplacementFoamForceFvPatchVectorField:: + solidDisplacementFoamForceFvPatchVectorField( + const solidDisplacementFoamForceFvPatchVectorField &stpvf, + const fvPatch &p, + const DimensionedField &iF, + const fvPatchFieldMapper &mapper) + : fixedGradientFvPatchVectorField(stpvf, p, iF, mapper), +#ifdef OPENFOAMFOUNDATION + force_(mapper(stpvf.force_)), +#else + force_(stpvf.force_, mapper), +#endif + forceFieldPtr_(), + curTimeIndex_(stpvf.curTimeIndex_) +{ +} + +#ifndef OPENFOAMFOUNDATION +solidDisplacementFoamForceFvPatchVectorField::solidDisplacementFoamForceFvPatchVectorField( + const solidDisplacementFoamForceFvPatchVectorField &stpvf) + : fixedGradientFvPatchVectorField(stpvf), + force_(stpvf.force_), + forceFieldPtr_(), + curTimeIndex_(stpvf.curTimeIndex_) +{ +} +#endif + +solidDisplacementFoamForceFvPatchVectorField::solidDisplacementFoamForceFvPatchVectorField( + const solidDisplacementFoamForceFvPatchVectorField &stpvf, + const DimensionedField &iF) + : fixedGradientFvPatchVectorField(stpvf, iF), + force_(stpvf.force_), + forceFieldPtr_(), + curTimeIndex_(stpvf.curTimeIndex_) +{ +} + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void solidDisplacementFoamForceFvPatchVectorField::autoMap( + const fvPatchFieldMapper &m) +{ + fixedGradientFvPatchVectorField::autoMap(m); + +#ifdef OPENFOAMFOUNDATION + m(force_, force_); +#else + force_.autoMap(m); +#endif +} + +// Reverse-map the given fvPatchField onto this fvPatchField +void solidDisplacementFoamForceFvPatchVectorField::rmap( + const fvPatchVectorField &ptf, + const labelList &addr) +{ + fixedGradientFvPatchVectorField::rmap(ptf, addr); + + const solidDisplacementFoamForceFvPatchVectorField &dmptf = + refCast(ptf); + + force_.rmap(dmptf.force_, addr); +} + +// Update the coefficients associated with the patch field +void solidDisplacementFoamForceFvPatchVectorField::updateCoeffs() +{ + if (updated()) { + return; + } + + if (curTimeIndex_ != db().time().timeIndex()) { + curTimeIndex_ = db().time().timeIndex(); + + // Called once per time-step + if (forceFieldPtr_.valid()) { + // Force the traction field boundary conditions to update + const_cast( + forceFieldPtr_()) + .correctBoundaryConditions(); + } + } + + if (forceFieldPtr_.valid()) { + force_ = forceFieldPtr_().boundaryField()[patch().index()]; + } + + // Convert the force field to a traction field + // Note: this assumes small strains / linear geometry + const vectorField traction(force_ / patch().magSf()); + + // Apply traction + // The code below comes from tractionDisplacement:updateCoeffs() + + const dictionary &mechanicalProperties = + db().lookupObject("mechanicalProperties"); + + const dictionary &thermalProperties = + db().lookupObject("thermalProperties"); + + const fvPatchField &rho = + patch().lookupPatchField("rho"); + + const fvPatchField &rhoE = + patch().lookupPatchField("E"); + + const fvPatchField &nu = + patch().lookupPatchField("nu"); + + const scalarField E(rhoE / rho); + const scalarField mu(E / (2.0 * (1.0 + nu))); + scalarField lambda(nu * E / ((1.0 + nu) * (1.0 - 2.0 * nu))); + scalarField threeK(E / (1.0 - 2.0 * nu)); + + if (mechanicalProperties.get("planeStress")) { + lambda = nu * E / ((1.0 + nu) * (1.0 - nu)); + threeK = E / (1.0 - nu); + } + + const scalarField twoMuLambda(2 * mu + lambda); + + const vectorField n(patch().nf()); + + const fvPatchField &sigmaD = + patch().lookupPatchField("sigmaD"); + + gradient() = + (traction / rho + twoMuLambda * fvPatchField::snGrad() - (n & sigmaD)) / twoMuLambda; + + if (thermalProperties.get("thermalStress")) { + const fvPatchField &threeKalpha = + patch().lookupPatchField("threeKalpha"); + + const fvPatchField &T = + patch().lookupPatchField("T"); + + gradient() += n * threeKalpha * T / twoMuLambda; + } + + fixedGradientFvPatchVectorField::updateCoeffs(); +} + +void solidDisplacementFoamForceFvPatchVectorField::write(Ostream &os) const +{ + // Bug-fix: courtesy of Michael@UW at https://www.cfd-online.com/Forums/ + // openfoam-cc-toolkits-fluid-structure-interaction/221892-solved-paraview + // -cant-read-solids-files-duplicate-entries-keyword-value.html#post762325 + // fixedGradientFvPatchVectorField::write(os); + fvPatchVectorField::write(os); + + if (forceFieldPtr_.valid()) { + os.writeKeyword("forceField") + << forceFieldPtr_().name() << token::END_STATEMENT << nl; + } else { +#ifdef OPENFOAMFOUNDATION + writeEntry(os, "force", force_); +#else + force_.writeEntry("force", os); +#endif + } + +#ifdef OPENFOAMFOUNDATION + writeEntry(os, "value", *this); + writeEntry(os, "gradient", gradient()); +#else + writeEntry("value", os); + gradient().writeEntry("gradient", os); +#endif +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +makePatchTypeField(fvPatchVectorField, solidDisplacementFoamForceFvPatchVectorField); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/solidDisplacementFoamForceFvPatchVectorField.H b/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/solidDisplacementFoamForceFvPatchVectorField.H new file mode 100644 index 000000000..8b29b4ed2 --- /dev/null +++ b/perpendicular-flap/solid-openfoam/solidDisplacementFoamForce/solidDisplacementFoamForceFvPatchVectorField.H @@ -0,0 +1,147 @@ +/*---------------------------------------------------------------------------*\ +License + This code is based on previous work of foam extend and solids4foam. + + This code is distributed under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + +Class + solidDisplacementFoamForceFvPatchVectorField + +Description + Force boundary condition for solidDisplacementFoam solvers, ported from + the solidForce condition in solids4foam. + + This is similar to tractionDisplacement except the absolute force per face + is specified. + + Note: this applies the force per face, not to the entire patch. + + Obviously, for a uniform force field, the total force applied to the patch + as the mesh is refined as the force per face stays constant. + + The primary motivation for this condition is for FSI cases using + solidDisplacementFoam and the preCICE coupling library. + + The force field can be directly specified or specified via a "force" + volVectorField, as used with preCICE. + +Author + Philip Cardiff, UCD. + +SourceFiles + solidDisplacementFoamForceFvPatchVectorField.C + +\*---------------------------------------------------------------------------*/ + +#ifndef solidDisplacementFoamForceFvPatchVectorField_H +#define solidDisplacementFoamForceFvPatchVectorField_H + +#include "fixedGradientFvPatchFields.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam { + +/*---------------------------------------------------------------------------*\ + Class solidDisplacementFoamForceFvPatchVectorField Declaration +\*---------------------------------------------------------------------------*/ + +class solidDisplacementFoamForceFvPatchVectorField + : public fixedGradientFvPatchVectorField { + + // Private Data + + //- Force + vectorField force_; + + //- Force field given as a vol field + autoPtr forceFieldPtr_; + + //- Current time index + label curTimeIndex_; + +public: + //- Runtime type information + TypeName("solidDisplacementFoamForce"); + + // Constructors + + //- Construct from patch and internal field + solidDisplacementFoamForceFvPatchVectorField( + const fvPatch &, + const DimensionedField &); + + //- Construct from patch, internal field and dictionary + solidDisplacementFoamForceFvPatchVectorField( + const fvPatch &, + const DimensionedField &, + const dictionary &); + + //- Construct by mapping given + // solidDisplacementFoamForceFvPatchVectorField onto a new patch + solidDisplacementFoamForceFvPatchVectorField( + const solidDisplacementFoamForceFvPatchVectorField &, + const fvPatch &, + const DimensionedField &, + const fvPatchFieldMapper &); + + //- Construct as copy + solidDisplacementFoamForceFvPatchVectorField( + const solidDisplacementFoamForceFvPatchVectorField & +#ifdef OPENFOAMFOUNDATION + ) = delete; +#else + ); + + //- Construct and return a clone + virtual tmp clone() const + { + return tmp( + new solidDisplacementFoamForceFvPatchVectorField(*this)); + } +#endif + + //- Construct as copy setting internal field reference + solidDisplacementFoamForceFvPatchVectorField( + const solidDisplacementFoamForceFvPatchVectorField &, + const DimensionedField &); + + //- Construct and return a clone setting internal field reference + virtual tmp clone( + const DimensionedField &iF) const + { + return tmp( + new solidDisplacementFoamForceFvPatchVectorField(*this, iF)); + } + + // Member functions + + // Mapping functions + + //- Map (and resize as needed) from self given a mapping object + virtual void autoMap( + const fvPatchFieldMapper &); + + //- Reverse map the given fvPatchField onto this fvPatchField + virtual void rmap( + const fvPatchVectorField &, + const labelList &); + + //- Update the coefficients associated with the patch field + virtual void updateCoeffs(); + + //- Write + virtual void write(Ostream &) const; +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/perpendicular-flap/solid-openfoam/system/blockMeshDict b/perpendicular-flap/solid-openfoam/system/blockMeshDict new file mode 100644 index 000000000..38b6334d0 --- /dev/null +++ b/perpendicular-flap/solid-openfoam/system/blockMeshDict @@ -0,0 +1,55 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +convertToMeters 0.01; + +vertices +( + (-5 0 0) + (5 0 0) + (5 100 0) + (-5 100 0) + + (-5 0 100) + (5 0 100) + (5 100 100) + (-5 100 100) +); + +blocks +( + hex (0 1 2 3 4 5 6 7) (6 15 1) simpleGrading (1 1 1) +); + +edges +( +); + +patches +( + patch interface + ( + (4 7 3 0) + (7 6 2 3) + (1 2 6 5) + ) + patch bottom + ( + (0 1 5 4) + ) + empty frontAndBack + ( + (3 2 1 0) + (4 5 6 7) + ) +); + +mergePatchPairs +( +); + diff --git a/perpendicular-flap/solid-openfoam/system/controlDict b/perpendicular-flap/solid-openfoam/system/controlDict new file mode 100644 index 000000000..edc77c791 --- /dev/null +++ b/perpendicular-flap/solid-openfoam/system/controlDict @@ -0,0 +1,50 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object controlDict; +} + +libs ("libsolidDisplacementFoamForce.so"); + +application solidDisplacementFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 5; + +deltaT 0.01; + +writeControl adjustableRunTime; + +writeInterval 0.1; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + libs ("libpreciceAdapterFunctionObject.so"); + } +} + + + diff --git a/perpendicular-flap/solid-openfoam/system/decomposeParDict b/perpendicular-flap/solid-openfoam/system/decomposeParDict new file mode 100644 index 000000000..ec722a896 --- /dev/null +++ b/perpendicular-flap/solid-openfoam/system/decomposeParDict @@ -0,0 +1,10 @@ +numberOfSubdomains 4; + +method simple; + +simpleCoeffs +{ + n (1 4 1); + delta 0.001; +} + diff --git a/perpendicular-flap/solid-openfoam/system/fvSchemes b/perpendicular-flap/solid-openfoam/system/fvSchemes new file mode 100644 index 000000000..018f7cda9 --- /dev/null +++ b/perpendicular-flap/solid-openfoam/system/fvSchemes @@ -0,0 +1,48 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} + +d2dt2Schemes +{ + default Euler; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default leastSquares; + grad(D) leastSquares; + grad(T) leastSquares; +} + +divSchemes +{ + default none; + div(sigmaD) Gauss linear; +} + +laplacianSchemes +{ + default none; + laplacian(DD,D) Gauss linear corrected; + laplacian(DT,T) Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default none; +} diff --git a/perpendicular-flap/solid-openfoam/system/fvSolution b/perpendicular-flap/solid-openfoam/system/fvSolution new file mode 100644 index 000000000..01600ef6e --- /dev/null +++ b/perpendicular-flap/solid-openfoam/system/fvSolution @@ -0,0 +1,30 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} + +solvers +{ + "(D|T)" + { + solver GAMG; + tolerance 1e-06; + relTol 0.9; + smoother GaussSeidel; + nCellsInCoarsestLevel 20; + } +} + +stressAnalysis +{ + compactNormalStress yes; + // Note: The accuracy of the solution can be significantly improved + // by increasing this number of iterations, but this will impact the runtime. + nCorrectors 30; + D 1e-06; +} + diff --git a/perpendicular-flap/solid-openfoam/system/preciceDict b/perpendicular-flap/solid-openfoam/system/preciceDict new file mode 100644 index 000000000..f0b1299e9 --- /dev/null +++ b/perpendicular-flap/solid-openfoam/system/preciceDict @@ -0,0 +1,50 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Solid; + +modules (FSI); + +interfaces +{ + Interface1 + { + mesh Solid-Mesh; + patches (interface); + locations faceCenters; + + readData + ( + Force + ); + + writeData + ( + Displacement + ); + }; +}; + +FSI +{ + solverType solid; + + // Name of cell displacement field + nameCellDisplacement D; + + // The solidDisplacementFoam does not have a point displacement field so we + // we use the special name "unused", which tells the adapter that it is not + // used + namePointDisplacement unused; + + // Name of the force field on the solid + nameForce solidForce; +} diff --git a/perpendicular-flap/solid-solids4foam/0/D b/perpendicular-flap/solid-solids4foam/0/D new file mode 100644 index 000000000..a05796b01 --- /dev/null +++ b/perpendicular-flap/solid-solids4foam/0/D @@ -0,0 +1,33 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + location "0"; + object D; +} + +dimensions [0 1 0 0 0 0 0]; + +internalField uniform (0 0 0); + +boundaryField +{ + interface + { + type solidForce; + forceField solidForce; + value uniform (0 0 0); + } + bottom + { + type fixedDisplacement; + value uniform (0 0 0); + } + frontAndBack + { + type empty; + } +} + + diff --git a/perpendicular-flap/solid-solids4foam/0/solidForce b/perpendicular-flap/solid-solids4foam/0/solidForce new file mode 100644 index 000000000..0cb4e7ce8 --- /dev/null +++ b/perpendicular-flap/solid-solids4foam/0/solidForce @@ -0,0 +1,32 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + location "0"; + object solidForce; +} + +dimensions [1 2 2 0 0 0 0]; + +internalField uniform (0 0 0); + +boundaryField +{ + interface + { + type calculated; + value uniform (0 0 0); + } + bottom + { + type calculated; + value uniform (0 0 0); + } + frontAndBack + { + type empty; + } +} + + diff --git a/perpendicular-flap/solid-solids4foam/clean.sh b/perpendicular-flap/solid-solids4foam/clean.sh new file mode 100755 index 000000000..c31d9fc76 --- /dev/null +++ b/perpendicular-flap/solid-solids4foam/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . diff --git a/perpendicular-flap/solid-solids4foam/constant/dynamicMeshDict b/perpendicular-flap/solid-solids4foam/constant/dynamicMeshDict new file mode 100644 index 000000000..e88696b3d --- /dev/null +++ b/perpendicular-flap/solid-solids4foam/constant/dynamicMeshDict @@ -0,0 +1,10 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object dynamicMeshDict; +} + +dynamicFvMesh staticFvMesh; + diff --git a/perpendicular-flap/solid-solids4foam/constant/g b/perpendicular-flap/solid-solids4foam/constant/g new file mode 100644 index 000000000..d5501f04c --- /dev/null +++ b/perpendicular-flap/solid-solids4foam/constant/g @@ -0,0 +1,12 @@ +FoamFile +{ + version 2.0; + format ascii; + class uniformDimensionedVectorField; + location "constant"; + object g; +} + +dimensions [0 1 -2 0 0 0 0]; +value ( 0 0 0 ); + diff --git a/perpendicular-flap/solid-solids4foam/constant/mechanicalProperties b/perpendicular-flap/solid-solids4foam/constant/mechanicalProperties new file mode 100644 index 000000000..74b76dc44 --- /dev/null +++ b/perpendicular-flap/solid-solids4foam/constant/mechanicalProperties @@ -0,0 +1,21 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object mechanicalProperties; +} + +planeStress no; + +mechanical +( + rubber + { + type linearElastic; + rho rho [1 -3 0 0 0 0 0] 3000; + E E [1 -1 -2 0 0 0 0] 4e6; + nu nu [0 0 0 0 0 0 0] 0.3; + } +); + diff --git a/perpendicular-flap/solid-solids4foam/constant/physicsProperties b/perpendicular-flap/solid-solids4foam/constant/physicsProperties new file mode 100644 index 000000000..4d7820de1 --- /dev/null +++ b/perpendicular-flap/solid-solids4foam/constant/physicsProperties @@ -0,0 +1,12 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object physicsProperties; +} + +type solid; + + diff --git a/perpendicular-flap/solid-solids4foam/constant/solidProperties b/perpendicular-flap/solid-solids4foam/constant/solidProperties new file mode 100644 index 000000000..183eead5c --- /dev/null +++ b/perpendicular-flap/solid-solids4foam/constant/solidProperties @@ -0,0 +1,25 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object solidProperties; +} + +solidModel linearGeometryTotalDisplacement; + +linearGeometryTotalDisplacementCoeffs +{ + // Maximum number of momentum correctors + nCorrectors 1000; + + // Solution tolerance for displacement + solutionTolerance 1e-08; + + // Alternative solution tolerance for displacement + alternativeTolerance 1e-08; + + // Write frequency for the residuals + infoFrequency 100; +} + diff --git a/perpendicular-flap/solid-solids4foam/run.sh b/perpendicular-flap/solid-solids4foam/run.sh new file mode 100755 index 000000000..4f2b797ab --- /dev/null +++ b/perpendicular-flap/solid-solids4foam/run.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/perpendicular-flap/solid-solids4foam/system/blockMeshDict b/perpendicular-flap/solid-solids4foam/system/blockMeshDict new file mode 100644 index 000000000..38b6334d0 --- /dev/null +++ b/perpendicular-flap/solid-solids4foam/system/blockMeshDict @@ -0,0 +1,55 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +convertToMeters 0.01; + +vertices +( + (-5 0 0) + (5 0 0) + (5 100 0) + (-5 100 0) + + (-5 0 100) + (5 0 100) + (5 100 100) + (-5 100 100) +); + +blocks +( + hex (0 1 2 3 4 5 6 7) (6 15 1) simpleGrading (1 1 1) +); + +edges +( +); + +patches +( + patch interface + ( + (4 7 3 0) + (7 6 2 3) + (1 2 6 5) + ) + patch bottom + ( + (0 1 5 4) + ) + empty frontAndBack + ( + (3 2 1 0) + (4 5 6 7) + ) +); + +mergePatchPairs +( +); + diff --git a/perpendicular-flap/solid-solids4foam/system/controlDict b/perpendicular-flap/solid-solids4foam/system/controlDict new file mode 100644 index 000000000..386a0d0fa --- /dev/null +++ b/perpendicular-flap/solid-solids4foam/system/controlDict @@ -0,0 +1,48 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object controlDict; +} + +application solids4Foam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 5; + +deltaT 0.01; + +writeControl adjustableRunTime; + +writeInterval 0.1; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + libs ("libpreciceAdapterFunctionObject.so"); + } +} + + + diff --git a/perpendicular-flap/solid-solids4foam/system/decomposeParDict b/perpendicular-flap/solid-solids4foam/system/decomposeParDict new file mode 100644 index 000000000..ec722a896 --- /dev/null +++ b/perpendicular-flap/solid-solids4foam/system/decomposeParDict @@ -0,0 +1,10 @@ +numberOfSubdomains 4; + +method simple; + +simpleCoeffs +{ + n (1 4 1); + delta 0.001; +} + diff --git a/perpendicular-flap/solid-solids4foam/system/fvSchemes b/perpendicular-flap/solid-solids4foam/system/fvSchemes new file mode 100644 index 000000000..87d288970 --- /dev/null +++ b/perpendicular-flap/solid-solids4foam/system/fvSchemes @@ -0,0 +1,51 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSchemes; +} + +d2dt2Schemes +{ + default backward; +} + +ddtSchemes +{ + default backward; +} + +gradSchemes +{ + default extendedLeastSquares 0; +} + +divSchemes +{ + default Gauss linear; +} + +laplacianSchemes +{ + default none; + laplacian(DD,D) Gauss linear corrected; + laplacian(DDD,DD) Gauss linear corrected; +} + +snGradSchemes +{ + default none; + snGrad(D) corrected; + snGrad(DD) corrected; +} + +interpolationSchemes +{ + default none; + interpolate(impK) linear; + interpolate(grad(D)) linear; + interpolate(grad(DD)) linear; + interpolate(sigma0) linear; +} + diff --git a/perpendicular-flap/solid-solids4foam/system/fvSolution b/perpendicular-flap/solid-solids4foam/system/fvSolution new file mode 100644 index 000000000..69fc05a9c --- /dev/null +++ b/perpendicular-flap/solid-solids4foam/system/fvSolution @@ -0,0 +1,38 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} + +solvers +{ + "D|DD" + { + solver PCG; + preconditioner FDIC; + tolerance 1e-09; + relTol 0.1; + } +} + +relaxationFactors +{ + // Under-relaxating the D equation by 0.99-0.9999 can improve convergence in + // some cases, in particular when there are solidContact boundaries + equations + { + //D 0.999; + } + + // Under-relaxating the D field by 0.1-0.9 can improve convergence in some + // cases + fields + { + //D 0.9; + } +} + + diff --git a/perpendicular-flap/solid-solids4foam/system/preciceDict b/perpendicular-flap/solid-solids4foam/system/preciceDict new file mode 100644 index 000000000..4c08dd9e4 --- /dev/null +++ b/perpendicular-flap/solid-solids4foam/system/preciceDict @@ -0,0 +1,46 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Solid; + +modules (FSI); + +interfaces +{ + Interface1 + { + mesh Solid-Mesh; + patches (interface); + locations faceCenters; + + readData + ( + Force + ); + + writeData + ( + Displacement + ); + }; +}; + +FSI +{ + solverType solid; + + // Name of displacement fields + namePointDisplacement pointD; + nameCellDisplacement D; + + // Name of the force field on the solid + nameForce solidForce; +} diff --git a/quickstart/README.md b/quickstart/README.md index 92fec9817..bd46a3015 100644 --- a/quickstart/README.md +++ b/quickstart/README.md @@ -14,28 +14,35 @@ toc: false This is the first step you may want to try if you are new to preCICE: install preCICE and some solvers, and run a simple coupled case. -To get a feeling what preCICE does, watch a [short presentation](https://www.youtube.com/watch?v=FCv2FNUvKA8), a [longer talk on the fundamentals](https://www.youtube.com/watch?v=9EDFlgfpGBs), or [click through a tutorial in your browser](http://run.precice.org/). +To get a feeling what preCICE does, watch a [short presentation](https://www.youtube.com/watch?v=FCv2FNUvKA8) or a [longer talk on the fundamentals](https://www.youtube.com/watch?v=9EDFlgfpGBs). ## Installation -1. Get and install preCICE. For Ubuntu 20.04 (Focal Fossa), this is pretty easy: [download](https://github.com/precice/precice/releases/latest) and install our binary package by clicking on it or using the following commands: +1. Get and install preCICE. For Ubuntu 22.04 (Jammy Jellyfish), this is pretty easy: [download](https://github.com/precice/precice/releases/latest) and install our binary package by clicking on it or using the following commands: ```bash - wget https://github.com/precice/precice/releases/download/v2.4.0/libprecice2_2.4.0_focal.deb - sudo apt install ./libprecice2_2.4.0_focal.deb + wget https://github.com/precice/precice/releases/download/v3.1.1/libprecice3_3.1.1_jammy.deb + sudo apt install ./libprecice3_3.1.1_jammy.deb ``` - - Are you using something else? Just pick what suits you best on [this overview page](https://precice.org/installation-overview.html). + | OS | Package | + | --- | --- | + | Ubuntu 20.04 Focal Fossa | [`libprecice3_3.1.1_focal.deb`](https://github.com/precice/precice/releases/download/v3.1.1/libprecice3_3.1.1_focal.deb) | + | Ubuntu 22.04 Jammy Jellyfish | [`libprecice3_3.1.1_jammy.deb`](https://github.com/precice/precice/releases/download/v3.1.1/libprecice3_3.1.1_jammy.deb) | + | Debian 11 "bullseye" | [`libprecice3_3.1.1_bullseye.deb`](https://github.com/precice/precice/releases/download/v3.1.1/libprecice3_3.1.1_bullseye.deb) | + | Debian 12 "bookworm" | [`libprecice3_3.1.1_bookworm.deb`](https://github.com/precice/precice/releases/download/v3.1.1/libprecice3_3.1.1_bookworm.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): ```bash # Add the signing key, add the repository, update (check this): wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | sudo bash - # Install OpenFOAM v2112: - sudo apt install openfoam2112-dev + # Install OpenFOAM v2312: + sudo apt install openfoam2312-dev # Enable OpenFOAM by default in your system and apply now: - echo "source /usr/lib/openfoam/openfoam2112/etc/bashrc" >> ~/.bashrc + echo "source /usr/lib/openfoam/openfoam2312/etc/bashrc" >> ~/.bashrc source ~/.bashrc ``` @@ -48,8 +55,9 @@ To get a feeling what preCICE does, watch a [short presentation](https://www.you 4. Download and install the [OpenFOAM-preCICE adapter](https://precice.org/adapter-openfoam-get.html): ```bash - git clone --branch=master --depth 1 https://github.com/precice/openfoam-adapter - cd openfoam-adapter + wget https://github.com/precice/openfoam-adapter/archive/refs/tags/v1.3.0.tar.gz + tar -xzf v1.3.0.tar.gz + cd openfoam-adapter-1.3.0/ ./Allwmake cd .. ``` @@ -57,7 +65,8 @@ To get a feeling what preCICE does, watch a [short presentation](https://www.you 5. Get the quickstart tutorial case: ```bash - git clone --branch=master --depth 1 https://github.com/precice/tutorials.git + wget https://github.com/precice/tutorials/releases/tag/v202404.0 + tar -xzf v202404.0.tar.gz cd tutorials/quickstart ``` @@ -71,6 +80,12 @@ In order to gain more control over the rigid body oscillation, a rotational spri ![overview](images/quickstart-setup.png) +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/quickstart-precice-config.png) + ## Building the rigid body solver Before starting the coupled simulation, we need to build the rigid body solver. You can run the following commands from the `solid-cpp` directory to build the `rigid_body_solver.cpp`: @@ -105,7 +120,7 @@ In serial, the simulation should take less than a minute to compute (simulated t 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! 🎉 -You may be curious what displacements OpenFOAM received from the rigid body solver. We can actually easily visualize the coupling meshes, including the exchanged coupling data: preCICE generates the relevant files during the simulation and stores them in the directory `solid-cpp/coupling-meshes`. Load these VTK files in ParaView and apply a `Glyph` filter with `Glyph Type: Arrow`,`Orientation Array: Displacement`, and `Scale Array: No scale array`. You can further add a `Warp By Vector` filter with `Displacement` to deform the coupling data. The result should look as follows: +You may be curious what displacements OpenFOAM received from the rigid body solver. We can actually easily visualize the coupling meshes, including the exchanged coupling data: preCICE generates the relevant files during the simulation and stores them in the directory `solid-cpp/precice-exports`. Load these VTK files in ParaView and apply a `Glyph` filter with `Glyph Type: Arrow`,`Orientation Array: Displacement`, and `Scale Array: No scale array`. You can further add a `Warp By Vector` filter with `Displacement` to deform the coupling data. The result should look as follows: ![result](images/quickstart-result.png) diff --git a/quickstart/fluid-openfoam/run.sh b/quickstart/fluid-openfoam/run.sh index c191b9e48..40cd648cf 100755 --- a/quickstart/fluid-openfoam/run.sh +++ b/quickstart/fluid-openfoam/run.sh @@ -1,8 +1,13 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + blockMesh -touch fluid-openfoam.foam ../../tools/run-openfoam.sh "$@" + . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/quickstart/images/quickstart-precice-config.png b/quickstart/images/quickstart-precice-config.png new file mode 100644 index 000000000..454847f13 Binary files /dev/null and b/quickstart/images/quickstart-precice-config.png differ diff --git a/quickstart/precice-config.xml b/quickstart/precice-config.xml index e33d690a7..213416ba8 100644 --- a/quickstart/precice-config.xml +++ b/quickstart/precice-config.xml @@ -1,4 +1,4 @@ - + - - - + + - - - - + + + + - - - - + + + + - - - - - - - - + + + + + + + + + + + + - - - - - - - + + + + + + + - + - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/quickstart/solid-cpp/.gitignore b/quickstart/solid-cpp/.gitignore new file mode 100644 index 000000000..01e69efeb --- /dev/null +++ b/quickstart/solid-cpp/.gitignore @@ -0,0 +1,5 @@ +CMakeFiles/ +cmake_install.cmake +CMakeCache.txt +Makefile +rigid_body_solver diff --git a/quickstart/solid-cpp/CMakeLists.txt b/quickstart/solid-cpp/CMakeLists.txt index 5f4f81702..bc5e9f3e4 100644 --- a/quickstart/solid-cpp/CMakeLists.txt +++ b/quickstart/solid-cpp/CMakeLists.txt @@ -7,7 +7,7 @@ SET(CMAKE_CXX_STANDARD 14) SET(CMAKE_CXX_EXTENSIONS OFF) SET(CMAKE_CXX_STANDARD_REQUIRED ON) -FIND_PACKAGE(precice REQUIRED CONFIG) +FIND_PACKAGE(precice 3.0 REQUIRED CONFIG) ADD_EXECUTABLE( ${TARGET} ${TARGET}.cpp) diff --git a/quickstart/solid-cpp/clean.sh b/quickstart/solid-cpp/clean.sh index a0ed77ed3..4c864fb36 100755 --- a/quickstart/solid-cpp/clean.sh +++ b/quickstart/solid-cpp/clean.sh @@ -3,5 +3,5 @@ set -e -u . ../../tools/cleaning-tools.sh -rm -rfv coupling-meshes clean_precice_logs . +clean_case_logs . diff --git a/quickstart/solid-cpp/rigid_body_solver.cpp b/quickstart/solid-cpp/rigid_body_solver.cpp index e0af5aefc..1c3aa3473 100644 --- a/quickstart/solid-cpp/rigid_body_solver.cpp +++ b/quickstart/solid-cpp/rigid_body_solver.cpp @@ -1,32 +1,39 @@ #include #include -#include #include +#include +// Include precice +#include using Vector = std::vector; struct DataContainer { void save_old_state(const Vector &vertices, const double &theta, - const double &theta_dot) + const double &theta_dot, + const double &time) { old_vertices = vertices; old_theta = theta; old_theta_dot = theta_dot; + old_time = time; } void reload_old_state(Vector &vertices, double &theta, - double &theta_dot) const + double &theta_dot, + double &time) const { vertices = old_vertices; theta = old_theta; theta_dot = old_theta_dot; + time = old_time; } Vector old_vertices; double old_theta; double old_theta_dot; + double old_time; }; class Solver { @@ -39,9 +46,9 @@ class Solver { void solve(const Vector &forces, const Vector &initial_vertices, - Vector & vertices, - double & theta, - double & theta_dot, + Vector &vertices, + double &theta, + double &theta_dot, const double spring_constant, const double delta_t) const { @@ -93,7 +100,7 @@ int main() // Mesh configuration constexpr int vertical_refinement = 3; constexpr int horizontal_refinement = 6; - // Rotation centre is at (0,0) + // Rotation center is at (0,0) constexpr double length = 0.2; constexpr double height = 0.02; @@ -108,26 +115,23 @@ int main() // Derived quantities constexpr int n_vertical_nodes = vertical_refinement * 2 + 1; constexpr int n_horizontal_nodes = horizontal_refinement * 2 + 1; - // Substract shared nodes at each rigid body corner + // Subtract shared nodes at each rigid body corner constexpr int n_nodes = (n_vertical_nodes + n_horizontal_nodes - 2) * 2; constexpr double mass = length * height * density; // The moment of inertia is computed according to the rigid body configuration: // a thin rectangular plate of height h, length l and mass m with axis of rotation // at the end of the plate: I = (1/12)*m*(4*l^2+h^2) - constexpr double inertia_moment = (1. / 12) * mass * (4 * std::pow(length, 2) + std::pow(height, 2)); + constexpr double inertia_moment = (1. / 12) * mass * (4 * length * length + height * height); constexpr double delta_y = height / (n_vertical_nodes - 1); constexpr double delta_x = length / (n_horizontal_nodes - 1); - // Create Solverinterface - precice::SolverInterface precice(solver_name, - config_file_name, - /*comm_rank*/ 0, - /*comm_size*/ 1); + // Create Participant + precice::Participant precice(solver_name, + config_file_name, + /*comm_rank*/ 0, + /*comm_size*/ 1); - const int mesh_id = precice.getMeshID(mesh_name); - const int dim = precice.getDimensions(); - const int write_id = precice.getDataID(data_write_name, mesh_id); - const int read_id = precice.getDataID(data_read_name, mesh_id); + const int dim = precice.getMeshDimensions(mesh_name); // Set up data structures Vector forces(dim * n_nodes); @@ -177,19 +181,28 @@ int main() const Vector initial_vertices = vertices; // Pass the vertices to preCICE - precice.setMeshVertices(mesh_id, - n_nodes, - vertices.data(), - vertex_ids.data()); + precice.setMeshVertices(mesh_name, + vertices, + vertex_ids); - // initialize the Solverinterface - double dt = precice.initialize(); + // we don't set any mesh connectivity here // Compute the absolute displacement between the current vertices and the // initial configuration. Here, this is mostly done for consistency reasons. for (uint i = 0; i < displacement.size(); ++i) displacement[i] = vertices[i] - initial_vertices[i]; + // Not required by the configuration, but we do it here for completeness + if (precice.requiresInitialData()) { + precice.writeData(mesh_name, + data_write_name, + vertex_ids, + displacement); + } + + // initialize precice + precice.initialize(); + // Set up a struct in order to store time dependent values DataContainer data_container; // Set up an object which handles the time integration @@ -199,55 +212,50 @@ int main() double time = 0; while (precice.isCouplingOngoing()) { - std::cout << "Rigid body: t = " << time << "s \n"; - - std::cout << "Rigid body: reading initial data \n"; - if (precice.isReadDataAvailable()) - precice.readBlockVectorData(read_id, - n_nodes, - vertex_ids.data(), - forces.data()); - // Store time dependent values - if (precice.isActionRequired( - precice::constants::actionWriteIterationCheckpoint())) { - data_container.save_old_state(vertices, theta, theta_dot); + if (precice.requiresWritingCheckpoint()) + data_container.save_old_state(vertices, theta, theta_dot, time); - precice.markActionFulfilled( - precice::constants::actionWriteIterationCheckpoint()); - } + // We don't introduce a solver-specific time-step size here + double dt = precice.getMaxTimeStepSize(); + time += dt; + std::cout << "Rigid body: t = " << time << "s \n"; + + std::cout << "Rigid body: reading coupling data \n"; + // We use an explicit time integration scheme, thus we always read data + // at the beginning of a time window (0) + precice.readData(mesh_name, + data_read_name, + vertex_ids, + 0, + forces); const double current_spring = time > switch_time ? spring_constant * stiffening_factor : spring_constant; // Solve system solver.solve(forces, initial_vertices, vertices, theta, theta_dot, current_spring, dt); // Advance coupled system - // Compute absolute displacement with respect to the initial configuration + // Compute absolute displacement with respect to the initial configuration (write data) for (uint i = 0; i < displacement.size(); ++i) displacement[i] = vertices[i] - initial_vertices[i]; std::cout << "Rigid body: writing coupling data \n"; - if (precice.isWriteDataRequired(dt)) - precice.writeBlockVectorData(write_id, - n_nodes, - vertex_ids.data(), - displacement.data()); + precice.writeData(mesh_name, + data_write_name, + vertex_ids, + displacement); std::cout << "Rigid body: advancing in time\n"; - dt = precice.advance(dt); + precice.advance(dt); // Reload time dependent values - if (precice.isActionRequired( - precice::constants::actionReadIterationCheckpoint())) { - data_container.reload_old_state(vertices, theta, theta_dot); - - precice.markActionFulfilled( - precice::constants::actionReadIterationCheckpoint()); - } + if (precice.requiresReadingCheckpoint()) + data_container.reload_old_state(vertices, theta, theta_dot, time); // Increment time in case the time window has been completed - if (precice.isTimeWindowComplete()) - time += dt; + if (precice.isTimeWindowComplete()) { + // Nothing to do in our simple case here + } } std::cout << "Rigid body: closing...\n"; diff --git a/quickstart/solid-cpp/run.sh b/quickstart/solid-cpp/run.sh index 60b4fd3eb..c764a8f73 100755 --- a/quickstart/solid-cpp/run.sh +++ b/quickstart/solid-cpp/run.sh @@ -1,9 +1,14 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + solver=./rigid_body_solver if [ -f "${solver}" ]; then ${solver} else echo "Unable to locate the executable ${solver}. Have a look at the README for building instructions." fi + +close_log diff --git a/tools/check-image-names.py b/tools/check-image-names.py new file mode 100755 index 000000000..dacf8db2e --- /dev/null +++ b/tools/check-image-names.py @@ -0,0 +1,24 @@ +#!python3 + +import sys +import os + +problems = False +for file in sys.argv[1:]: + parts = file.split(os.sep) + # Ignore non-interesting files + if len(parts) != 3 or parts[1] != "images": + continue + + if parts[0] == "quickstart": + prefix = "quickstart-" + else: + prefix = f"tutorials-{parts[0]}-" + + if not parts[2].startswith(prefix): + print(f"Incorrect: {file}") + print(f"Expected prefix: {prefix}") + print() + problems = True + +sys.exit(1 if problems else 0) diff --git a/tools/check-links-to-precice.sh b/tools/check-links-to-precice.sh new file mode 100755 index 000000000..951adc5ce --- /dev/null +++ b/tools/check-links-to-precice.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +sed -i "s/http:\/\/precice.org/https:\/\/precice.org/g" "$@" diff --git a/tools/check-size.sh b/tools/check-size.sh index 92cec1b54..340794a9f 100755 --- a/tools/check-size.sh +++ b/tools/check-size.sh @@ -2,7 +2,7 @@ # Run this script at the root of the repository to check the size of images CODE=0 -MAXIMUMSIZE=250 +MAXIMUMSIZE=750 MAXIMUMGIFSIZE=2200 RED='\033[0;31m' diff --git a/tools/check.sh b/tools/check.sh index e78121b18..03379c008 100755 --- a/tools/check.sh +++ b/tools/check.sh @@ -9,7 +9,7 @@ tutorials=$(find . -maxdepth 1 -type d -not -name ".*" | grep -vE $IGNORE | sed for tutorial in $tutorials; do # Check permalinks - docs=$(find "./$tutorial" -maxdepth 1 -type f -name "*.md" -print0 | xargs grep -l "permalink:" | sed "s/^.\///") + docs=$(find "./$tutorial" -maxdepth 1 -type f -name "*.md" -print0 | xargs -0 grep -l "permalink:" | sed "s/^.\///") for doc in $docs; do link=$(grep "permalink:" "$doc" | sed "s/permalink: \+//") prefix="tutorials-$tutorial" @@ -40,7 +40,7 @@ for tutorial in $tutorials; do done # Check quickstart -docs=$(find ./quickstart -maxdepth 1 -type f -name "*.md" -print0 | xargs grep -l "permalink:" | sed "s/^.\///") +docs=$(find ./quickstart -maxdepth 1 -type f -name "*.md" -print0 | xargs -0 grep -l "permalink:" | sed "s/^.\///") for doc in $docs; do link=$(grep "permalink:" "$doc" | sed "s/permalink: \+//") prefix="quickstart" diff --git a/tools/clean-tutorial-base.sh b/tools/clean-tutorial-base.sh index 6661e6561..88f60e8c6 100755 --- a/tools/clean-tutorial-base.sh +++ b/tools/clean-tutorial-base.sh @@ -5,3 +5,7 @@ set -e -u . ../tools/cleaning-tools.sh clean_tutorial . +clean_precice_logs . +rm -fv ./*.log +rm -fv ./*.vtu + diff --git a/tools/cleaning-tools.sh b/tools/cleaning-tools.sh index 98332b57f..7ece48288 100755 --- a/tools/cleaning-tools.sh +++ b/tools/cleaning-tools.sh @@ -9,13 +9,21 @@ clean_tutorial() { ( set -e -u cd "$1" - echo "-- Cleaning up all cases in $(pwd)..." + echo "# Cleaning up all cases in $(pwd)..." rm -rfv ./precice-run/ + # Run clean.sh if it exists in the base tutorial directory + if test -f "clean.sh"; then + ./clean.sh + fi + for case in */; do - if [ "${case}" = images/ ]; then + if [ "${case}" = images/ ] || [ "${case}" = reference-results/ ]; then continue fi + case "${case}" in solver*) + continue + esac (cd "${case}" && ./clean.sh || echo "No cleaning script in ${case} - skipping") done ) @@ -25,15 +33,24 @@ clean_precice_logs() { ( set -e -u cd "$1" - echo "---- Cleaning up preCICE logs in $(pwd)" + echo "- Cleaning up preCICE logs in $(pwd)" rm -fv ./precice-*-iterations.log \ ./precice-*-convergence.log \ - ./precice-*-events.json \ - ./precice-*-events-summary.log \ - ./precice-postProcessingInfo.log \ ./precice-*-watchpoint-*.log \ ./precice-*-watchintegral-*.log \ ./core + rm -rfv ./precice-profiling/ profiling.json trace.json + rm -rfv ./precice-exports/ + ) +} + +clean_case_logs() { + ( + set -e -u + cd "$1" + echo "- Cleaning up general case logs in $(pwd)" + CASENAME="$(readlink -f "$0" | xargs dirname | xargs basename)" + rm -fv "./$CASENAME.log" ) } @@ -41,9 +58,13 @@ clean_calculix() { ( set -e -u cd "$1" - echo "--- Cleaning up CalculiX case in $(pwd)" - rm -fv ./*.cvg ./*.dat ./*.frd ./*.sta ./*.12d spooles.out dummy + echo "- Cleaning up CalculiX case in $(pwd)" + rm -fv ./*.cvg ./*.dat ./*.frd ./*.sta ./*.12d ./*.rout spooles.out dummy + rm -fv WarnNodeMissMultiStage.nam + rm -fv ./*.eig + rm -fv ./*.vtk clean_precice_logs . + clean_case_logs . ) } @@ -51,10 +72,11 @@ clean_codeaster() { ( set -e -u cd "$1" - echo "--- Cleaning up code_aster case in $(pwd)" + echo "- Cleaning up code_aster case in $(pwd)" rm -fv ./*.mess ./*.resu ./*.rmed rm -rfv ./REPE_OUT/* clean_precice_logs . + clean_case_logs . ) } @@ -62,9 +84,10 @@ clean_dealii() { ( set -e -u cd "$1" - echo "--- Cleaning up deal.II case in $(pwd)" + echo "- Cleaning up deal.II case in $(pwd)" rm -rfv ./dealii-output/ clean_precice_logs . + clean_case_logs . ) } @@ -72,11 +95,10 @@ clean_fenics() { ( set -e -u cd "$1" - echo "--- Cleaning up FEniCS case in $(pwd)" - rm -fv spooles.out output/* + echo "- Cleaning up FEniCS case in $(pwd)" rm -rfv ./output/ - rm -rfv ./preCICE-output/ clean_precice_logs . + clean_case_logs . ) } @@ -84,10 +106,10 @@ clean_nutils() { ( set -e -u cd "$1" - echo "--- Cleaning up Nutils case in $(pwd)" + echo "- Cleaning up Nutils case in $(pwd)" rm -fv ./*.vtk - rm -rfv ./preCICE-output/ clean_precice_logs . + clean_case_logs . ) } @@ -95,15 +117,15 @@ clean_openfoam() { ( set -e -u cd "$1" - echo "--- Cleaning up OpenFOAM case in $(pwd)" + echo "- Cleaning up OpenFOAM case in $(pwd)" 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 - rm -rfv 0/uniform/functionObjects/functionObjectProperties + cleanCase > /dev/null + rm -rfv 0/uniform/functionObjects/functionObjectProperties history fi - rm -rfv ./preCICE-output/ clean_precice_logs . + clean_case_logs . ) } @@ -111,9 +133,20 @@ clean_su2() { ( set -e -u cd "$1" - echo "--- Cleaning up SU2 case in $(pwd)" - rm -fv ./restart_flow_*.dat forces_breakdown.dat ./surface_flow_*.csv ./flow_*.vtk ./history_*.vtk + echo "- Cleaning up SU2 case in $(pwd)" + rm -fv ./restart_flow_*.dat ./restart_flow_*.csv forces_breakdown.dat ./surface_flow_*.csv ./flow_*.vtk ./history_*.vtk ./history.vtk ./history_*.csv ./history.csv ./surface_flow_*.vtu ./flow_*.vtu clean_precice_logs . + clean_case_logs . + ) +} + +clean_aste() { + ( + set -e -u + cd "$1" + echo "- Cleaning up ASTE results in $(pwd)" + rm -fv result.vtk result.stats.json + rm -fvr fine_mesh coarse_mesh mapped ) } @@ -121,12 +154,35 @@ clean_dune() { ( set -e -u cd "$1" - echo "--- Cleaning up DUNE case in $(pwd)" + echo "- Cleaning up DUNE case in $(pwd)" rm -fv ./dgfparser.log rm -fv ./*.pvd rm -fv ./*.vtu - rm -rfv ./preCICE-output/ rm -rfv ./output/ clean_precice_logs . + clean_case_logs . + ) +} + +clean_dumux() { + ( + set -e -u + cd "$1" + echo "- Cleaning up DuMuX case in $(pwd)" + rm -fv ./*.vtu + rm -fv ./*.pvd + clean_precice_logs . + clean_case_logs . + ) +} + +clean_fmi() { + ( + set -e -u + cd "$1" + echo "- Cleaning up FMI case in $(pwd)" + rm -rfv ./output/ + clean_precice_logs . + clean_case_logs . ) } diff --git a/tools/log.sh b/tools/log.sh new file mode 100644 index 000000000..76cd533d1 --- /dev/null +++ b/tools/log.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -e -u + +CASENAME="$(pwd | xargs basename)" +LOGFILE="$CASENAME.log" +export LOGFILE + +STARTDATE="$(date --rfc-email)" +STARTTIME="$(date +%s)" +echo "Started on: $STARTDATE" | tee "$CASENAME.log" 2>&1 + +close_log() { + echo "Started on: $STARTDATE" | tee --append "$LOGFILE" 2>&1 + ENDDATE="$(date --rfc-email)" + ENDTIME="$(date +%s)" + echo "Finished on: $ENDDATE" | tee --append "$LOGFILE" 2>&1 + echo "Duration: $((ENDTIME-STARTTIME)) seconds (wall-clock time, including time waiting for participants)" | tee --append "$LOGFILE" 2>&1 +} diff --git a/tools/openfoam-remove-empty-dirs.sh b/tools/openfoam-remove-empty-dirs.sh index 4d3acc36d..3d0dcd436 100755 --- a/tools/openfoam-remove-empty-dirs.sh +++ b/tools/openfoam-remove-empty-dirs.sh @@ -1,25 +1,27 @@ #! /bin/sh +# Cleaning up stray functionObjectProperties files, see https://github.com/precice/openfoam-adapter/issues/26 openfoam_remove_empty_dirs() { ( set -e -u - echo "Looking for any time directories without results (e.g. stray functionObjectProperties files, see openfoam-adapter issue #26 on GitHub)..." + echo "Cleaning up any time directories without results" for f in [0-9]* [0-9]*.[0-9]*; do - if ! [ -f "${f}/U" ] && ! [ -f "${f}/T" ] && ! [ -f "${f}/U.gz" ] && ! [ -f "${f}/T.gz" ]; then - rm -rfv "${f}" + if ! [ -f "${f}/U" ] && ! [ -f "${f}/T" ] && ! [ -f "${f}/U.gz" ] && ! [ -f "${f}/T.gz" ] && ! [ -f "${f}/D" ] && ! [ -f "${f}/pointD" ] && ! [ -f "${f}/DD" ] && ! [ -f "${f}/pointDD" ] && ! [ -f "${f}/D.gz" ] && ! [ -f "${f}/pointD.gz" ] && ! [ -f "${f}/DD.gz" ] && ! [ -f "${f}/pointDD.gz" ]; then + rm -rf "${f}" fi done if [ -d processor0 ]; then for d in processor*; do cd "${d}" for f in [0-9]* [0-9]*.[0-9]*; do - if ! [ -f "${f}/U" ] && ! [ -f "${f}/T" ] && ! [ -f "${f}/U.gz" ] && ! [ -f "${f}/T.gz" ]; then - rm -rfv "${f}" + if ! [ -f "${f}/U" ] && ! [ -f "${f}/T" ] && ! [ -f "${f}/U.gz" ] && ! [ -f "${f}/T.gz" ] && ! [ -f "${f}/D" ] && ! [ -f "${f}/pointD" ] && ! [ -f "${f}/DD" ] && ! [ -f "${f}/pointDD" ] && ! [ -f "${f}/D.gz" ] && ! [ -f "${f}/pointD.gz" ] && ! [ -f "${f}/DD.gz" ] && ! [ -f "${f}/pointDD.gz" ]; then + rm -rf "${f}" fi done cd .. done fi + echo "Done." ) } diff --git a/tools/run-dealii.sh b/tools/run-dealii.sh index 318bb5143..64148aa6f 100755 --- a/tools/run-dealii.sh +++ b/tools/run-dealii.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash set -e -u EXE="" diff --git a/tools/run-openfoam.sh b/tools/run-openfoam.sh index e0667aa16..e3bf2c920 100755 --- a/tools/run-openfoam.sh +++ b/tools/run-openfoam.sh @@ -1,6 +1,10 @@ #!/bin/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" + # 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" diff --git a/partitioned-heat-conduction/fenics/.gitignore b/tools/tests/.gitignore similarity index 54% rename from partitioned-heat-conduction/fenics/.gitignore rename to tools/tests/.gitignore index 7c6571e48..3072e6ffe 100644 --- a/partitioned-heat-conduction/fenics/.gitignore +++ b/tools/tests/.gitignore @@ -1,2 +1,2 @@ -venv *.pyc +*.pyo \ No newline at end of file diff --git a/tools/tests/README.md b/tools/tests/README.md new file mode 100644 index 000000000..a68c0dbaf --- /dev/null +++ b/tools/tests/README.md @@ -0,0 +1,348 @@ +--- +title: preCICE system tests +permalink: dev-docs-system-tests.html +sidebar: docs_sidebar +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. + +## Running the system tests + +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. + +### Running the tests for a preCICE release + +Workflow for the preCICE v3 release testing: + +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/): + + ```bash + gh workflow run run_testsuite_manual.yml -f suites=release_test -f build_args="PRECICE_REF:v3.1.1,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,TUTORIALS_REF:340b447" --ref=develop + ``` + +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: + + - 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!). + +6. Download the build artifacts from Summary > runs. + + - In there, you may want to check the `stdout.log` and `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`. + +### Running specific test suites + +To test a certain test-suite defined in `tests.yaml`, use: + +```bash +python3 systemtests.py --suites=fenics_test, +``` + +To discover all tests, use `python print_test_suites.py`. + +To be able to fill in the right case tuple into the `tests.yaml`, you can use the `python3 print_case_combinations.py` script. + +## Running the system tests on GitHub Actions + +Go to Actions > [Run Testsuite (manual)](https://github.com/precice/tutorials/actions/workflows/run_testsuite_manual.yml) to see this workflow. + +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/): + +```shell +gh workflow run run_testsuite_manual.yml -f suites=fenics_test --ref=develop +``` + +Another example, to use the latest releases and enable debug information of the tests: + +```shell +gh workflow run run_testsuite_manual.yml -f suites=fenics_test -f build_args="PRECICE_REF:v3.1.1,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,TUTORIALS_REF:340b447" -f loglevel=DEBUG --ref=develop +``` + +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,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 | ++---------------------------------------------------------+---------+-------------------+-----------------+-----------------------+ +``` + +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. + +## Understanding what went wrong + +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 `runs` 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: a `stderr.log` and `stdout.log`. This can be a starting point for a further investigation. + +## Adding new tests + +### Adding tutorials + +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` + +### Adding Testsuites + +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`. + +### Generate reference results + +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. + +## 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. + +Let's dive deeper into some of these aspects. + +### General architecture + +Each tutorial directory contains a metadata file, describing which participants each case directory implements, and how to run it. + +A list of tests describes all tests to be executed, grouped by test suites. Each test is a combination of tutorial cases. + +Test steps include modifying the tutorial configuration files for the test system, building the Docker containers used by the respective Docker Compose service of each component, and comparing results to reference results using fieldcompare. + +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). + +### 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` +- `flow-over-a-heated-plate/` + - `fluid-openfoam/` + - `run.sh`: describes how to execute the respective case + - `solid-fenics/` + - `solid-openfoam/` + - ... + - `metadata.yml`: describes each case directory (which participant, which component, which script to run, ...) +- `tools/tests/` + - `component-templates/`: jinja2 templates for Docker Compose services for the components + - `calculix-adapter.yaml` + - `fenics-adapter.yaml` + - `openfoam-adapter.yaml` + - ... + - `dockerfiles/ubuntu_2204/` + - Dockerfile: a multi-stage build Dockerfile that defines how to build each component, in a layered approach + - `docker-compose.template.yaml`: Describes how to prepare each test (Docker Componse service template) + - `docker-compose.field_compare.template.yaml`: Describes how to compare results with fieldcompare (Docker Compose service template) + - `components.yaml`: Declares the available components and their parameters/options + - `reference_results.metadata.template`: Template for reporting the versions used to generate the reference results + - `reference_versions.yaml`: List of arguments to use for generating the reference results + - `tests.yaml`: Declares the available tests, grouped in test suites + +User-facing tools: + +- `tools/tests/` + - `systemtests.py`: Executes the system tests, starting Docker Compose services of each required component (after building them), running each test, and comparing the results to reference results. + - `print_test_suites.py`: Prints the available tests. + - `print_metadata.py`: Prints the metadata of each tutorial that contains a `metadata.yaml` file. + - `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) + +Implementation scripts: + +- `tools/tests/` + - `systemtests.py`: Main entry point + - `requirements.txt`: Dependencies (jinja2, pyyaml) + - `metadata_parser/`: Reads the YAML files into Python objects (defines the schema) + - `systemtests/`: Main implementation classes + - `Systemtest.py` + - `SystemtestArguments.py` + - `TestSuite.py` + +### Metadata + +Every tutorial contains a file called `metadata.yaml` describing some important properties of the tutorial. For example: + +```yaml +name: Elastic tube 3D +path: elastic-tube-3d +url: https://precice.org/tutorials-elastic-tube-3d.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 + + solid-fenics: + participant: Solid + directory: ./solid-fenics + run: ./run.sh + component: fenics-adapter +``` + +Description: + +- `name`: A human-readable, descriptive name +- `path`: Where the tutorial is located, relative to the tutorials repository +- `url`: A web page with more information on the tutorial +- `participants`: A list of preCICE participants, typically corresponing to different domains of the simulation +- `cases`: A list of solver configuration directories. Each element of the list includes: + - `participant`: Which participant this solver case can serve as + - `directory`: Where the case directory is located, relative to the tutorial directory + - `run`: Command that executes the tutorial + - `component`: Component or list of components that this case depends upon (typically an adapter) + +### 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: + +```yaml +openfoam-adapter: + repository: https://github.com/precice/openfoam-adapter + template: component-templates/openfoam-adapter.yaml + build_arguments: + PRECICE_REF: + description: Version of preCICE to use + default: "main" + PLATFORM: + description: Dockerfile platform used + default: "ubuntu_2204" + TUTORIALS_REF: + description: Tutorial git reference to use + default: "master" + OPENFOAM_EXECUTABLE: + options: ["openfoam2306","openfoam2212","openfoam2112"] + description: exectuable of openfoam to use + default: "openfoam2306" + OPENFOAM_ADAPTER_REF: + description: Reference/tag of the actual OpenFOAM adapter + default: "master" +``` + +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: + +- A build_argument ending in **_REF** means that it refers to a git commit-ish (like a tag or commit) beeing used to build the image. Its important to not use branch names here as we heavily rely on dockers build cache to speedup things. But since the input variable to the docker builder will not change, we might have wrong cache hits. +- All other build_arguments are free of rules and up to the container maintainer. + +### Component templates + +Templates for defining a Docker Compose service for each component are available in `component-templates/`. For example: + +```yaml +image: precice/fenics-adapter:{{ build_arguments["FENICS_ADAPTER_REF"] }} +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" +``` + +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). +- `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 +``` + +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 triggerable `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 + +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: + +- 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. + +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 new file mode 100644 index 000000000..c77b8523d --- /dev/null +++ b/tools/tests/build_docker_images.py @@ -0,0 +1,96 @@ + +import argparse +from pathlib import Path +from systemtests.SystemtestArguments import SystemtestArguments +from systemtests.Systemtest import Systemtest, display_systemtestresults_as_table +from systemtests.TestSuite import TestSuites +from metadata_parser.metdata import Tutorials +import logging +import time +from paths import PRECICE_TUTORIAL_DIR, PRECICE_TESTS_RUN_DIR, PRECICE_TESTS_DIR + + +def main(): + parser = argparse.ArgumentParser(description='build docker images') + + # Add an argument for the components + parser.add_argument('--suites', type=str, + help='Comma-separated test-suites to execute') + parser.add_argument( + '--build_args', + type=str, + help='Comma-separated list of arguments provided to the components like openfoam:2102,pythonbindings:latest') + 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') + + # 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') + + print(f"Using log-level: {args.log_level}") + + systemtests_to_run = [] + available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) + + build_args = SystemtestArguments.from_args(args.build_args) + run_directory = Path(args.rundir) + if args.suites: + 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) + if not test_suite_found: + logging.error(f"Did not find the testsuite with name {test_suite_requested}") + else: + test_suites_to_execute.append(test_suite_found) + if not test_suites_to_execute: + raise RuntimeError( + f"No matching test suites with names {test_suites_requested} found. Use print_test_suites.py to get an overview") + # now convert the test_suites into systemtests + for test_suite in test_suites_to_execute: + tutorials = test_suite.cases_of_tutorial.keys() + for tutorial in tutorials: + for case, reference_result in zip( + test_suite.cases_of_tutorial[tutorial], test_suite.reference_results[tutorial]): + systemtests_to_run.append( + Systemtest(tutorial, build_args, case, reference_result)) + + if not systemtests_to_run: + raise RuntimeError("Did not find any Systemtests to execute.") + + logging.info(f"About to build the images for the following systemtests:\n {systemtests_to_run}") + + results = [] + for number, systemtest in enumerate(systemtests_to_run): + logging.info(f"Started building {systemtest}, {number}/{len(systemtests_to_run)}") + t = time.perf_counter() + result = systemtest.run_only_build(run_directory) + elapsed_time = time.perf_counter() - t + logging.info(f"Building image for {systemtest} took {elapsed_time} seconds") + results.append(result) + + build_docker_success = True + for result in results: + if not result.success: + logging.error(f"Failed to run {result.systemtest}") + build_docker_success = False + else: + logging.info(f"Success running {result.systemtest}") + + display_systemtestresults_as_table(results) + if build_docker_success: + exit(0) + else: + exit(1) + + +if __name__ == '__main__': + main() diff --git a/tools/tests/component-templates/bare.yaml b/tools/tests/component-templates/bare.yaml new file mode 100644 index 000000000..7de1f206a --- /dev/null +++ b/tools/tests/component-templates/bare.yaml @@ -0,0 +1,16 @@ +build: + context: {{ dockerfile_context }} + args: + {% for key, value in build_arguments.items() %} + - {{key}}={{value}} + {% endfor %} + target: precice +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/calculix-adapter.yaml b/tools/tests/component-templates/calculix-adapter.yaml new file mode 100644 index 000000000..ca35dd8df --- /dev/null +++ b/tools/tests/component-templates/calculix-adapter.yaml @@ -0,0 +1,16 @@ +build: + context: {{ dockerfile_context }} + args: + {% for key, value in build_arguments.items() %} + - {{key}}={{value}} + {% endfor %} + target: calculix_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/fenics-adapter.yaml b/tools/tests/component-templates/fenics-adapter.yaml new file mode 100644 index 000000000..220a52525 --- /dev/null +++ b/tools/tests/component-templates/fenics-adapter.yaml @@ -0,0 +1,16 @@ +build: + context: {{ dockerfile_context }} + args: + {% for key, value in build_arguments.items() %} + - {{key}}={{value}} + {% endfor %} + target: fenics_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/nutils-adapter.yaml b/tools/tests/component-templates/nutils-adapter.yaml new file mode 100644 index 000000000..5893c65a7 --- /dev/null +++ b/tools/tests/component-templates/nutils-adapter.yaml @@ -0,0 +1,16 @@ +build: + context: {{ dockerfile_context }} + args: + {% for key, value in build_arguments.items() %} + - {{key}}={{value}} + {% endfor %} + target: nutils_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/openfoam-adapter.yaml b/tools/tests/component-templates/openfoam-adapter.yaml new file mode 100644 index 000000000..c376c4a58 --- /dev/null +++ b/tools/tests/component-templates/openfoam-adapter.yaml @@ -0,0 +1,16 @@ +build: + context: {{ dockerfile_context }} + args: + {% for key, value in build_arguments.items() %} + - {{key}}={{value}} + {% endfor %} + target: openfoam_adapter +depends_on: + prepare: + condition: service_completed_successfully +volumes: + - {{ run_directory }}:/runs +command: > + /bin/bash -c "id && + cd '/runs/{{ tutorial_folder }}/{{ case_folder }}' && + openfoam {{ run }} | 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 new file mode 100644 index 000000000..3cd65d274 --- /dev/null +++ b/tools/tests/component-templates/python-bindings.yaml @@ -0,0 +1,16 @@ +build: + context: {{ dockerfile_context }} + args: + {% for key, value in build_arguments.items() %} + - {{key}}={{value}} + {% endfor %} + target: python_bindings +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/su2-adapter.yaml b/tools/tests/component-templates/su2-adapter.yaml new file mode 100644 index 000000000..d466a949a --- /dev/null +++ b/tools/tests/component-templates/su2-adapter.yaml @@ -0,0 +1,16 @@ +build: + context: {{ dockerfile_context }} + args: + {% for key, value in build_arguments.items() %} + - {{key}}={{value}} + {% endfor %} + target: su2_adapter +depends_on: + prepare: + condition: service_completed_successfully +volumes: + - {{ run_directory }}:/runs +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" diff --git a/tools/tests/components.yaml b/tools/tests/components.yaml new file mode 100644 index 000000000..acbd55eb6 --- /dev/null +++ b/tools/tests/components.yaml @@ -0,0 +1,129 @@ +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 + PRECICE_REF: + description: Version of preCICE to use + default: "main" + PLATFORM: + description: Dockerfile platform used + default: "ubuntu_2204" + TUTORIALS_REF: + description: Tutorial git reference to use + default: "master" + +python-bindings: + repository: https://github.com/precice/python-bindings + template: component-templates/python-bindings.yaml + build_arguments: + PRECICE_REF: + description: Version of preCICE to use + default: "main" + PLATFORM: + description: Dockerfile platform used + default: "ubuntu_2204" + TUTORIALS_REF: + description: Tutorial git reference to use + default: "master" + PYTHON_BINDINGS_REF: + semnantic: Git ref of the pythonbindings to use + default: "master" + +openfoam-adapter: + repository: https://github.com/precice/openfoam-adapter + template: component-templates/openfoam-adapter.yaml + build_arguments: + PRECICE_REF: + description: Version of preCICE to use + default: "main" + PLATFORM: + description: Dockerfile platform used + default: "ubuntu_2204" + TUTORIALS_REF: + description: Tutorial git reference to use + default: "master" + OPENFOAM_EXECUTABLE: + options: ["openfoam2306","openfoam2212","openfoam2112"] + description: exectuable of openfoam to use + default: "openfoam2306" + OPENFOAM_ADAPTER_REF: + description: Reference/tag of the actual OpenFOAM adapter + default: "master" + + +fenics-adapter: + repository: https://github.com/precice/fenics-adapter + template: component-templates/fenics-adapter.yaml + build_arguments: + PRECICE_REF: + description: Version of preCICE to use + default: "main" + PLATFORM: + description: Dockerfile platform used + default: "ubuntu_2204" + TUTORIALS_REF: + description: Tutorial git reference to use + default: "master" + PYTHON_BINDINGS_REF: + semnantic: Git ref of the pythonbindings to use + default: "master" + FENICS_ADAPTER_REF: + semnantic: Git ref of the fenics adapter to use + default: "master" + +nutils-adapter: + repository: https://github.com/precice/nutils-adapter + template: component-templates/nutils-adapter.yaml + build_arguments: + PRECICE_REF: + description: Version of preCICE to use + default: "main" + PLATFORM: + description: Dockerfile platform used + default: "ubuntu_2204" + TUTORIALS_REF: + description: Tutorial git reference to use + default: "master" + PYTHON_BINDINGS_REF: + semnantic: Git ref of the pythonbindings to use + + +calculix-adapter: + repository: https://github.com/precice/calculix-adapter + template: component-templates/calculix-adapter.yaml + build_arguments: + PRECICE_REF: + description: Version of preCICE to use + default: "main" + PLATFORM: + description: Dockerfile platform used + default: "ubuntu_2204" + TUTORIALS_REF: + description: Tutorial git reference to use + default: "master" + CALULIX_VERSION: + description: Version of Calculix to use + default: "2.20" + CALULIX_ADAPTER_REF: + description: Version of Calculix-Adapter to use + default: "master" + +su2-adapter: + repository: https://github.com/precice/su2-adapter + template: component-templates/su2-adapter.yaml + build_arguments: + PRECICE_REF: + description: Version of preCICE to use + default: "main" + PLATFORM: + description: Dockerfile platform used + default: "ubuntu_2204" + 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" diff --git a/tools/tests/docker-compose.field_compare.template.yaml b/tools/tests/docker-compose.field_compare.template.yaml new file mode 100644 index 000000000..4e86de2e7 --- /dev/null +++ b/tools/tests/docker-compose.field_compare.template.yaml @@ -0,0 +1,13 @@ +version: "3.9" +services: + field-compare: + build: https://github.com/dglaeser/fieldcompare-action.git # use the docker container provided by fieldcompare + volumes: + - {{ run_directory }}:/runs + command: + - /runs/{{ tutorial_folder }}/{{ precice_output_folder }} + - /runs/{{ tutorial_folder }}/{{ reference_output_folder }} + - "-rtol 3e-7" + +# Currently its really hard to estimate the impact of compiling and executing in a different platform (like github actions) +# 3e-7 might not be the thightest we can afford and we want to have but its an okayish guestimation for now. \ No newline at end of file diff --git a/tools/tests/docker-compose.template.yaml b/tools/tests/docker-compose.template.yaml new file mode 100644 index 000000000..e8006f4ad --- /dev/null +++ b/tools/tests/docker-compose.template.yaml @@ -0,0 +1,24 @@ +version: "3.9" +services: + prepare: + build: + context: {{ dockerfile_context }} + target: base_image + args: + {% for key, value in build_arguments.items() %} + - {{key}}={{value}} + {% endfor %} + volumes: + - {{ run_directory }}:/runs + command: > + /bin/bash -c "id && + cd '/runs/{{ tutorial_folder }}' && + sed -i 's%
%
%g' precice-config.xml && + sed -i 's|m2n:sockets |m2n:sockets network=\"eth0\" |g' precice-config.xml && + cat precice-config.xml" + + + {% for service in services %} + {{ service }}: + {{ services[service] |indent(4) }} + {% endfor %} diff --git a/tools/tests/dockerfiles/ubuntu_2204/Dockerfile b/tools/tests/dockerfiles/ubuntu_2204/Dockerfile new file mode 100644 index 000000000..6dbb627ac --- /dev/null +++ b/tools/tests/dockerfiles/ubuntu_2204/Dockerfile @@ -0,0 +1,156 @@ +FROM ubuntu:22.04 as base_image +USER root +SHELL ["/bin/bash", "-c"] +ENV DEBIAN_FRONTEND=noninteractive +# We set a sensical value, but still have the possibilty to influence this via the build time arguments. +# When the dockerfile is built using the systemtests.py we set the PRECICE_UID and PRECICE_GID to the user executing the systemtests. +# This ensures no file ownership problems down the line and is the most easy fix, as we normally built the containers locally +# If not built via the systemtests.py its either possible to specify manually but 1000 would be the default anyway. +ARG PRECICE_UID=1000 +ARG PRECICE_GID=1000 +RUN groupadd -g ${PRECICE_GID} precice && useradd -u ${PRECICE_UID} -g ${PRECICE_GID} -ms /bin/bash precice +ENV PATH="${PATH}:/home/precice/.local/bin" +ENV LD_LIBRARY_PATH="/home/precice/.local/lib:${LD_LIBRARY_PATH}" +ENV CPATH="/home/precice/.local/include:$CPATH" +# Enable detection with pkg-config and CMake +ENV PKG_CONFIG_PATH="/home/precice/.local/lib/pkgconfig:$PKG_CONFIG_PATH" +ENV CMAKE_PREFIX_PATH="/home/precice/.local:$CMAKE_PREFIX_PATH" +USER precice + +FROM base_image as precice_dependecies +USER root +# Installing necessary dependecies for preCICE +RUN apt-get -qq update && \ + apt-get -qq -y install \ + build-essential \ + software-properties-common \ + cmake \ + curl \ + g++ \ + gfortran \ + git \ + libbenchmark-dev \ + libboost-all-dev \ + libeigen3-dev \ + libxml2-dev \ + lsb-release \ + petsc-dev \ + python3-dev \ + python3-numpy \ + python3-pip \ + python3-venv \ + pkg-config \ + wget +USER precice +RUN python3 -m pip install --user --upgrade pip + + +FROM precice_dependecies as precice +# Install & build precice into /home/precice/precice +ARG PRECICE_REF +USER precice +WORKDIR /home/precice +RUN git clone https://github.com/precice/precice.git precice && \ + cd precice && \ + git checkout ${PRECICE_REF} && \ + mkdir build && cd build &&\ + cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/home/precice/.local/ -DPRECICE_PETScMapping=OFF -DBUILD_TESTING=OFF && \ + make all install -j $(nproc) + +FROM precice_dependecies as openfoam_adapter +ARG OPENFOAM_EXECUTABLE +USER root +RUN apt-get update &&\ + wget -q -O - https://dl.openfoam.com/add-debian-repo.sh | bash &&\ + apt-get -qq install ${OPENFOAM_EXECUTABLE}-dev &&\ + ln -s $(which ${OPENFOAM_EXECUTABLE} ) /usr/bin/openfoam +USER precice +COPY --from=precice /home/precice/.local/ /home/precice/.local/ +ARG OPENFOAM_ADAPTER_REF +# Build the OpenFOAM adapter +USER precice +WORKDIR /home/precice +RUN git clone https://github.com/precice/openfoam-adapter.git &&\ + cd openfoam-adapter && \ + git checkout ${OPENFOAM_ADAPTER_REF} && \ + /usr/bin/${OPENFOAM_EXECUTABLE} ./Allwmake -j $(nproc) + + +FROM precice_dependecies as python_bindings +COPY --from=precice /home/precice/.local/ /home/precice/.local/ +ARG PYTHON_BINDINGS_REF +USER precice +WORKDIR /home/precice +# Builds the precice python bindings for python3 +# Installs also matplotlib as its needed for the elastic-tube 1d fluid-python participant. +RUN pip3 install --user git+https://github.com/precice/python-bindings.git@${PYTHON_BINDINGS_REF} && \ + pip3 install --user matplotlib + +FROM precice_dependecies as fenics_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 fenics +USER precice +RUN pip3 install --user fenics-ufl +ARG FENICS_ADAPTER_REF +# Building fenics-adapter +RUN pip3 install --user git+https://github.com/precice/fenics-adapter.git@${FENICS_ADAPTER_REF} + + +FROM precice_dependecies as nutils_adapter +COPY --from=python_bindings /home/precice/.local /home/precice/.local +USER precice +# Installing nutils - There is no adapter +RUN pip3 install --user nutils + + +FROM precice_dependecies as calculix_adapter +COPY --from=precice /home/precice/.local /home/precice/.local +USER root +RUN apt-get -qq update && \ + apt-get -qq install libarpack2-dev libspooles-dev libyaml-cpp-dev +ARG CALULIX_VERSION +USER precice +#Download Calculix +WORKDIR /home/precice +RUN wget http://www.dhondt.de/ccx_${CALULIX_VERSION}.src.tar.bz2 && \ + tar xvjf ccx_${CALULIX_VERSION}.src.tar.bz2 && \ + rm -fv ccx_${CALULIX_VERSION}.src.tar.bz2 + +ARG CALULIX_ADAPTER_REF +WORKDIR /home/precice +RUN git clone https://github.com/precice/calculix-adapter.git && \ + cd calculix-adapter && \ + git checkout ${CALULIX_ADAPTER_REF} &&\ + make CXX_VERSION=${CALULIX_VERSION} ADDITIONAL_FFLAGS="-fallow-argument-mismatch" -j $(nproc) && \ + ln -s /home/precice/calculix-adapter/bin/ccx_preCICE /home/precice/.local/bin/ccx_preCICE + +FROM python_bindings as su2_adapter +COPY --from=precice /home/precice/.local /home/precice/.local +USER root +RUN apt-get -qq update && \ + apt-get -qq install swig +ARG SU2_VERSION +USER precice + +# Download and build SU2 (We could also use pre-built binaries from the SU2 releases) +WORKDIR /home/precice +RUN wget https://github.com/su2code/SU2/archive/refs/tags/v${SU2_VERSION}.tar.gz && \ + tar xvzf v${SU2_VERSION}.tar.gz && \ + rm -fv v${SU2_VERSION}.tar.gz +RUN pip3 install --user mpi4py +ARG SU2_ADAPTER_REF +WORKDIR /home/precice +ENV SU2_RUN="/home/precice/SU2_RUN" +ENV SU2_HOME="/home/precice/SU2-${SU2_VERSION}" +ENV PATH="/home/precice/su2-adapter/run:$SU2_RUN:$PATH" +ENV PYTHONPATH="$SU2_RUN:$PYTHONPATH" +RUN git clone https://github.com/precice/su2-adapter.git && \ + cd su2-adapter &&\ + git checkout ${SU2_ADAPTER_REF} &&\ + ./su2AdapterInstall +RUN cd "${SU2_HOME}" &&\ + ./meson.py build -Denable-pywrapper=true --prefix=$SU2_RUN &&\ + ./ninja -C build install diff --git a/tools/tests/generate_reference_results.py b/tools/tests/generate_reference_results.py new file mode 100644 index 000000000..335b73a62 --- /dev/null +++ b/tools/tests/generate_reference_results.py @@ -0,0 +1,148 @@ + +import argparse +from metadata_parser.metdata import Tutorials, ReferenceResult +from systemtests.TestSuite import TestSuites +from systemtests.SystemtestArguments import SystemtestArguments +from systemtests.Systemtest import Systemtest +from pathlib import Path +from typing import List +from paths import PRECICE_TESTS_DIR, PRECICE_TUTORIAL_DIR +import hashlib +from jinja2 import Environment, FileSystemLoader +import tarfile +import subprocess +from datetime import datetime +import logging + +from paths import PRECICE_TUTORIAL_DIR, PRECICE_TESTS_RUN_DIR, PRECICE_TESTS_DIR, PRECICE_REL_OUTPUT_DIR +import time + + +def create_tar_gz(source_folder: Path, output_filename: Path): + with tarfile.open(output_filename, "w:gz") as tar: + tar.add(source_folder, arcname=output_filename.name.replace(".tar.gz", "")) + + +def get_machine_informations(): + def command_is_avail(command: str): + try: + rc = subprocess.call(['which', command], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + except FileNotFoundError: + return False + + return rc == 0 + uname_info = "uname not available on the machine the systemtests were executed." + lscpu_info = "lscpu not available on the machine the systemtests were executed." + if (command_is_avail("uname")): + result = subprocess.run(["uname", "-a"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + if result.returncode == 0: + uname_info = result.stdout + + if (command_is_avail("lscpu") and command_is_avail("grep")): + result_lscpu = subprocess.run(["lscpu"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + result = subprocess.run(["grep", "-v", "Vulner"], input=result_lscpu.stdout, + stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + if result.returncode == 0: + lscpu_info = result.stdout + + return (uname_info, lscpu_info) + + +def render_reference_results_info( + reference_results: List[ReferenceResult], + arguments_used: SystemtestArguments, + time: str): + def sha256sum(filename): + with open(filename, 'rb', buffering=0) as f: + return hashlib.file_digest(f, 'sha256').hexdigest() + + files = [] + for reference_result in reference_results: + files.append({ + 'sha256': sha256sum(reference_result.path), + 'time': time, + 'name': reference_result.path.name, + }) + uname, lscpu = get_machine_informations() + render_dict = { + 'arguments': arguments_used.arguments, + 'files': files, + 'uname': uname, + 'lscpu': lscpu, + } + + jinja_env = Environment(loader=FileSystemLoader(PRECICE_TESTS_DIR)) + template = jinja_env.get_template("reference_results.metadata.template") + return template.render(render_dict) + + +def main(): + + parser = argparse.ArgumentParser(description='Generate reference data for systemtests') + 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') + + args = parser.parse_args() + + logging.basicConfig(level=args.log_level, format='%(levelname)s: %(message)s') + + print(f"Using log-level: {args.log_level}") + + run_directory = Path(args.rundir) + + available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) + + test_suites = TestSuites.from_yaml(PRECICE_TESTS_DIR / "tests.yaml", available_tutorials) + + # Read in parameters + build_args = SystemtestArguments.from_yaml(PRECICE_TESTS_DIR / "reference_versions.yaml") + systemtests_to_run = set() + + for test_suite in test_suites: + tutorials = test_suite.cases_of_tutorial.keys() + for tutorial in tutorials: + for case, reference_result in zip( + test_suite.cases_of_tutorial[tutorial], test_suite.reference_results[tutorial]): + systemtests_to_run.add( + Systemtest(tutorial, build_args, case, reference_result)) + + reference_result_per_tutorial = {} + current_time_string = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + logging.info(f"About to run the following tests {systemtests_to_run}") + for number, systemtest in enumerate(systemtests_to_run): + logging.info(f"Started running {systemtest}, {number}/{len(systemtests_to_run)}") + t = time.perf_counter() + result = systemtest.run_for_reference_results(run_directory) + elapsed_time = time.perf_counter() - t + logging.info(f"Running {systemtest} took {elapsed_time} seconds") + if not result.success: + raise RuntimeError(f"Failed to execute {systemtest}") + reference_result_per_tutorial[systemtest.tutorial] = [] + + # Put the tar.gz in there + for systemtest in systemtests_to_run: + reference_result_folder = systemtest.get_system_test_dir() / PRECICE_REL_OUTPUT_DIR + reference_result_per_tutorial[systemtest.tutorial].append(systemtest.reference_result) + # create folder if needed + systemtest.reference_result.path.parent.mkdir(parents=True, exist_ok=True) + if reference_result_folder.exists(): + create_tar_gz(reference_result_folder, systemtest.reference_result.path) + else: + raise RuntimeError( + f"Error executing: \n {systemtest} \n Could not find result folder {reference_result_folder}\n Probably the tutorial did not run through properly. Please check corresponding logs") + + # write readme + for tutorial in reference_result_per_tutorial.keys(): + with open(tutorial.path / "reference_results.metadata", 'w') as file: + ref_results_info = render_reference_results_info( + reference_result_per_tutorial[tutorial], build_args, current_time_string) + logging.info(f"Writing results for {tutorial.name}") + file.write(ref_results_info) + logging.info(f"Done. Please make sure to manually have a look into the reference results before making a PR.") + + +if __name__ == '__main__': + main() diff --git a/tools/tests/metadata_parser/__init__.py b/tools/tests/metadata_parser/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tools/tests/metadata_parser/metdata.py b/tools/tests/metadata_parser/metdata.py new file mode 100644 index 000000000..67ff7e716 --- /dev/null +++ b/tools/tests/metadata_parser/metdata.py @@ -0,0 +1,443 @@ +from dataclasses import dataclass, field +from pathlib import Path +from typing import List, Tuple, Optional, Dict +import glob +import yaml +import itertools +from paths import PRECICE_TESTS_DIR, PRECICE_TUTORIAL_DIR + + +@dataclass +class BuildArgument: + """Represents a BuildArgument needed to run the docker container""" + + description: str + """The description of the parameter.""" + + key: str + """The name of the parameter.""" + + value_options: Optional[list] = None + """The optinal list of value options for the parameter. If none is suplied all values are accepted""" + + default: Optional[str] = None + """The default value for the parameter.""" + + @property + def required(self) -> bool: + """ + Check if the BuildArgument need to be supplied via CommandLineArgs + + Returns: + bool: True if the parameter is required, False otherwise. + """ + return False if self.default else True + + def __eq__(self, other) -> bool: + if isinstance(other, BuildArgument): + return self.key == other.key + return False + + def __hash__(self) -> int: + return hash(self.key) + + def __repr__(self) -> str: + return f"{self.key}" + + +class BuildArguments: + """Represents a collection of build_arguments used to built the docker images.""" + + def __init__(self, arguments: List[BuildArgument]): + self.arguments = arguments + + @classmethod + def from_components_yaml(cls, data): + """ + Create a list of Paramters from the components YAML data. + + Args: + data: The components YAML 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}") + 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)) + + return cls(arguments) + + def __iter__(self): + return iter(self.arguments) + + def __getitem__(self, index): + return self.arguments[index] + + def __setitem__(self, index, value): + self.arguments[index] = value + + def __len__(self): + return len(self.arguments) + + def __repr__(self) -> str: + return f"{self.arguments}" + + +@dataclass +class Component: + """ + Represents a component like e.g the openfoam-adapter + """ + + name: str + template: str + repository: str + parameters: BuildArguments + + def __eq__(self, other): + if isinstance(other, Component): + return self.name == other.name + return False + + def __repr__(self) -> str: + return f"{self.name}" + + +class Components(list): + """ + Represents the collection of components read in from the components.yaml + """ + + def __init__(self, components: List[Component]): + self.components = components + + @classmethod + def from_yaml(cls, path): + """ + Creates a Components instance from a YAML file. + + Args: + path: The path to the YAML file. + + Returns: + An instance of Components. + """ + components = [] + with open(path, 'r') as f: + data = yaml.safe_load(f) + 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)) + + return cls(components) + + def __iter__(self): + return iter(self.components) + + def __getitem__(self, index): + return self.components[index] + + def __setitem__(self, index, value): + self.components[index] = value + + def __len__(self): + return len(self.components) + + def get_by_name(self, name_to_search): + """ + Retrieves a component by its name. + + Args: + name_to_search: The name of the component to search for. + + Returns: + The component with the specified name, or None if not found. + """ + for component in self.components: + if component.name == name_to_search: + return component + + return None + + +@dataclass +class Participant: + """Represents a participant in a coupled simulation""" + + name: str + """The name of the participant.""" + + def __eq__(self, other) -> bool: + if isinstance(other, Participant): + return self.name == other.name + return False + + def __repr__(self) -> str: + return f"{self.name}" + +# Forward declaration of tutorial + + +class Tutorial: + pass + + +@dataclass +class Case: + """ + Represents a case inside of a tutorial. + """ + name: str + participant: str + path: Path + run_cmd: str + tutorial: Tutorial = field(init=False) + component: Component + + def __post_init__(self): + """ + Performs sanity checks after initializing the Case instance. + """ + if not self.component: + raise Exception( + f'Tried to instantiate the case {self.name} but failed. Reason: Could not find the component it uses in the components.yaml file.') + + @classmethod + def from_dict(cls, name, dict, available_components): + """ + Creates a Case instance from a the tutorial yaml dict. + + Args: + name: The name of the case. + dict: The dictionary containing the case data. + available_components: Components read from the components.yaml file + + Returns: + An instance of the Case but without the tutorial set, this needs to be done later + """ + participant = dict["participant"] + path = Path(dict["directory"]) + run_cmd = dict["run"] + + component = available_components.get_by_name(dict["component"]) + return cls(name, participant, path, run_cmd, component) + + def __repr__(self) -> str: + return f"{self.name}" + + def __hash__(self) -> int: + return hash(f"{self.name,self.participant,self.component,self.tutorial}") + + def __eq__(self, other) -> bool: + if isinstance(other, Case): + return ( + self.name == other.name) and ( + self.participant == other.participant) and ( + self.component == other.component) and ( + self.tutorial == other.tutorial) + return False + + +@dataclass +class CaseCombination: + """Represents a case combination able to run the tutorial""" + + cases: Tuple[Case] + tutorial: Tutorial + + def __eq__(self, other) -> bool: + if isinstance(other, CaseCombination): + return set(self.cases) == set(other.cases) + return False + + def __repr__(self) -> str: + return f"{self.cases}" + + @classmethod + def from_string_list(cls, case_names: List[str], tutorial: Tutorial): + cases = [] + for case_name in case_names: + cases.append(tutorial.get_case_by_string(case_name)) + return cls(tuple(cases), tutorial) + + @classmethod + def from_cases_tuple(cls, cases: Tuple[Case], tutorial: Tutorial): + return cls(cases, tutorial) + + +@dataclass +class ReferenceResult: + path: Path + case_combination: CaseCombination + + def __repr__(self) -> str: + return f"{self.path.as_posix()}" + + def __post_init__(self): + # built full path + self.path = PRECICE_TUTORIAL_DIR / self.path + + +@dataclass +class Tutorial: + """ + Represents a tutorial with various attributes and methods. + """ + + name: str + path: Path + url: str + participants: List[str] + cases: List[Case] + case_combinations: List[CaseCombination] = field(init=False) + + def __post_init__(self): + for case in self.cases: + case.tutorial = self + # get all case combinations + + def get_all_possible_case_combinations(tutorial: Tutorial): + case_combinations = [] + cases_dict = {} + for participant in tutorial.participants: + cases_dict[participant] = [] + for case in tutorial.cases: + cases_dict[case.participant].append(case) + + for combination in itertools.product(*[cases_dict[participant] for participant in tutorial.participants]): + case_combinations.append(CaseCombination.from_cases_tuple(combination, self)) + return case_combinations + + self.case_combinations = get_all_possible_case_combinations(self) + + def __eq__(self, other) -> bool: + if isinstance(other, Tutorial): + return (self.name == other.name) and (self.path == other.path) + return False + + def __hash__(self) -> int: + return hash(self.path) + + def __repr__(self) -> str: + """ + Returns a string representation of the Tutorial. + """ + return f"""\n{self.name}: + Path: {self.path} + URL: {self.url} + Participants: {self.participants} + Cases: {self.cases} + """ + + def get_case_by_string(self, case_name: str) -> Optional[Case]: + """ + Retrieves Optional case based on the case_name + + Args: + case_name: the name of the case in search + + Returns: + Either None or a Case mathing the casename + """ + for case in self.cases: + if case.name == case_name: + return case + return None + + @classmethod + def from_yaml(cls, path, available_components): + """ + Creates a Tutorial instance from a YAML file. + + Args: + path: The path to the YAML file. + available_components: The Components instance containing available components. + + Returns: + An instance of Tutorial. + """ + with open(path, 'r') as f: + data = yaml.safe_load(f) + name = data['name'] + path = PRECICE_TUTORIAL_DIR / data['path'] + url = data['url'] + participants = data.get('participants', []) + cases_raw = data.get('cases', {}) + cases = [] + for case_name in cases_raw.keys(): + cases.append(Case.from_dict( + case_name, cases_raw[case_name], available_components)) + return cls(name, path, url, participants, cases) + + +class Tutorials(list): + """ + Represents a collection of tutorials. + """ + + def __iter__(self): + return iter(self.tutorials) + + def __getitem__(self, index): + return self.tutorials[index] + + def __setitem__(self, index, value): + self.tutorials[index] = value + + def __len__(self): + return len(self.tutorials) + + def __init__(self, tutorials: List[Tutorial]): + """ + Initializes the Tutorials instance with a base path and a list of tutorials. + + Args: + path: The path to the folder containing the tutorial folders. + tutorials: The list of tutorials. + """ + self.tutorials = tutorials + + def get_by_path(self, relative_path: str) -> Optional[Tutorial]: + """ + Retrieves a Tutorial by its relative path. + + Args: + path_to_search: The path of the Tutorial to search for. + + Returns: + The Tutorial with the specified path, or None if not found. + """ + + for tutorial in self.tutorials: + if tutorial.path.name == relative_path: + return tutorial + + return None + + @classmethod + def from_path(cls, path): + """ + Read ins all the metadata.yaml files available in path/*/metadata.yaml + + Args: + path: The path containing the tutorial folders + """ + + yaml_files = glob.glob(f'{path}/*/metadata.yaml') + tutorials = [] + available_components = Components.from_yaml( + PRECICE_TESTS_DIR / "components.yaml") + for yaml_path in yaml_files: + tut = Tutorial.from_yaml(yaml_path, available_components) + tutorials.append(tut) + return cls(tutorials) diff --git a/tools/tests/paths.py b/tools/tests/paths.py new file mode 100644 index 000000000..8b7f064d2 --- /dev/null +++ b/tools/tests/paths.py @@ -0,0 +1,7 @@ +from pathlib import Path +PRECICE_TUTORIAL_DIR = Path(__file__).parent.parent.parent +PRECICE_TESTS_RUN_DIR = Path(__file__).parent.parent.parent / "runs" +PRECICE_TOOLS_DIR = Path(__file__).parent.parent +PRECICE_TESTS_DIR = Path(__file__).parent +PRECICE_REL_OUTPUT_DIR = "precice-exports" +PRECICE_REL_REFERENCE_DIR = "reference-results-unpacked" diff --git a/tools/tests/print_case_combinations.py b/tools/tests/print_case_combinations.py new file mode 100644 index 000000000..25e318918 --- /dev/null +++ b/tools/tests/print_case_combinations.py @@ -0,0 +1,32 @@ +import yaml +from metadata_parser.metdata import Tutorials +from paths import PRECICE_TUTORIAL_DIR + +import argparse +import logging + + +def main(): + parser = argparse.ArgumentParser(description='Prints available Metadata for tutorials') + 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}") + + available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) + + tutorials = {} + for tutorial in available_tutorials: + cases_combinations = [ + f"{combination}" for combination in tutorial.case_combinations] + tutorials[tutorial.path.name] = cases_combinations + + print(yaml.dump(tutorials)) + + +if __name__ == '__main__': + main() diff --git a/tools/tests/print_metadata.py b/tools/tests/print_metadata.py new file mode 100644 index 000000000..500e549c9 --- /dev/null +++ b/tools/tests/print_metadata.py @@ -0,0 +1,26 @@ +from metadata_parser.metdata import Tutorials +from paths import PRECICE_TUTORIAL_DIR + +import argparse +import logging + + +def main(): + parser = argparse.ArgumentParser(description='Prints available Metadata for tutorials') + 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}") + + available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) + print("Fount the following tutorials read from the metadata.yaml") + for tutorial in available_tutorials: + print(tutorial) + + +if __name__ == '__main__': + main() diff --git a/tools/tests/print_test_suites.py b/tools/tests/print_test_suites.py new file mode 100644 index 000000000..6fc1e4039 --- /dev/null +++ b/tools/tests/print_test_suites.py @@ -0,0 +1,29 @@ +from metadata_parser.metdata import Tutorials +from systemtests.TestSuite import TestSuites +from paths import PRECICE_TESTS_DIR, PRECICE_TUTORIAL_DIR + + +import argparse +import logging + + +def main(): + parser = argparse.ArgumentParser(description='Prints available Test Suites') + 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}") + + available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) + available_testsuites = TestSuites.from_yaml( + PRECICE_TESTS_DIR / "tests.yaml", available_tutorials) + + print(available_testsuites) + + +if __name__ == '__main__': + main() diff --git a/tools/tests/reference_results.metadata.template b/tools/tests/reference_results.metadata.template new file mode 100644 index 000000000..d7f189fe2 --- /dev/null +++ b/tools/tests/reference_results.metadata.template @@ -0,0 +1,34 @@ + + +# 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 | +|------|------|-------| +{% for file in files -%} +| {{ file.name }} | {{ file.time }} | {{ file.sha256 }} | +{% endfor %} +## List of arguments used to generate the files + +| name | value | +|------|------| +{% for name,value in arguments.items() -%} +| {{ name }} | {{ value }} | +{% endfor -%} + + +## Information about the machine + +### uname -a + +{{ uname }} + +### lscpu + +{{ lscpu }} \ No newline at end of file diff --git a/tools/tests/reference_versions.yaml b/tools/tests/reference_versions.yaml new file mode 100644 index 000000000..7497b4dbd --- /dev/null +++ b/tools/tests/reference_versions.yaml @@ -0,0 +1,11 @@ +PRECICE_REF: "v3.1.1" +OPENFOAM_EXECUTABLE: "openfoam2312" +OPENFOAM_ADAPTER_REF: "v1.3.0" +PYTHON_BINDINGS_REF: "v3.1.0" +FENICS_ADAPTER_REF: "v2.1.0" +TUTORIALS_REF: "340b447" # April 12, 2024, just before v202404.0 +PLATFORM: "ubuntu_2204" +CALULIX_VERSION: "2.20" +CALULIX_ADAPTER_REF: "v2.20.1" +SU2_VERSION: "7.5.1" +SU2_ADAPTER_REF: "64d4aff" # Distribution v2404 diff --git a/tools/tests/requirements.txt b/tools/tests/requirements.txt new file mode 100644 index 000000000..df67e0dd1 --- /dev/null +++ b/tools/tests/requirements.txt @@ -0,0 +1,2 @@ +jinja2 +pyyaml \ No newline at end of file diff --git a/tools/tests/systemtests.py b/tools/tests/systemtests.py new file mode 100644 index 000000000..7a57bbde0 --- /dev/null +++ b/tools/tests/systemtests.py @@ -0,0 +1,96 @@ + +import argparse +from pathlib import Path +from systemtests.SystemtestArguments import SystemtestArguments +from systemtests.Systemtest import Systemtest, display_systemtestresults_as_table +from systemtests.TestSuite import TestSuites +from metadata_parser.metdata import Tutorials, Case +import logging +import time +from paths import PRECICE_TUTORIAL_DIR, PRECICE_TESTS_RUN_DIR, PRECICE_TESTS_DIR + + +def main(): + parser = argparse.ArgumentParser(description='systemtest') + + # Add an argument for the components + parser.add_argument('--suites', type=str, + help='Comma-separated test-suites to execute') + parser.add_argument( + '--build_args', + type=str, + help='Comma-separated list of arguments provided to the components like openfoam:2102,pythonbindings:latest') + 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') + + # 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') + + print(f"Using log-level: {args.log_level}") + + systemtests_to_run = [] + available_tutorials = Tutorials.from_path(PRECICE_TUTORIAL_DIR) + + build_args = SystemtestArguments.from_args(args.build_args) + run_directory = Path(args.rundir) + if args.suites: + 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) + if not test_suite_found: + logging.error(f"Did not find the testsuite with name {test_suite_requested}") + else: + test_suites_to_execute.append(test_suite_found) + if not test_suites_to_execute: + raise RuntimeError( + f"No matching test suites with names {test_suites_requested} found. Use print_test_suites.py to get an overview") + # now convert the test_suites into systemtests + for test_suite in test_suites_to_execute: + tutorials = test_suite.cases_of_tutorial.keys() + for tutorial in tutorials: + for case, reference_result in zip( + test_suite.cases_of_tutorial[tutorial], test_suite.reference_results[tutorial]): + systemtests_to_run.append( + Systemtest(tutorial, build_args, case, reference_result)) + + 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}") + + results = [] + for number, systemtest in enumerate(systemtests_to_run): + 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} seconds") + 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}") + + display_systemtestresults_as_table(results) + if system_test_success: + exit(0) + else: + exit(1) + + +if __name__ == '__main__': + main() diff --git a/tools/tests/systemtests/Systemtest.py b/tools/tests/systemtests/Systemtest.py new file mode 100644 index 000000000..eacb5ace4 --- /dev/null +++ b/tools/tests/systemtests/Systemtest.py @@ -0,0 +1,629 @@ +import subprocess +from typing import List, Dict, Optional +from jinja2 import Environment, FileSystemLoader +from dataclasses import dataclass, field +import shutil +from pathlib import Path +from paths import PRECICE_REL_OUTPUT_DIR, PRECICE_TOOLS_DIR, PRECICE_REL_REFERENCE_DIR, PRECICE_TESTS_DIR, PRECICE_TUTORIAL_DIR + +from metadata_parser.metdata import Tutorial, CaseCombination, Case, ReferenceResult +from .SystemtestArguments import SystemtestArguments + +from datetime import datetime +import tarfile +import time + +import unicodedata +import re +import logging +import os + + +GLOBAL_TIMEOUT = 600 +SHORT_TIMEOUT = 10 + + +def slugify(value, allow_unicode=False): + """ + Taken from https://github.com/django/django/blob/master/django/utils/text.py + Convert to ASCII if 'allow_unicode' is False. Convert spaces or repeated + dashes to single dashes. Remove characters that aren't alphanumerics, + underscores, or hyphens. Convert to lowercase. Also strip leading and + trailing whitespace, dashes, and underscores. + """ + value = str(value) + if allow_unicode: + value = unicodedata.normalize('NFKC', value) + else: + value = unicodedata.normalize('NFKD', value).encode( + 'ascii', 'ignore').decode('ascii') + value = re.sub(r'[^\w\s-]', '', value.lower()) + return re.sub(r'[-\s]+', '-', value).strip('-_') + + +class Systemtest: + pass + + +@dataclass +class DockerComposeResult: + exit_code: int + stdout_data: List[str] + stderr_data: List[str] + systemtest: Systemtest + runtime: float # in seconds + + +@dataclass +class FieldCompareResult: + exit_code: int + stdout_data: List[str] + stderr_data: List[str] + systemtest: Systemtest + runtime: float # in seconds + + +@dataclass +class SystemtestResult: + success: bool + stdout_data: List[str] + stderr_data: List[str] + systemtest: Systemtest + build_time: float # in seconds + solver_time: float # in seconds + fieldcompare_time: float # in seconds + + +def display_systemtestresults_as_table(results: List[SystemtestResult]): + """ + Prints the result in a nice tabluated way to get an easy overview + """ + 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}} | {'success':^7} | {'building time [s]':^17} | {'solver time [s]':^15} | {'fieldcompare time [s]':^21} |" + separator = "+-" + "-" * (max_name_length + 2) + \ + "-+---------+-------------------+-----------------+-----------------------+" + + print(separator) + print(header) + print(separator) + + for result in results: + row = f"| {str(result.systemtest):<{max_name_length + 2}} | {result.success:^7} | {result.build_time:^17.2f} | {result.solver_time:^15.2f} | {result.fieldcompare_time:^21.2f} |" + print(row) + print(separator) + + +@dataclass +class Systemtest: + """ + Represents a system test by specifing the cases and the corresponding Tutorial + """ + + tutorial: Tutorial + arguments: SystemtestArguments + case_combination: CaseCombination + reference_result: ReferenceResult + params_to_use: Dict[str, str] = field(init=False) + env: Dict[str, str] = field(init=False) + + def __eq__(self, other) -> bool: + if isinstance(other, Systemtest): + return ( + self.tutorial == other.tutorial) and ( + self.arguments == other.arguments) and ( + self.case_combination == other.case_combination) + return False + + def __hash__(self) -> int: + return hash(f"{self.tutorial,self.arguments,self.case_combination}") + + def __post_init__(self): + self.__init_args_to_use() + self.env = {} + + def __init_args_to_use(self): + """ + Checks if all required parameters for the realisation of the cases are supplied in the cmdline arguments. + If a parameter is missing and it's required, an exception is raised. + Otherwise, the default value is used if available. + + In the end it populates the args_to_use dict + + Raises: + Exception: If a required parameter is missing. + """ + self.params_to_use = {} + needed_parameters = set() + for case in self.case_combination.cases: + needed_parameters.update(case.component.parameters) + + for needed_param in needed_parameters: + if self.arguments.contains(needed_param.key): + self.params_to_use[needed_param.key] = self.arguments.get( + needed_param.key) + else: + if needed_param.required: + raise Exception( + f"{needed_param} is needed to be given via --params to instantiate the systemtest for {self.tutorial.name}") + else: + self.params_to_use[needed_param.key] = needed_param.default + + def __get_docker_services(self) -> Dict[str, str]: + """ + Renders the service templates for each case using the parameters to use. + + Returns: + A dictionary of rendered services per case name. + """ + try: + plaform_requested = self.params_to_use.get("PLATFORM") + except Exception as exc: + raise KeyError("Please specify a PLATFORM argument") from exc + + self.dockerfile_context = PRECICE_TESTS_DIR / "dockerfiles" / Path(plaform_requested) + if not self.dockerfile_context.exists(): + raise ValueError( + f"The path {self.dockerfile_context.resolve()} resulting from argument PLATFORM={plaform_requested} could not be found in the system") + + def render_service_template_per_case(case: Case, params_to_use: Dict[str, str]) -> str: + render_dict = { + 'run_directory': self.run_directory.resolve(), + 'tutorial_folder': self.tutorial_folder, + 'build_arguments': params_to_use, + 'params': params_to_use, + 'case_folder': case.path, + 'run': case.run_cmd, + 'dockerfile_context': self.dockerfile_context, + } + jinja_env = Environment(loader=FileSystemLoader(PRECICE_TESTS_DIR)) + template = jinja_env.get_template(case.component.template) + return template.render(render_dict) + + rendered_services = {} + for case in self.case_combination.cases: + rendered_services[case.name] = render_service_template_per_case( + case, self.params_to_use) + return rendered_services + + def __get_docker_compose_file(self): + rendered_services = self.__get_docker_services() + render_dict = { + 'run_directory': self.run_directory.resolve(), + 'tutorial_folder': self.tutorial_folder, + 'tutorial': self.tutorial.path.name, + 'services': rendered_services, + 'build_arguments': self.params_to_use, + 'dockerfile_context': self.dockerfile_context, + 'precice_output_folder': PRECICE_REL_OUTPUT_DIR, + } + jinja_env = Environment(loader=FileSystemLoader(PRECICE_TESTS_DIR)) + template = jinja_env.get_template("docker-compose.template.yaml") + return template.render(render_dict) + + def __get_field_compare_compose_file(self): + render_dict = { + 'run_directory': self.run_directory.resolve(), + 'tutorial_folder': self.tutorial_folder, + 'precice_output_folder': PRECICE_REL_OUTPUT_DIR, + 'reference_output_folder': PRECICE_REL_REFERENCE_DIR + "/" + self.reference_result.path.name.replace(".tar.gz", ""), + } + jinja_env = Environment(loader=FileSystemLoader(PRECICE_TESTS_DIR)) + template = jinja_env.get_template( + "docker-compose.field_compare.template.yaml") + return template.render(render_dict) + + def _get_git_ref(self, repository: Path, abbrev_ref=False) -> Optional[str]: + try: + result = subprocess.run([ + "git", + "-C", os.fspath(repository.resolve()), + "rev-parse", + "--abbrev-ref" if abbrev_ref else + "HEAD"], stdout=subprocess.PIPE, + stderr=subprocess.PIPE, text=True, check=True, timeout=60) + current_ref = result.stdout.strip() + return current_ref + except Exception as e: + raise RuntimeError(f"An error occurred while getting the current Git ref: {e}") from e + + def _fetch_ref(self, repository: Path, ref: str): + try: + result = subprocess.run([ + "git", + "-C", os.fspath(repository.resolve()), + "fetch" + ], check=True, timeout=60) + if result.returncode != 0: + raise RuntimeError(f"git command returned code {result.returncode}") + + except Exception as e: + raise RuntimeError(f"An error occurred while fetching origin '{ref}': {e}") + + def _checkout_ref_in_subfolder(self, repository: Path, subfolder: Path, ref: str): + try: + result = subprocess.run([ + "git", + "-C", os.fspath(repository.resolve()), + "checkout", ref, + "--", os.fspath(subfolder.resolve()) + ], check=True, timeout=60) + if result.returncode != 0: + raise RuntimeError(f"git command returned code {result.returncode}") + + except Exception as e: + raise RuntimeError(f"An error occurred while checking out '{ref}' for folder '{repository}': {e}") + + def __copy_tutorial_into_directory(self, run_directory: Path): + """ + Checks out the requested tutorial ref and copies the entire tutorial into a folder to prepare for running. + """ + current_time_string = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + self.run_directory = run_directory + current_ref = self._get_git_ref(PRECICE_TUTORIAL_DIR) + ref_requested = self.params_to_use.get("TUTORIALS_REF") + if ref_requested: + logging.debug(f"Checking out tutorials {ref_requested} before copying") + self._fetch_ref(PRECICE_TUTORIAL_DIR, ref_requested) + self._checkout_ref_in_subfolder(PRECICE_TUTORIAL_DIR, self.tutorial.path, ref_requested) + + self.tutorial_folder = slugify(f'{self.tutorial.path.name}_{self.case_combination.cases}_{current_time_string}') + destination = run_directory / self.tutorial_folder + src = self.tutorial.path + self.system_test_dir = destination + shutil.copytree(src, destination) + + if ref_requested: + with open(destination / "tutorials_ref", 'w') as file: + file.write(ref_requested) + self._checkout_ref_in_subfolder(PRECICE_TUTORIAL_DIR, self.tutorial.path, current_ref) + + def __copy_tools(self, run_directory: Path): + destination = run_directory / "tools" + src = PRECICE_TOOLS_DIR + try: + shutil.copytree(src, destination) + except Exception as e: + logging.debug(f"tools are already copied: {e} ") + + def __put_gitignore(self, run_directory: Path): + # Create the .gitignore file with a single asterisk + gitignore_file = run_directory / ".gitignore" + with gitignore_file.open("w") as file: + file.write("*") + + def __cleanup(self): + shutil.rmtree(self.run_directory) + + def __get_uid_gid(self): + try: + uid = int(subprocess.check_output(["id", "-u"]).strip()) + gid = int(subprocess.check_output(["id", "-g"]).strip()) + return uid, gid + except Exception as e: + logging.error("Error getting group and user id: ", e) + + def __write_env_file(self): + with open(self.system_test_dir / ".env", "w") as env_file: + for key, value in self.env.items(): + env_file.write(f"{key}={value}\n") + + def __unpack_reference_results(self): + with tarfile.open(self.reference_result.path) as reference_results_tared: + # specify which folder to extract to + reference_results_tared.extractall(self.system_test_dir / PRECICE_REL_REFERENCE_DIR) + logging.debug( + f"extracting {self.reference_result.path} into {self.system_test_dir / PRECICE_REL_REFERENCE_DIR}") + + def _run_field_compare(self): + """ + Writes the Docker Compose file to disk, executes docker-compose up, and handles the process output. + + Args: + docker_compose_content: The content of the Docker Compose file. + + Returns: + A SystemtestResult object containing the state. + """ + logging.debug(f"Running fieldcompare for {self}") + time_start = time.perf_counter() + self.__unpack_reference_results() + docker_compose_content = self.__get_field_compare_compose_file() + 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 + process = subprocess.Popen(['docker', + 'compose', + '--file', + 'docker-compose.field_compare.yaml', + 'up', + '--exit-code-from', + 'field-compare'], + 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() + 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) + stdout_data.extend(stdout.decode().splitlines()) + stderr_data.extend(stderr.decode().splitlines()) + process.poll() + 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) + + def _build_docker(self): + """ + Builds the docker image + """ + logging.debug(f"Building docker image for {self}") + time_start = time.perf_counter() + docker_compose_content = self.__get_docker_compose_file() + 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) + + def _run_tutorial(self): + """ + Runs precice couple + + Returns: + A DockerComposeResult object containing the state. + """ + 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=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 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) + + 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 / "stdout.log", 'w') as stdout_file: + stdout_file.write("\n".join(stdout_data)) + with open(self.system_test_dir / "stderr.log", 'w') as stderr_file: + stderr_file.write("\n".join(stderr_data)) + + def __prepare_for_run(self, run_directory: Path): + """ + Prepares the run_directory with folders and datastructures needed for every systemtest execution + """ + self.__copy_tutorial_into_directory(run_directory) + self.__copy_tools(run_directory) + self.__put_gitignore(run_directory) + host_uid, host_gid = self.__get_uid_gid() + self.params_to_use['PRECICE_UID'] = host_uid + self.params_to_use['PRECICE_GID'] = host_gid + + 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) + 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, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=0, + fieldcompare_time=0) + + docker_run_result = self._run_tutorial() + 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, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=docker_run_result.runtime, + fieldcompare_time=0) + + fieldcompare_result = self._run_field_compare() + std_out.extend(fieldcompare_result.stdout_data) + std_err.extend(fieldcompare_result.stderr_data) + if fieldcompare_result.exit_code != 0: + self.__write_logs(std_out, std_err) + logging.critical(f"Fieldcompare returned non zero exit code, therefore {self} failed") + return SystemtestResult( + False, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=docker_run_result.runtime, + fieldcompare_time=fieldcompare_result.runtime) + + # self.__cleanup() + self.__write_logs(std_out, std_err) + return SystemtestResult( + True, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=docker_run_result.runtime, + fieldcompare_time=fieldcompare_result.runtime) + + 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) + 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, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=0, + fieldcompare_time=0) + + docker_run_result = self._run_tutorial() + 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, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=docker_run_result.runtime, + fieldcompare_time=0) + + self.__write_logs(std_out, std_err) + return SystemtestResult( + True, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=docker_run_result.runtime, + fieldcompare_time=0) + + 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) + 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, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=0, + fieldcompare_time=0) + + self.__write_logs(std_out, std_err) + return SystemtestResult( + True, + std_out, + std_err, + self, + build_time=docker_build_result.runtime, + solver_time=0, + fieldcompare_time=0) + + def get_system_test_dir(self) -> Path: + return self.system_test_dir diff --git a/tools/tests/systemtests/SystemtestArguments.py b/tools/tests/systemtests/SystemtestArguments.py new file mode 100644 index 000000000..2b7b3eeec --- /dev/null +++ b/tools/tests/systemtests/SystemtestArguments.py @@ -0,0 +1,39 @@ +from dataclasses import dataclass +import yaml +from typing import Optional + + +@dataclass +class SystemtestArguments: + arguments: dict[str, str] + + @classmethod + def from_args(cls, cmd_args): + if not cmd_args: + return cls({}) + + params_provided = cmd_args.split(",") + arguments = {} + for param in params_provided: + key, value = param.split(":") + arguments[key] = value + + return cls(arguments) + + @classmethod + def from_yaml(cls, yml_file): + if not yml_file: + return cls({}) + arguments = {} + with open(yml_file, 'r') as f: + arguments = yaml.safe_load(f) + return cls(arguments) + + def __repr__(self): + return f"{self.arguments}" + + def contains(self, argument_key): + return argument_key in self.arguments.keys() + + def get(self, argument_key) -> Optional[str]: + return self.arguments[argument_key] diff --git a/tools/tests/systemtests/TestSuite.py b/tools/tests/systemtests/TestSuite.py new file mode 100644 index 000000000..9d8c2ac72 --- /dev/null +++ b/tools/tests/systemtests/TestSuite.py @@ -0,0 +1,109 @@ +from dataclasses import dataclass, field +from typing import Optional, List, Dict +from metadata_parser.metdata import Tutorials, Tutorial, Case, CaseCombination, ReferenceResult + +import yaml + + +@dataclass +class TestSuite: + name: str + cases_of_tutorial: Dict[Tutorial, List[CaseCombination]] + reference_results: Dict[Tutorial, List[ReferenceResult]] + + def __repr__(self) -> str: + return_string = f"Test suite: {self.name} contains:" + for tutorial, cases in self.cases_of_tutorial.items(): + return_string += f""" + {tutorial.name} + cases: {cases} + reference_results: {self.reference_results[tutorial]}""" + + return return_string + + +class TestSuites(list): + """ + Represents the collection of testsuites read in from the tests.yaml + """ + + def __init__(self, testsuites: List[TestSuite]): + self.testsuites = testsuites + + @classmethod + def from_yaml(cls, path, parsed_tutorials: Tutorials): + """ + Creates a TestSuites instance from a YAML file. + + Args: + path: The path to the YAML file. + + Returns: + An instance of TestSuites. + """ + testsuites = [] + with open(path, 'r') as f: + data = yaml.safe_load(f) + test_suites_raw = data['test_suites'] + for test_suite_name in test_suites_raw: + case_combinations_of_tutorial = {} + reference_results_of_tutorial = {} + # iterate over tutorials: + for tutorial_case in test_suites_raw[test_suite_name]['tutorials']: + tutorial = parsed_tutorials.get_by_path(tutorial_case['path']) + if not tutorial: + raise Exception(f"No tutorial with path {tutorial_case['path']} found.") + # initialize the datastructure for the new Testsuite + if tutorial not in case_combinations_of_tutorial: + case_combinations_of_tutorial[tutorial] = [] + reference_results_of_tutorial[tutorial] = [] + + all_case_combinations = tutorial.case_combinations + case_combination_requested = CaseCombination.from_string_list( + tutorial_case['case_combination'], tutorial) + if case_combination_requested in all_case_combinations: + case_combinations_of_tutorial[tutorial].append(case_combination_requested) + reference_results_of_tutorial[tutorial].append(ReferenceResult( + tutorial_case['reference_result'], case_combination_requested)) + else: + raise Exception( + f"Could not find the following cases {tutorial_case['case-combination']} in the current metadata of tutorial {tutorial.name}") + + testsuites.append(TestSuite(test_suite_name, case_combinations_of_tutorial, + reference_results_of_tutorial)) + + return cls(testsuites) + + def __iter__(self): + return iter(self.testsuites) + + def __getitem__(self, index): + return self.testsuites[index] + + def __setitem__(self, index, value): + self.testsuites[index] = value + + def __len__(self): + return len(self.testsuites) + + def get_by_name(self, name_to_search) -> Optional[TestSuite]: + """ + Retrieves a testsuite by its name. + + Args: + name_to_search: The name of the testsuite to search for. + + Returns: + The component with the specified name, or None if not found. + """ + for testsuite in self.testsuites: + if testsuite.name == name_to_search: + return testsuite + + return None + + def __repr__(self) -> str: + return_str = "" + for tests_suite in self.testsuites: + return_str += f"{tests_suite}\n\n" + return return_str diff --git a/tools/tests/systemtests/__init__.py b/tools/tests/systemtests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tools/tests/tests.yaml b/tools/tests/tests.yaml new file mode 100644 index 000000000..f68b36b0f --- /dev/null +++ b/tools/tests/tests.yaml @@ -0,0 +1,97 @@ +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 + - path: perpendicular-flap + case_combination: + - fluid-openfoam + - solid-calculix + reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-calculix.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 + fenics_test: + tutorials: + - 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 + nutils_test: + tutorials: + - path: flow-over-heated-plate + case_combination: + - fluid-openfoam + - solid-nutils + reference_result: ./flow-over-heated-plate/reference-results/fluid-openfoam_solid-nutils.tar.gz + calculix_test: + tutorials: + - path: perpendicular-flap + case_combination: + - fluid-openfoam + - solid-calculix + reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-calculix.tar.gz + su2_test: + tutorials: + - path: perpendicular-flap + case_combination: + - fluid-su2 + - solid-fenics + reference_result: ./perpendicular-flap/reference-results/fluid-su2_solid-fenics.tar.gz + elastic_tube_1d_test: + 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: + tutorials: + - path: elastic-tube-1d + case_combination: + - fluid-cpp + - solid-python + reference_result: ./elastic-tube-1d/reference-results/fluid-cpp_solid-python.tar.gz + - path: flow-over-heated-plate + 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 + 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 + case_combination: + - fluid-openfoam + - solid-openfoam + reference_result: ./flow-over-heated-plate/reference-results/fluid-openfoam_solid-openfoam.tar.gz + - path: perpendicular-flap + case_combination: + - fluid-openfoam + - solid-calculix + reference_result: ./perpendicular-flap/reference-results/fluid-openfoam_solid-calculix.tar.gz + - path: perpendicular-flap + case_combination: + - fluid-su2 + - solid-fenics + reference_result: ./perpendicular-flap/reference-results/fluid-su2_solid-fenics.tar.gz diff --git a/tools/visualize-configs.sh b/tools/visualize-configs.sh new file mode 100755 index 000000000..145e2042c --- /dev/null +++ b/tools/visualize-configs.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# Run this script at the root of the repository to generate PNG files from each precice-config.xml + +set -e -u + +visualize_config(){ + ( + if [[ "$1" == quickstart ]]; then + outfile="images/quickstart-precice-config" + else + outfile="images/tutorials-$1-precice-config" + fi + + cd "$1" + if [ -f precice-config.xml ]; then + echo "Visualizing the configuration in $1" + mkdir -p images + precice-config-visualizer -o "$outfile.dot" precice-config.xml + + # Special case, to be removed once bug https://github.com/precice/config-visualizer/issues/22 + if [[ "$1" == partitioned-heat-conduction-direct ]]; then + sed 's/compound=True;//' --in-place "$outfile.dot" + fi + + dot -Tpng "$outfile.dot" > "$outfile.png" + rm "$outfile.dot" + fi + ) +} + +export -f visualize_config + +python3 -m venv .venv +. .venv/bin/activate +pip install precice-config-visualizer + +tutorials=$(find . -maxdepth 1 -type d -not -name ".*" | sed "s/^.\///") + +if command -v parallel &> /dev/null; then + parallel visualize_config ::: "$tutorials" +else + visualize_config ::: "$tutorials" +fi diff --git a/turek-hron-fsi3/.gitignore b/turek-hron-fsi3/.gitignore deleted file mode 100644 index 5515bdeb9..000000000 --- a/turek-hron-fsi3/.gitignore +++ /dev/null @@ -1 +0,0 @@ -solid-dealii/nonlinear_elasticity diff --git a/turek-hron-fsi3/README.md b/turek-hron-fsi3/README.md index f03e88a06..05240cc59 100644 --- a/turek-hron-fsi3/README.md +++ b/turek-hron-fsi3/README.md @@ -17,16 +17,18 @@ The setup is shown schematically here: For more information please refer to the original publication of the benchmark [1]. +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-turek-hron-fsi3-precice-config.png) + ## Available solvers 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://www.precice.org/adapter-openfoam-overview.html). -{% important %} -For the parabolic inflow profile, this tutorial requires groovyBC. groovyBC is part of swak4Foam. You can find more explanations in [openfoamwiki.net](https://openfoamwiki.net/index.php/Contrib/swak4Foam) or get it from an [unofficial GitHub mirror](https://github.com/Unofficial-Extend-Project-Mirror/openfoam-extend-swak4Foam-dev.git). Please follow the building instructions there. -{% endimportant %} - Solid participant: * deal.II. For more information, have a look at the [deal.II adapter documentation](https://www.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. diff --git a/turek-hron-fsi3/fluid-openfoam/0/U b/turek-hron-fsi3/fluid-openfoam/0/U index 298a0809e..8bd25ec5f 100644 --- a/turek-hron-fsi3/fluid-openfoam/0/U +++ b/turek-hron-fsi3/fluid-openfoam/0/U @@ -16,7 +16,7 @@ boundaryField cylinder { type noSlip; - } + } flap { @@ -36,11 +36,39 @@ boundaryField inlet { - // Time-varying parabolic inlet profile - type groovyBC; - variables "yp=pts().y;minY=min(yp);maxY=max(yp);para=-1.5*(maxY-pos().y)*(pos().y-minY)/(0.25*pow(maxY-minY,2))*normal();"; - valueExpression "time()<2 ? 0.5*(1-cos(0.5*pi*time()))*2*para : 2*para"; - value uniform (2 0 0); + // Time-varying parabolic inlet profile + type codedFixedValue; + value uniform (1 0 0); + name parabolicVelocity; + + code + #{ + const vectorField& Cf = patch().Cf(); + vectorField& field = *this; + + const scalar pi = constant::mathematical::pi; + const scalar Umean = 2.0; + const scalar H = 0.41; // channel height + const scalar H_2 = H * H; // equals 0.1681 + const scalar t = this->db().time().value(); + // ramp up below 2 seconds + if (t < 2) + { + forAll(Cf, faceI) + { + const scalar y = Cf[faceI].y(); + field[faceI] = vector((1.5 * Umean * 4.0 / H_2) * y * (H - y) * ((1 - cos((pi / 2) * t)) / 2), 0, 0); + } + } + else + { + forAll(Cf, faceI) + { + const scalar y = Cf[faceI].y(); + field[faceI] = vector((1.5 * Umean * 4.0 / H_2) * y * (H - y), 0, 0); + } + } + #}; } outlet diff --git a/turek-hron-fsi3/fluid-openfoam/run.sh b/turek-hron-fsi3/fluid-openfoam/run.sh index c191b9e48..da82a9ba2 100755 --- a/turek-hron-fsi3/fluid-openfoam/run.sh +++ b/turek-hron-fsi3/fluid-openfoam/run.sh @@ -1,8 +1,12 @@ -#!/bin/sh +#!/bin/bash set -e -u +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + blockMesh -touch fluid-openfoam.foam ../../tools/run-openfoam.sh "$@" . ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/turek-hron-fsi3/fluid-openfoam/system/controlDict b/turek-hron-fsi3/fluid-openfoam/system/controlDict index 8be725212..3091c4343 100644 --- a/turek-hron-fsi3/fluid-openfoam/system/controlDict +++ b/turek-hron-fsi3/fluid-openfoam/system/controlDict @@ -9,8 +9,6 @@ FoamFile application pimpleFoam; // latest OpenFOAM // application pimpleDyMFoam; // OpenFOAM v1712, OpenFOAM 5.x, or older -libs ( "libgroovyBC.so" ) ; - startFrom startTime; startTime 0; diff --git a/turek-hron-fsi3/images/tutorials-turek-hron-fsi3-precice-config.png b/turek-hron-fsi3/images/tutorials-turek-hron-fsi3-precice-config.png new file mode 100644 index 000000000..e74878ef3 Binary files /dev/null and b/turek-hron-fsi3/images/tutorials-turek-hron-fsi3-precice-config.png differ diff --git a/turek-hron-fsi3/precice-config.xml b/turek-hron-fsi3/precice-config.xml index cd39d7e5a..ae004917b 100644 --- a/turek-hron-fsi3/precice-config.xml +++ b/turek-hron-fsi3/precice-config.xml @@ -1,4 +1,4 @@ - + - - - + + - - - + + + - - - + + + - - - - + + + + - - - - - - - - + + + + + + + + + + - - - - - - - - + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/two-scale-heat-conduction/README.md b/two-scale-heat-conduction/README.md new file mode 100644 index 000000000..43435a518 --- /dev/null +++ b/two-scale-heat-conduction/README.md @@ -0,0 +1,91 @@ +--- +title: Two-scale heat conduction +permalink: tutorials-two-scale-heat-conduction.html +keywords: Macro-micro, Micro Manager, Nutils, DuMuX, Heat conduction +summary: We solve a two-scale heat conduction problem with a predefined micro structure of two materials. One macro simulation is coupled to several micro simulations using the Micro Manager. +--- + +{% note %} +Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/two-scale-heat-conduction). Read how in the [tutorials introduction](https://www.precice.org/tutorials.html). +{% endnote %} + +## Setup + +This tutorial solves a heat conduction problem on a 2D domain which has an underlying micro-structure. This micro-structure changes the constituent quantities necessary for solving the problem on the macro scale. This leads to a two-scale problem with one macro-scale simulation and several micro-scale simulations. + +![Case setup of two-scale-heat-conduction case](images/tutorials-two-scale-heat-conduction-macro-micro-schematic.png) + +At each Gauss point of the macro domain there exists a micro simulation. The macro problem is one participant, which is coupled to many micro simulations. Each micro simulation is not an individual coupling participant, instead we use a managing software which controls all the micro simulations and their coupling via preCICE. The case is chosen from the first example case in the publication + +*Bastidas, Manuela & Bringedal, Carina & Pop, Iuliu Sorin (2021), A two-scale iterative scheme for a phase-field model for precipitation and dissolution in porous media. Applied Mathematics and Computation. 396. 125933. [10.1016/j.amc.2020.125933](https://doi.org/10.1016/j.amc.2020.125933)*. + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-two-scale-heat-conduction-precice-config.png) + +## Available solvers and dependencies + +* Both the macro and micro simulations can be solved using the finite element library [Nutils](https://nutils.org/install.html) v7 or the simulation framework [DuMux](https://git.iws.uni-stuttgart.de/dumux-repositories/dumux/). +* While using Nutils, the macro simulation is written in Python, so it requires the [Python bindings of preCICE](https://precice.org/installation-bindings-python.html). +* The [Micro Manager](https://precice.org/tooling-micro-manager-installation.html) controls all micro-simulations and facilitates coupling via preCICE. Use the [develop](https://github.com/precice/micro-manager/tree/develop) branch of the Micro Manager. + +### DuMux setup + +To solve either the macro or micro simulations with the DuMux framework, the necessary DUNE modules need to be downloaded and set up. This is done by running `sh setup-dumux.sh` in the tutorial folder. + +Note that if an existing installation of DUNE modules is detected in a default location, this may lead to problems in running the `setup-dumux.sh` script. The environment variable `DUNE_CONTROL_PATH` is suppressed by the script. + +## Running the simulation + +You can find the corresponding `run.sh`script for running the case in the folders corresponding to the solvers you want to use. + +Run the macro problem: + +```bash +cd macro-nutils +./run.sh +``` + +Check the Micro Manager [configuration](https://precice.org/tooling-micro-manager-configuration.html) and [running](https://precice.org/tooling-micro-manager-running.html) documentation to understand how to set it up and launch it. There is a Python script `run-micro-problems.py` in the tutorial directory to directly run the Micro Manager. This script imports the Micro Manager, and calls its `solve()` method. The Micro Manager can be run via this script in serial or parallel. Run it in serial: + +```bash +cd micro-nutils +./run.sh -s +``` + +If you want to use DuMux, use `cd macro-dumux` instead of `cd macro-nutils` and/or `cd micro-dumux` instead of `cd micro-nutils`. + +## Running the simulation in parallel + +Only the `micro-nutils` participant can be run in parallel. To run it in parallel, run: + +```bash +cd micro-nutils +./run.sh -p +``` + +The `num_procs` needs to fit the decomposition specified in the `micro-manager-config.json` (default: two ranks). + +**NOTE**: When running `micro-nutils`, even though the case setup and involved physics is simple, each micro simulation is an instance of Nutils, which usually has a moderately high computation time. If the Micro Manager is run on 2 processors, the total runtime is approximately 10-15 minutes depending on the compute machine. Do not run the Micro Manager in serial, because the runtime will be several hours. + +Running `micro-dumux` is much faster. A serial simulation takes approximately 2 minutes to finish. + +## Post-processing + +Here are the results from Nutils-Nutils and DuMux-DuMux combination: + +Macro and micro data of macro-nutils - micro-nutils simulation + +Macro and micro data of macro-nutils - micro-nutils simulation + +The differences of the fields are mainly introduced in by the different numerical schemes in the two solvers. + +The participant `macro-nutils` outputs `macro-*.vtk` files which can be viewed in ParaView to see the macro concentration field. The Micro Manager uses the [export functionality](https://precice.org/configuration-export.html#enabling-exporters) of preCICE to output micro simulation data and [adaptivity related data](https://precice.org/tooling-micro-manager-configuration.html#adding-adaptivity-in-the-precice-xml-configuration) to VTU files which can be viewed in ParaView. To view the data on each micro simulation, create a Glyph on the Micro Manager VTU data. In the figure above, micro-scale porosity is shown. For a lower concentration value, the porosity increases (in the lower left corner). + +Adaptive mesh refinement in the micro simulation + +The micro simulations themselves have a circular micro structure which is resolved in every time step. To output VTK files for each micro simulation, uncomment the `output()` function in the file `micro-nutils/micro.py`. The figure above shows the changing phase field used to represent the circular micro structure and the diffuse interface width. + +Similar to the output data files from simulation with Nutils, the `VTU` files from macro and micro solvers, that are written in DuMux, could also be rendered and inspected with ParaView with the mentioned method. diff --git a/two-scale-heat-conduction/clean-tutorial.sh b/two-scale-heat-conduction/clean-tutorial.sh new file mode 120000 index 000000000..4713f5092 --- /dev/null +++ b/two-scale-heat-conduction/clean-tutorial.sh @@ -0,0 +1 @@ +../tools/clean-tutorial-base.sh \ No newline at end of file diff --git a/two-scale-heat-conduction/compile-dumux-cases.sh b/two-scale-heat-conduction/compile-dumux-cases.sh new file mode 100755 index 000000000..82b796be5 --- /dev/null +++ b/two-scale-heat-conduction/compile-dumux-cases.sh @@ -0,0 +1,12 @@ +#!/bin/sh +set -e -u + +cd macro-dumux/build-cmake/appl +make macro_dumux +cd ../../../micro-dumux/build-cmake/appl +make +cd ../../../ + +# Move macro-dumux and micro-dumux executables to the participant folder level +mv macro-dumux/build-cmake/appl/macro_dumux macro-dumux/ +mv micro-dumux/build-cmake/appl/micro_sim.cpython-310-x86_64-linux-gnu.so micro-dumux/ diff --git a/two-scale-heat-conduction/images/tutorials-two-scale-heat-conduction-evolving-micro-simulations.png b/two-scale-heat-conduction/images/tutorials-two-scale-heat-conduction-evolving-micro-simulations.png new file mode 100644 index 000000000..602b4f6f5 Binary files /dev/null and b/two-scale-heat-conduction/images/tutorials-two-scale-heat-conduction-evolving-micro-simulations.png differ diff --git a/two-scale-heat-conduction/images/tutorials-two-scale-heat-conduction-macro-micro-schematic.png b/two-scale-heat-conduction/images/tutorials-two-scale-heat-conduction-macro-micro-schematic.png new file mode 100644 index 000000000..f6a8a538e Binary files /dev/null and b/two-scale-heat-conduction/images/tutorials-two-scale-heat-conduction-macro-micro-schematic.png differ diff --git a/two-scale-heat-conduction/images/tutorials-two-scale-heat-conduction-precice-config.png b/two-scale-heat-conduction/images/tutorials-two-scale-heat-conduction-precice-config.png new file mode 100644 index 000000000..c4d6bd152 Binary files /dev/null and b/two-scale-heat-conduction/images/tutorials-two-scale-heat-conduction-precice-config.png differ diff --git a/two-scale-heat-conduction/images/tutorials-two-scale-heat-conduction-results-du-du.png b/two-scale-heat-conduction/images/tutorials-two-scale-heat-conduction-results-du-du.png new file mode 100644 index 000000000..4fa15e90d Binary files /dev/null and b/two-scale-heat-conduction/images/tutorials-two-scale-heat-conduction-results-du-du.png differ diff --git a/two-scale-heat-conduction/images/tutorials-two-scale-heat-conduction-results.png b/two-scale-heat-conduction/images/tutorials-two-scale-heat-conduction-results.png new file mode 100644 index 000000000..ce00f5c6a Binary files /dev/null and b/two-scale-heat-conduction/images/tutorials-two-scale-heat-conduction-results.png differ diff --git a/two-scale-heat-conduction/macro-dumux/CMakeLists.txt b/two-scale-heat-conduction/macro-dumux/CMakeLists.txt new file mode 100644 index 000000000..f639a0a70 --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.13) +project(macro-dumux CXX) + +if(NOT (dune-common_DIR OR dune-common_ROOT OR + "${CMAKE_PREFIX_PATH}" MATCHES ".*dune-common.*")) + string(REPLACE ${PROJECT_NAME} dune-common dune-common_DIR + ${PROJECT_BINARY_DIR}) +endif() + +#find dune-common and set the module path +find_package(dune-common REQUIRED) +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules" + ${dune-common_MODULE_PATH}) + +#include the dune macros +include(DuneMacros) + +# start a dune project with information from dune.module +dune_project() + +dune_enable_all_packages() + +add_subdirectory(doc) +add_subdirectory(cmake/modules) +add_subdirectory(appl) + +# finalize the dune project, e.g. generating config.h etc. +finalize_dune_project(GENERATE_CONFIG_H_CMAKE) diff --git a/two-scale-heat-conduction/macro-dumux/appl/CMakeLists.txt b/two-scale-heat-conduction/macro-dumux/appl/CMakeLists.txt new file mode 100644 index 000000000..a800ea3e7 --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/appl/CMakeLists.txt @@ -0,0 +1,7 @@ +add_executable(macro_dumux main.cc) +target_compile_definitions(macro_dumux PUBLIC "ENABLEMONOLITHIC=0") +target_link_libraries(macro_dumux PRIVATE dumux-precice) +target_compile_definitions(macro_dumux PUBLIC TYPETAG=OnePNIConductionCCTpfa) + +# add a symlink for each input file +add_input_file_links() diff --git a/two-scale-heat-conduction/macro-dumux/appl/main.cc b/two-scale-heat-conduction/macro-dumux/appl/main.cc new file mode 100644 index 000000000..b8897e6c9 --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/appl/main.cc @@ -0,0 +1,372 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "properties.hh" + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include +#include + +int main(int argc, char **argv) +{ + using namespace Dumux; + + // define the type tag for this problem + using TypeTag = Properties::TTag::TYPETAG; + + // make some types available + using Scalar = GetPropType; + + // initialize MPI, finalize is done automatically on exit + const auto &mpiHelper = Dune::MPIHelper::instance(argc, argv); + + // print dumux start message + if (mpiHelper.rank() == 0) + DumuxMessage::print(/*firstCall=*/true); + + // parse command line arguments and input file + Parameters::init(argc, argv); + Parameters::print(); + + // try to create a grid (from the given grid file or the input file) + GridManager> gridManager; + gridManager.init(); + + // we compute on the leaf grid view + const auto &leafGridView = gridManager.grid().leafGridView(); + + // create the finite volume grid geometry + using GridGeometry = GetPropType; + auto gridGeometry = std::make_shared(leafGridView); + + // the problem (initial and boundary conditions) + using Problem = GetPropType; + auto problem = std::make_shared(gridGeometry); + + //////////////////////// + // Initialize preCICE // + //////////////////////// + + // Tell preCICE about: + // - Name of solver + // - What rank of how many ranks this instance is + // Configure preCICE. For now the config file is hardcoded. + std::string preciceConfigFilename = "../precice-config.xml"; + const std::string meshName = "macro-mesh"; + if (argc > 2) + preciceConfigFilename = argv[argc - 1]; + + auto &couplingParticipant = Dumux::Precice::CouplingAdapter::getInstance(); + + if (getParam("Precice.RunWithCoupling") == true) { + couplingParticipant.announceSolver("macro-heat", preciceConfigFilename, + mpiHelper.rank(), mpiHelper.size()); + // verify that dimensions match + const int preciceDim = couplingParticipant.getMeshDimensions(meshName); + const int dim = int(leafGridView.dimension); + std::cout << "coupling Dims = " << dim << " , leafgrid dims = " << dim + << std::endl; + if (preciceDim != dim) + DUNE_THROW(Dune::InvalidStateException, "Dimensions do not match"); + } + + // get mesh coordinates + std::vector coords; + std::vector coupledElementIdxs; + + // coordinate loop (created vectors are 1D) + // these positions of cell centers are later communicated to precice + std::cout << "Coordinates: " << std::endl; + for (const auto &element : elements(leafGridView)) { + auto fvGeometry = localView(*gridGeometry); + fvGeometry.bindElement(element); + for (const auto &scv : scvs(fvGeometry)) { + coupledElementIdxs.push_back(scv.elementIndex()); + const auto &pos = scv.center(); + for (const auto p : pos) { + coords.push_back(p); + std::cout << p << " "; + } + std::cout << " ;" << std::endl; + } + } + std::cout << "Number of Coupled Cells:" << coupledElementIdxs.size() + << std::endl; + + // initialize preCICE + auto numberOfElements = + coords.size() / couplingParticipant.getMeshDimensions(meshName); + if (getParam("Precice.RunWithCoupling") == true) { + couplingParticipant.setMesh(meshName, coords); + + // couples between dumux element indices and preciceIndices; + couplingParticipant.createIndexMapping(coupledElementIdxs); + } + + // initialize the coupling data + const std::string readDatak00 = "k_00"; + const std::string readDatak01 = "k_01"; + const std::string readDatak10 = "k_10"; + const std::string readDatak11 = "k_11"; + const std::string readDataPorosity = "porosity"; + const std::string writeDataConcentration = "concentration"; + // const std::string writeDataTemperature = "temperature"; + + if (getParam("Precice.RunWithCoupling") == true) { + couplingParticipant.announceQuantity(meshName, readDatak00); + couplingParticipant.announceQuantity(meshName, readDatak01); + couplingParticipant.announceQuantity(meshName, readDatak10); + couplingParticipant.announceQuantity(meshName, readDatak11); + couplingParticipant.announceQuantity(meshName, readDataPorosity); + couplingParticipant.announceQuantity(meshName, writeDataConcentration); + // couplingParticipant.announceQuantity(meshName, writeDataTemperature); + } + + // the solution vector (initialized with zeros) NElements x 2(pressure, + // temperature) + using SolutionVector = GetPropType; + SolutionVector x(gridGeometry->numDofs()); + problem->applyInitialSolution(x); + auto xOld = x; + + // initialize the coupling data + std::vector temperatures; + for (int solIdx = 0; solIdx < numberOfElements; ++solIdx) { + temperatures.push_back(x[solIdx][problem->returnTemperatureIdx()]); + }; + + if (getParam("Precice.RunWithCoupling") == true) { + couplingParticipant.writeQuantityVector(meshName, writeDataConcentration, + temperatures); + if (couplingParticipant + .requiresToWriteInitialData()) { // not called in our example + // couplingParticipant.writeQuantityToOtherSolver(meshName, + // writeDataTemperature); + } + + // initialize other data since they are not allowed to be read from micro + // side + std::vector kInitial(numberOfElements, 1.0); + std::vector porosityInitial(numberOfElements, 0.5); + couplingParticipant.writeQuantityVector(meshName, readDatak00, kInitial); + couplingParticipant.writeQuantityVector(meshName, readDatak01, kInitial); + couplingParticipant.writeQuantityVector(meshName, readDatak10, kInitial); + couplingParticipant.writeQuantityVector(meshName, readDatak11, kInitial); + couplingParticipant.writeQuantityVector(meshName, readDataPorosity, + porosityInitial); + } + + // the grid variables + using GridVariables = GetPropType; + auto gridVariables = std::make_shared(problem, gridGeometry); + gridVariables->init(x); + + // intialize the vtk output module + using IOFields = GetPropType; + VtkOutputModule vtkWriter(*gridVariables, x, + problem->name()); + IOFields::initOutputModule(vtkWriter); + // add model specific output fields + vtkWriter.addField(problem->getPorosity(), "porosity"); + vtkWriter.addField(problem->getK00(), "k00"); + vtkWriter.addField(problem->getK01(), "k01"); + vtkWriter.addField(problem->getK10(), "k10"); + vtkWriter.addField(problem->getK11(), "k11"); + problem->updateVtkOutput(x); + vtkWriter.write(0.0); + + // output every vtkOutputInterval time step + const int vtkOutputInterval = getParam("TimeLoop.OutputInterval"); + + // initialize + couplingParticipant.initialize(); + + // get some time loop parameters + const auto tEnd = getParam("TimeLoop.TEnd"); + double preciceDt = couplingParticipant.getMaxTimeStepSize(); + double dt; + if (getParam("Precice.RunWithCoupling") == true) + dt = preciceDt; + else + dt = getParam("TimeLoop.InitialDt"); + + // instantiate time loop + auto timeLoop = std::make_shared>(0.0, dt, tEnd); + + // the assembler with time loop for instationary problem + using Assembler = FVAssembler; + auto assembler = std::make_shared(problem, gridGeometry, + gridVariables, timeLoop, xOld); + + // the linear solver + using LinearSolver = + ILUBiCGSTABIstlSolver, + LinearAlgebraTraitsFromAssembler>; + auto linearSolver = std::make_shared(gridGeometry->gridView(), + gridGeometry->dofMapper()); + + // the non-linear solver + using NewtonSolver = Dumux::NewtonSolver; + NewtonSolver nonLinearSolver(assembler, linearSolver); + + // time loop + int n = 0; // counts timesteps for the output interval + std::cout << "Time Loop starts" << std::endl; + timeLoop->start(); + do { + if (getParam("Precice.RunWithCoupling") == true) { + if (couplingParticipant.isCouplingOngoing() == false) + break; + + // write checkpoint + if (couplingParticipant.requiresToWriteCheckpoint()) { + xOld = x; + } + + // read porosity and conductivity data from other solver + couplingParticipant.readQuantityFromOtherSolver(meshName, readDatak00, + dt); + couplingParticipant.readQuantityFromOtherSolver(meshName, readDatak01, + dt); + couplingParticipant.readQuantityFromOtherSolver(meshName, readDatak10, + dt); + couplingParticipant.readQuantityFromOtherSolver(meshName, readDatak11, + dt); + couplingParticipant.readQuantityFromOtherSolver(meshName, + readDataPorosity, dt); + } + std::cout << "Solver starts" << std::endl; + + // linearize & solve + nonLinearSolver.solve(x, *timeLoop); + + for (int solIdx = 0; solIdx < numberOfElements; ++solIdx) + temperatures[solIdx] = x[solIdx][problem->returnTemperatureIdx()]; + + if (getParam("Precice.RunWithCoupling") == true) { + couplingParticipant.writeQuantityVector(meshName, + writeDataConcentration, temperatures); + couplingParticipant.writeQuantityToOtherSolver(meshName, + writeDataConcentration); + } + + // advance precice + if (getParam("Precice.RunWithCoupling") == true) { + couplingParticipant.advance(dt); + preciceDt = couplingParticipant.getMaxTimeStepSize(); + dt = std::min(preciceDt, std::min(nonLinearSolver.suggestTimeStepSize( + timeLoop->timeStepSize()), + getParam("TimeLoop.MaxDt"))); + if (preciceDt != dt) { + std::cout << "preciceDt too large. We currently assume fixed timestep " + "size but timesteps no longer correspond: preciceDt = " + << preciceDt << " and dt =" << dt << std::endl; + // exit(1); + } + } else + dt = std::min( + nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()), + getParam("TimeLoop.MaxDt")); + + std::cout << "dt: " << dt << std::endl; + + if (getParam("Precice.RunWithCoupling") == true) { + if (couplingParticipant.requiresToReadCheckpoint()) { + // make the new solution the old solution + x = xOld; + gridVariables->update(x); + gridVariables->advanceTimeStep(); + } else // coupling successful + { + n += 1; + if (n == vtkOutputInterval) { + problem->updateVtkOutput(x); + vtkWriter.write(timeLoop->time()); + n = 0; + } + gridVariables->advanceTimeStep(); + // advance the time loop to the next step + timeLoop->advanceTimeStep(); + // report statistics of this time step + timeLoop->reportTimeStep(); + } + } else { + xOld = x; + gridVariables->advanceTimeStep(); + // advance the time loop to the next step + timeLoop->advanceTimeStep(); + // report statistics of this time step + timeLoop->reportTimeStep(); + + // output every outputinterval steps + n += 1; + if (n == vtkOutputInterval) { + problem->updateVtkOutput(x); + vtkWriter.write(timeLoop->time()); + n = 0; + } + } + // set new dt as suggested by the newton solver or by precice + timeLoop->setTimeStepSize(dt); + + std::cout << "Time: " << timeLoop->time() << std::endl; + + } while (!timeLoop->finished()); + + timeLoop->finalize(leafGridView.comm()); + + //////////////////////////////////////////////////////////// + // finalize, print dumux message to say goodbye + //////////////////////////////////////////////////////////// + if (getParam("Precice.RunWithCoupling") == true) { + couplingParticipant.finalize(); + } + // print dumux end message + if (mpiHelper.rank() == 0) { + Parameters::print(); + DumuxMessage::print(/*firstCall=*/false); + } + + return 0; +} // end main diff --git a/two-scale-heat-conduction/macro-dumux/appl/myenergyvolumevariables.hh b/two-scale-heat-conduction/macro-dumux/appl/myenergyvolumevariables.hh new file mode 100644 index 000000000..e3bcc6544 --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/appl/myenergyvolumevariables.hh @@ -0,0 +1,456 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup NIModel + * \brief Base class for the model specific class which provides + * access to all volume averaged quantities. + */ + +#ifndef DUMUX_MY_ENERGY_VOLUME_VARIABLES_HH +#define DUMUX_MY_ENERGY_VOLUME_VARIABLES_HH + +#include +#include + +#include +#include + +namespace Dumux { + +// forward declaration +template +class MyEnergyVolumeVariablesImplementation; + +/*! + * \ingroup NIModel + * \brief Base class for the model specific class which provides + * access to all volume averaged quantities. + * + * The volume variables base class is specialized for isothermal and + * non-isothermal models. + */ +template +using MyEnergyVolumeVariables = MyEnergyVolumeVariablesImplementation< + IsothermalTraits, Impl, + IsothermalTraits::ModelTraits::enableEnergyBalance()>; + +/*! + * \ingroup NIModel + * \brief The isothermal base class + */ +template +class MyEnergyVolumeVariablesImplementation { + using Scalar = typename IsothermalTraits::PrimaryVariables::value_type; + static constexpr int dimWorld = 2; // hardcoded for now + using DimWorldMatrix = Dune::FieldMatrix; + +public: + using FluidState = typename IsothermalTraits::FluidState; + using SolidState = typename IsothermalTraits::SolidState; + using FluidSystem = typename IsothermalTraits::FluidSystem; + + //! The temperature is obtained from the problem as a constant for isothermal + //! models + template + void updateTemperature( + const ElemSol &elemSol, const Problem &problem, const Element &element, + const Scv &scv, FluidState &fluidState, + SolidState &solidState) + { // retrieve temperature from solution vector, + // all phases have the same temperature + Scalar T = problem.spatialParams().temperature(element, scv, elemSol); + for (int phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) { + fluidState.setTemperature(phaseIdx, T); + } + solidState.setTemperature(T); + } + + template + void updateSolidEnergyParams(const ElemSol &elemSol, const Problem &problem, + const Element &element, const Scv &scv, + SolidState &solidState) {} + + //! The phase enthalpy is zero for isothermal models + //! This is needed for completing the fluid state + template + static Scalar enthalpy(const FluidState &fluidState, + const ParameterCache ¶mCache, const int phaseIdx) + { + return 0; + } + + //! The effective thermal conductivity is zero for isothermal models + template + void updateEffectiveThermalConductivity(const ElemSol &elemSol, + const Problem &problem, + const Element &element, + const Scv &scv, + SolidState &solidState) {} +}; + +//! The non-isothermal implicit volume variables base class +template +class MyEnergyVolumeVariablesImplementation { + using Scalar = typename Traits::PrimaryVariables::value_type; + static constexpr int dimWorld = 2; // hardcoded for now + using DimWorldMatrix = Dune::FieldMatrix; + using Idx = typename Traits::ModelTraits::Indices; + using ParentType = PorousMediumFlowVolumeVariables; + + static constexpr int temperatureIdx = Idx::temperatureIdx; + static constexpr int numEnergyEq = Traits::ModelTraits::numEnergyEq(); + + static constexpr bool fullThermalEquilibrium = (numEnergyEq == 1); + static constexpr bool fluidThermalEquilibrium = (numEnergyEq == 2); + +public: + // export the fluidstate + using FluidState = typename Traits::FluidState; + //! export the underlying fluid system + using FluidSystem = typename Traits::FluidSystem; + //! Export the indices + using Indices = Idx; + // export the solidstate + using SolidState = typename Traits::SolidState; + //! export the underlying solid system + using SolidSystem = typename Traits::SolidSystem; + + //! The temperature is obtained from the problem as a constant for isothermal + //! models + template + void updateTemperature(const ElemSol &elemSol, const Problem &problem, + const Element &element, const Scv &scv, + FluidState &fluidState, SolidState &solidState) + { + if constexpr (fullThermalEquilibrium) { + // retrieve temperature from solution vector, all phases have the same + // temperature + const Scalar T = elemSol[scv.localDofIndex()][temperatureIdx]; + for (int phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) { + fluidState.setTemperature(phaseIdx, T); + } + solidState.setTemperature(T); + } + + else { + // this means we have 1 temp for fluid phase, one for solid + if constexpr (fluidThermalEquilibrium) { + const Scalar T = elemSol[scv.localDofIndex()][temperatureIdx]; + for (int phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) { + fluidState.setTemperature(phaseIdx, T); + } + } + // this is for numEnergyEqFluid > 1 + else { + for (int phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) { + // retrieve temperatures from solution vector, phases might have + // different temperature + const Scalar T = + elemSol[scv.localDofIndex()][temperatureIdx + phaseIdx]; + fluidState.setTemperature(phaseIdx, T); + } + } + const Scalar solidTemperature = + elemSol[scv.localDofIndex()][temperatureIdx + numEnergyEq - 1]; + solidState.setTemperature(solidTemperature); + } + } + + template + void updateSolidEnergyParams(const ElemSol &elemSol, const Problem &problem, + const Element &element, const Scv &scv, + SolidState &solidState) + { + Scalar cs = solidHeatCapacity_(elemSol, problem, element, scv, solidState); + solidState.setHeatCapacity(cs); + + Scalar rhos = solidDensity_(elemSol, problem, element, scv, solidState); + solidState.setDensity(rhos); + } + + template + void updateEffectiveThermalConductivity(const ElemSol &elemSol, + const Problem &problem, + const Element &element, + const Scv &scv, + SolidState &solidState) + { + lambdaEff_ = + solidThermalConductivity_(elemSol, problem, element, scv, solidState); + } + + /*! + * \brief Returns the total internal energy of a phase in the + * sub-control volume. + * + * \param phaseIdx The phase index + */ + Scalar internalEnergy(const int phaseIdx) const + { + return asImp_().fluidState().internalEnergy(phaseIdx); + } + + /*! + * \brief Returns the total enthalpy of a phase in the sub-control + * volume. + * + * \param phaseIdx The phase index + */ + Scalar enthalpy(const int phaseIdx) const + { + return asImp_().fluidState().enthalpy(phaseIdx); + } + + /*! + * \brief Returns the temperature in fluid / solid phase(s) + * the sub-control volume. + */ + Scalar temperatureSolid() const + { + return asImp_().solidState().temperature(); + } + + /*! + * \brief Returns the temperature of a fluid phase assuming thermal + * nonequilibrium the sub-control volume. \param phaseIdx The local index of + * the phases + */ + Scalar temperatureFluid(const int phaseIdx) const + { + return asImp_().fluidState().temperature(phaseIdx); + } + + /*! + * \brief Returns the total heat capacity \f$\mathrm{[J/(kg K)]}\f$ of the + * rock matrix in the sub-control volume. + */ + Scalar solidHeatCapacity() const + { + return asImp_().solidState().heatCapacity(); + } + + /*! + * \brief Returns the mass density \f$\mathrm{[kg/m^3]}\f$ of the rock matrix + * in the sub-control volume. + */ + Scalar solidDensity() const + { + return asImp_().solidState().density(); + } + + /*! + * \brief Returns the effective thermal conductivity \f$\mathrm{[W/(m*K)]}\f$ + * in the sub-control volume. Specific to equilibirum models (case + * fullThermalEquilibrium). + */ + template = 0> + DimWorldMatrix effectiveThermalConductivity() const + { + return lambdaEff_; + } + + //! The phase enthalpy is zero for isothermal models + //! This is needed for completing the fluid state + template + static Scalar enthalpy(const FluidState &fluidState, + const ParameterCache ¶mCache, const int phaseIdx) + { + return FluidSystem::enthalpy(fluidState, paramCache, phaseIdx); + } + +protected: + const Impl &asImp_() const + { + return *static_cast(this); + } + Impl &asImp_() + { + return *static_cast(this); + } + +private: + /*! + * It has to be decided if the full solid system / solid state interface is + * used (general option, but more complicated), or the simple nonisothermal + * spatial params interface (simpler but less general). In the simple + * nonisothermal spatial params interface the functions solidHeatCapacity, + * solidDensity, and solidThermalConductivity in the spatial params overwrite + * the parameters given in the solid system. This only makes sense in + * combination with the simplest solid system InertSolidPhase, and can be used + * to quickly change parameters in certain domain regions. For setups with + * more general solids with several components these functions should not + * exist. Instead, the solid system determines the values for + * solidHeatCapacity, solidDensity, and solidThermalConductivity depending on + * the given composition. + */ + + /*! + * \name Access functions for the solidsystem / solidstate interface + */ + // \{ + + /*! + * \brief Gets the solid heat capacity in an scv. + * + * \param elemSol the element solution vector + * \param problem the problem to solve + * \param element the element (codim-0-entity) the scv belongs to + * \param scv the sub control volume + * \param solidState the solid state + * \note this gets selected if the user uses the solidsystem / solidstate + * interface + */ + template (), + int> = 0> + Scalar solidHeatCapacity_(const ElemSol &elemSol, const Problem &problem, + const Element &element, const Scv &scv, + const SolidState &solidState) + { + return SolidSystem::heatCapacity(solidState); + } + + /*! + * \brief Gets the solid density in an scv. + * + * \param elemSol the element solution vector + * \param problem the problem to solve + * \param element the element (codim-0-entity) the scv belongs to + * \param scv the sub control volume + * \param solidState the solid state + * \note this gets selected if the user uses the solidsystem / solidstate + * interface + */ + template (), + int> = 0> + Scalar solidDensity_(const ElemSol &elemSol, const Problem &problem, + const Element &element, const Scv &scv, + const SolidState &solidState) + { + return SolidSystem::density(solidState); + } + + // \} + + /*! + * \name Access functions for the simple nonisothermal spatial params + * interface in combination with an InertSolidPhase as solid system + */ + // \{ + + /*! + * \brief Gets the solid heat capacity in an scv. + * + * \param elemSol the element solution vector + * \param problem the problem to solve + * \param element the element (codim-0-entity) the scv belongs to + * \param scv the sub control volume + * \param solidState the solid state + * \note this gets selected if the user uses the simple spatial params + * interface in combination with an InertSolidPhase as solid system + */ + template (), + int> = 0> + Scalar solidHeatCapacity_(const ElemSol &elemSol, const Problem &problem, + const Element &element, const Scv &scv, + const SolidState &solidState) + { + static_assert(Detail::isInertSolidPhase::value, + "solidHeatCapacity can only be overwritten in the spatial " + "params when the solid system is a simple InertSolidPhase\n" + "If you select a proper solid system, the solid heat " + "capacity will be computed as stated in the solid system!"); + std::cout << "sHC called in myenergyvolumevariables" << std::endl; // DEBUG + return problem.spatialParams().solidHeatCapacity(element, scv, elemSol, + solidState); + } + + /*! + * \brief Gets the solid density in an scv. + * + * \param elemSol the element solution vector + * \param problem the problem to solve + * \param element the element (codim-0-entity) the scv belongs to + * \param scv the sub control volume + * \param solidState the solid state + * \note this gets selected if the user uses the simple spatial params + * interface in combination with an InertSolidPhase as solid system + */ + template (), + int> = 0> + Scalar solidDensity_(const ElemSol &elemSol, const Problem &problem, + const Element &element, const Scv &scv, + const SolidState &solidState) + { + static_assert(Detail::isInertSolidPhase::value, + "solidDensity can only be overwritten in the spatial params " + "when the solid system is a simple InertSolidPhase\n" + "If you select a proper solid system, the solid density will " + "be computed as stated in the solid system!"); + return problem.spatialParams().solidDensity(element, scv, elemSol, + solidState); + } + + /*! + * \brief Gets the solid's thermal conductivity in an scv. + * + * \param elemSol the element solution vector + * \param problem the problem to solve + * \param element the element (codim-0-entity) the scv belongs to + * \param scv the sub control volume + * \param solidState the solid state + * \note this gets selected if the user uses the solidsystem / solidstate + * interface + */ + template (), + int> = 0> + DimWorldMatrix + solidThermalConductivity_(const ElemSol &elemSol, const Problem &problem, + const Element &element, const Scv &scv, + const SolidState &solidState) + { + static_assert( + Detail::isInertSolidPhase::value, + "solidThermalConductivity can only be overwritten in the spatial " + "params when the solid system is a simple InertSolidPhase\n" + "If you select a proper solid system, the solid thermal conductivity " + "will be computed as stated in the solid system!"); + return problem.spatialParams().solidThermalConductivity(element, scv); + } + + DimWorldMatrix lambdaEff_; +}; + +} // end namespace Dumux + +#endif diff --git a/two-scale-heat-conduction/macro-dumux/appl/mysimpleliquid.hh b/two-scale-heat-conduction/macro-dumux/appl/mysimpleliquid.hh new file mode 100644 index 000000000..920e35191 --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/appl/mysimpleliquid.hh @@ -0,0 +1,93 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ + +#ifndef DUMUX_SIMPLE_H2O_HH +#define DUMUX_SIMPLE_H2O_HH + +#include +#include +#include +#include + +namespace Dumux::Components { + +template +class MySimpleLiquid + : public Components::Base>, + public Components::Liquid>, + public Components::Gas> { + +public: + static std::string name() + { + return "MySimpleLiquid"; + } + + static const Scalar liquidEnthalpy(Scalar temperature, Scalar pressure) + { + static const Scalar tRef = + getParam("Component.LiquidReferenceTemperature"); + return liquidHeatCapacity(temperature, pressure) * (temperature - tRef) + + pressure / liquidDensity(temperature, pressure); + } + static constexpr bool liquidIsCompressible() + { + return false; + } + + static constexpr bool liquidViscosityIsConstant() + { + return true; + } + + static Scalar liquidDensity(Scalar temperature, Scalar pressure) + { + return getParam("Component.LiquidDensity"); + } + + static Scalar liquidPressure(Scalar temperature, Scalar density) + { + DUNE_THROW(Dune::InvalidStateException, + "The liquid pressure is undefined for incompressible fluids"); + } + + static Scalar liquidViscosity(Scalar temperature, Scalar pressure) + { + return getParam("Component.LiquidViscosity"); + } + + static Scalar liquidHeatCapacity(Scalar temperature, Scalar pressure) + { + return getParam("Component.LiquidHeatCapacity"); + } + + static Scalar + liquidThermalConductivity(Scalar temperature, + Scalar pressure) + { // never called, our conductivity + // tensor is used instead + return getParam("Component.LiquidThermalConductivity"); + } +}; + +template +struct IsAqueous> : public std::true_type { +}; + +} // end namespace Dumux::Components + +#endif diff --git a/two-scale-heat-conduction/macro-dumux/appl/myvolumevariables.hh b/two-scale-heat-conduction/macro-dumux/appl/myvolumevariables.hh new file mode 100644 index 000000000..18d5dace7 --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/appl/myvolumevariables.hh @@ -0,0 +1,246 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ +/*! + * \file + * \ingroup My OnePModel + * \brief Quantities required by the one-phase fully implicit model defined on a + * vertex. Copy of OnePModel, inherits from MyEnergyVolumeVariables + */ + +#ifndef DUMUX_MY_1P_VOLUME_VARIABLES_HH +#define DUMUX_MY_1P_VOLUME_VARIABLES_HH + +#include +#include +#include +#include +#include "myenergyvolumevariables.hh" + +namespace Dumux { + +/*! + * \ingroup OnePModel + * \brief Contains the quantities which are constant within a + * finite volume in the one-phase model. + * + * \tparam Traits Class encapsulating types to be used by the vol vars + */ +template +class MyOnePVolumeVariables + : public PorousMediumFlowVolumeVariables, + public MyEnergyVolumeVariables> { + using ThisType = MyOnePVolumeVariables; + using ParentType = PorousMediumFlowVolumeVariables; + using EnergyVolVars = + MyEnergyVolumeVariables>; + + using Scalar = typename Traits::PrimaryVariables::value_type; + using PermeabilityType = typename Traits::PermeabilityType; + static constexpr int numFluidComps = ParentType::numFluidComponents(); + static constexpr int dimWorld = 2; // hardcoded for now + using DimWorldMatrix = Dune::FieldMatrix; + +public: + //! Export the underlying fluid system + using FluidSystem = typename Traits::FluidSystem; + //! Export the fluid state type + using FluidState = typename Traits::FluidState; + //! Export the indices + using Indices = typename Traits::ModelTraits::Indices; + //! Export type of solid state + using SolidState = typename Traits::SolidState; + //! Export type of solid system + using SolidSystem = typename Traits::SolidSystem; + + /*! + * \brief Updates all quantities for a given control volume. + * + * \param elemSol A vector containing all primary variables connected to the + * element \param problem The object specifying the problem which ought to be + * simulated \param element An element which contains part of the control + * volume \param scv The sub-control volume + */ + template + void update(const ElemSol &elemSol, const Problem &problem, + const Element &element, const Scv &scv) + { + ParentType::update(elemSol, problem, element, scv); + + // porosity + completeFluidState(elemSol, problem, element, scv, fluidState_, + solidState_); + + // porosity and permeability + updateSolidVolumeFractions(elemSol, problem, element, scv, solidState_, + numFluidComps); + EnergyVolVars::updateSolidEnergyParams(elemSol, problem, element, scv, + solidState_); + permeability_ = problem.spatialParams().permeability(element, scv, elemSol); + EnergyVolVars::updateEffectiveThermalConductivity(elemSol, problem, element, + scv, solidState_); + } + + /*! + * \brief Sets complete fluid state + * + * \param elemSol A vector containing all primary variables connected to the + * element \param problem The object specifying the problem which ought to be + * simulated \param element An element which contains part of the control + * volume \param scv The sub-control volume \param fluidState A container with + * the current (physical) state of the fluid \param solidState A container + * with the current (physical) state of the solid + */ + template + void completeFluidState(const ElemSol &elemSol, const Problem &problem, + const Element &element, const Scv &scv, + FluidState &fluidState, SolidState &solidState) + { + EnergyVolVars::updateTemperature(elemSol, problem, element, scv, fluidState, + solidState); + fluidState.setSaturation(/*phaseIdx=*/0, 1.); + + const auto &priVars = elemSol[scv.localDofIndex()]; + fluidState.setPressure(/*phaseIdx=*/0, priVars[Indices::pressureIdx]); + + // saturation in a single phase is always 1 and thus redundant + // to set. But since we use the fluid state shared by the + // immiscible multi-phase models, so we have to set it here... + fluidState.setSaturation(/*phaseIdx=*/0, 1.0); + + typename FluidSystem::ParameterCache paramCache; + paramCache.updatePhase(fluidState, /*phaseIdx=*/0); + + Scalar value = FluidSystem::density(fluidState, paramCache, /*phaseIdx=*/0); + fluidState.setDensity(/*phaseIdx=*/0, value); + + value = FluidSystem::viscosity(fluidState, paramCache, /*phaseIdx=*/0); + fluidState.setViscosity(/*phaseIdx=*/0, value); + + // compute and set the enthalpy + value = EnergyVolVars::enthalpy(fluidState, paramCache, /*phaseIdx=*/0); + fluidState.setEnthalpy(/*phaseIdx=*/0, value); + } + + /*! + * \brief Returns the temperature \f$\mathrm{[K]}\f$ inside the sub-control + * volume. + * + * Note that we assume thermodynamic equilibrium, i.e. the + * temperatures of the rock matrix and of all fluid phases are + * identical. + */ + Scalar temperature() const + { + return fluidState_.temperature(); + } + + /*! + * \brief Returns the phase state for the control volume. + */ + const SolidState &solidState() const + { + return solidState_; + } + + /*! + * \brief Returns the effective pressure \f$\mathrm{[Pa]}\f$ of a given phase + * within the control volume. + */ + Scalar pressure(int phaseIdx = 0) const + { + return fluidState_.pressure(phaseIdx); + } + + /*! + * \brief Returns the saturation. + */ + Scalar saturation(int phaseIdx = 0) const + { + return 1.0; + } + + /*! + * \brief Returns the mass density \f$\mathrm{[kg/m^3]}\f$ of a given phase + * within the control volume. + */ + Scalar density(int phaseIdx = 0) const + { + return fluidState_.density(phaseIdx); + } + + /*! + * \brief Returns the dynamic viscosity \f$\mathrm{[Pa s]}\f$ of the fluid + * within the control volume. + */ + Scalar viscosity(int phaseIdx = 0) const + { + return fluidState_.viscosity(phaseIdx); + } + + /*! + * \brief Returns the mobility \f$\mathrm{[1/(Pa s)]}\f$. + * + * This function enables the use of ImplicitDarcyFluxVariables + * with the 1p fully implicit model, ALTHOUGH the term mobility is + * usually not employed in the one phase context. + * + * \param phaseIdx The phase index + */ + Scalar mobility(int phaseIdx = 0) const + { + return 1.0 / fluidState_.viscosity(phaseIdx); + } + + /*! + * \brief Returns the average porosity \f$\mathrm{[-]}\f$ within the control + * volume. + */ + Scalar porosity() const + { + return solidState_.porosity(); + } + + /*! + * \brief Returns the permeability within the control volume in \f$[m^2]\f$. + */ + const PermeabilityType &permeability() const + { + return permeability_; + } + + /*! + * \brief Returns the fluid state of the control volume. + */ + const FluidState &fluidState() const + { + return fluidState_; + } + + DimWorldMatrix effectiveThermalConductivity() const + { + return EnergyVolVars::effectiveThermalConductivity(); + } + +protected: + FluidState fluidState_; + SolidState solidState_; + PermeabilityType permeability_; +}; + +} // namespace Dumux + +#endif diff --git a/two-scale-heat-conduction/macro-dumux/appl/problem.hh b/two-scale-heat-conduction/macro-dumux/appl/problem.hh new file mode 100644 index 000000000..0ce1dbf5f --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/appl/problem.hh @@ -0,0 +1,274 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ + +/* + * \brief OnePModel in combination with the NI model for a conduction problem. + * The simulation domain is a tube with an elevated temperature on the left hand + * side. + */ + +#ifndef DUMUX_1PNI_CONDUCTION_PROBLEM_HH +#define DUMUX_1PNI_CONDUCTION_PROBLEM_HH + +#include + +#include +#include +#include +#include + +#include + +namespace Dumux { + +template +class OnePNIConductionProblem : public PorousMediumFlowProblem { + using ParentType = PorousMediumFlowProblem; + using GridView = + typename GetPropType::GridView; + using Scalar = GetPropType; + using PrimaryVariables = GetPropType; + using FluidSystem = GetPropType; + using BoundaryTypes = Dumux::BoundaryTypes< + GetPropType::numEq()>; + using VolumeVariables = GetPropType; + using SolutionVector = GetPropType; + using Element = typename GridView::template Codim<0>::Entity; + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + using GridGeometry = GetPropType; + + enum { dimWorld = GridView::dimensionworld }; + using DimWorldMatrix = Dune::FieldMatrix; + + // copy indices of primary variables for convenience + using Indices = + typename GetPropType::Indices; + enum { + pressureIdx = Indices::pressureIdx, + temperatureIdx = Indices::temperatureIdx + }; + +public: + OnePNIConductionProblem(std::shared_ptr gridGeometry) + : ParentType(gridGeometry), + couplingParticipant_(Dumux::Precice::CouplingAdapter::getInstance()) + { + // initialize fluid system + FluidSystem::init(); + + name_ = getParam("Problem.Name"); + + porosity_.resize(gridGeometry->numDofs()); + k00_.resize(gridGeometry->numDofs()); + k01_.resize(gridGeometry->numDofs()); + k10_.resize(gridGeometry->numDofs()); + k11_.resize(gridGeometry->numDofs()); + } + + /*! + * \brief Return the temperature index. + */ + int returnTemperatureIdx() + { + return temperatureIdx; + } + + /*! + * \brief Return the problem name. + * This is used as a prefix for files generated by the simulation. + */ + const std::string &name() const + { + return name_; + } + + /*! + * \brief Specifies which kind of boundary condition should be + * used for which equation on a given boundary segment. + * + * \param globalPos The position for which the bc type should be evaluated + */ + BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const + { + BoundaryTypes bcTypes; + + // meshwidth calculation (assumes regular rectangular grid) + auto cells = getParam>("Grid.Cells"); + double meshWidthX = (this->gridGeometry().bBoxMax()[0] - + this->gridGeometry().bBoxMin()[0]) / + cells[0]; + double meshWidthY = (this->gridGeometry().bBoxMax()[1] - + this->gridGeometry().bBoxMin()[1]) / + cells[1]; + + if (globalPos[1] < this->gridGeometry().bBoxMin()[1] + eps_ && + getParam("BoundaryConditions.BcTypeBottom") == "dirichlet") + bcTypes.setAllDirichlet(); + else if (globalPos[1] > this->gridGeometry().bBoxMax()[1] - eps_ && + getParam("BoundaryConditions.BcTypeTop") == + "dirichlet") + bcTypes.setAllDirichlet(); + else if (globalPos[0] < this->gridGeometry().bBoxMin()[0] + eps_ && + getParam("BoundaryConditions.BcTypeLeft") == + "dirichlet") + bcTypes.setAllDirichlet(); + else if (globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_ && + getParam("BoundaryConditions.BcTypeRight") == + "dirichlet") + bcTypes.setAllDirichlet(); + // heat source bottom left corner + else if ((globalPos[1] < this->gridGeometry().bBoxMin()[1] + eps_ && + globalPos[0] < + this->gridGeometry().bBoxMin()[0] + meshWidthX + eps_) && + getParam("BoundaryConditions.UseHeatSourceBottomLeft")) + bcTypes.setAllDirichlet(); + else if ((globalPos[0] < this->gridGeometry().bBoxMin()[0] + eps_ && + globalPos[1] < + this->gridGeometry().bBoxMin()[1] + meshWidthY + eps_) && + getParam("BoundaryConditions.UseHeatSourceBottomLeft")) + bcTypes.setAllDirichlet(); + else + bcTypes.setAllNeumann(); // default is adiabatic + return bcTypes; + } + + /*! + * \brief Evaluates the boundary conditions for a Dirichlet boundary segment. + * This function is only called in dirichlet boundary cells. + * \param globalPos The position for which the bc type should be evaluated + */ + PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const + { + PrimaryVariables priVars(initial_()); + + // meshwidth calculation (assumes regular rectangular grids) + auto cells = getParam>("Grid.Cells"); + double meshWidthX = (this->gridGeometry().bBoxMax()[0] - + this->gridGeometry().bBoxMin()[0]) / + cells[0]; + double meshWidthY = (this->gridGeometry().bBoxMax()[1] - + this->gridGeometry().bBoxMin()[1]) / + cells[1]; + + if (globalPos[0] < this->gridGeometry().bBoxMin()[0] + eps_) + priVars[temperatureIdx] = getParam("BoundaryConditions.BcLeft"); + else if (globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_) + priVars[temperatureIdx] = getParam("BoundaryConditions.BcRight"); + + if (globalPos[1] < this->gridGeometry().bBoxMin()[1] + eps_) + priVars[temperatureIdx] = getParam("BoundaryConditions.BcBottom"); + else if (globalPos[1] > this->gridGeometry().bBoxMax()[1] - eps_) + priVars[temperatureIdx] = getParam("BoundaryConditions.BcTop"); + + // heat source bottom left corner + if (getParam("BoundaryConditions.UseHeatSourceBottomLeft")) { + if ((globalPos[1] < this->gridGeometry().bBoxMin()[1] + eps_ && + globalPos[0] < + this->gridGeometry().bBoxMin()[0] + meshWidthX + eps_) || + (globalPos[0] < this->gridGeometry().bBoxMin()[0] + eps_ && + globalPos[1] < + this->gridGeometry().bBoxMin()[1] + meshWidthY + eps_)) + priVars[temperatureIdx] = + getParam("BoundaryConditions.HeatSourceBottomLeft"); + } + return priVars; + } + + /*! + * \brief Evaluates the initial value for a control volume. + * + * \param globalPos The position for which the initial condition should be + * evaluated + */ + PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const + { + return initial_(); + } + + // to make available to vtkOutput + const std::vector &getPorosity() + { + return porosity_; + } + const std::vector &getK00() + { + return k00_; + } + const std::vector &getK01() + { + return k01_; + } + const std::vector &getK10() + { + return k10_; + } + const std::vector &getK11() + { + return k11_; + } + + /*! + * \brief Function to update the conductivities, porosities of additional vtk + * output + * + * \param globalPos The position for which the initial condition should be + * evaluated + */ + template + void updateVtkOutput(const SolutionVector &curSol) + { + for (const auto &element : elements(this->gridGeometry().gridView())) { + const auto elemSol = + elementSolution(element, curSol, this->gridGeometry()); + auto fvGeometry = localView(this->gridGeometry()); + fvGeometry.bindElement(element); + for (const auto &scv : scvs(fvGeometry)) { + VolumeVariables volVars; + volVars.update(elemSol, *this, element, scv); + const auto elementIdx = scv.elementIndex(); + porosity_[elementIdx] = volVars.porosity(); + k00_[elementIdx] = volVars.effectiveThermalConductivity()[0][0]; + k01_[elementIdx] = volVars.effectiveThermalConductivity()[0][1]; + k10_[elementIdx] = volVars.effectiveThermalConductivity()[1][0]; + k11_[elementIdx] = volVars.effectiveThermalConductivity()[1][1]; + } + } + } + +private: + Dumux::Precice::CouplingAdapter &couplingParticipant_; + + // the internal method for the initial condition + PrimaryVariables initial_() const + { + PrimaryVariables priVars(0.0); + priVars[pressureIdx] = getParam("InitialConditions.Pressure"); + priVars[temperatureIdx] = getParam("InitialConditions.Temperature"); + return priVars; + } + static constexpr Scalar eps_ = 1e-6; + std::string name_; + std::vector porosity_; + std::vector k00_; + std::vector k01_; + std::vector k10_; + std::vector k11_; +}; + +} // namespace Dumux + +#endif diff --git a/two-scale-heat-conduction/macro-dumux/appl/properties.hh b/two-scale-heat-conduction/macro-dumux/appl/properties.hh new file mode 100644 index 000000000..0d20ffd7f --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/appl/properties.hh @@ -0,0 +1,93 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ + +#ifndef DUMUX_1PNI_CONDUCTION_PROBLEM_PROPERTIES_HH +#define DUMUX_1PNI_CONDUCTION_PROBLEM_PROPERTIES_HH + +#include +#include +#include +#include +#include +#include +#include + +#include "mysimpleliquid.hh" +#include "myvolumevariables.hh" +#include "problem.hh" +#include "spatialparams.hh" + +namespace Dumux::Properties { +// Create new type tags +namespace TTag { +struct OnePNIConduction { + using InheritsFrom = std::tuple; +}; +struct OnePNIConductionCCTpfa { + using InheritsFrom = std::tuple; +}; +} // end namespace TTag + +// Set the grid type +template +struct Grid { + using type = Dune::YaspGrid<2>; +}; // structured parallel 2D grid +// Set the problem property +template +struct Problem { + using type = OnePNIConductionProblem; +}; + +// Set the fluid system +template +struct FluidSystem { + using type = FluidSystems::OnePLiquid< + GetPropType, + Components::MySimpleLiquid>>; +}; + +//! Set the volume variables property +template +struct VolumeVariables { +private: + using PV = GetPropType; + using FSY = GetPropType; + using FST = GetPropType; + using SSY = GetPropType; + using SST = GetPropType; + using PT = typename GetPropType::PermeabilityType; + using MT = GetPropType; + + using Traits = OnePVolumeVariablesTraits; + +public: + using type = MyOnePVolumeVariables; +}; + +// Set the spatial parameters +template +struct SpatialParams { + using GridGeometry = GetPropType; + using Scalar = GetPropType; + using type = OnePNISpatialParams; +}; + +} // namespace Dumux::Properties +// end namespace Dumux +#endif diff --git a/two-scale-heat-conduction/macro-dumux/appl/spatialparams.hh b/two-scale-heat-conduction/macro-dumux/appl/spatialparams.hh new file mode 100644 index 000000000..f427d9939 --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/appl/spatialparams.hh @@ -0,0 +1,113 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ + +#ifndef DUMUX_TEST_1PNI_SPATIAL_PARAMS_HH +#define DUMUX_TEST_1PNI_SPATIAL_PARAMS_HH + +#include +#include + +#include + +namespace Dumux { + +/*! + * \brief Definition of the spatial parameters for the 1pni problems. + */ +template +class OnePNISpatialParams + : public FVPorousMediumFlowSpatialParamsOneP< + GridGeometry, Scalar, OnePNISpatialParams> { + using GridView = typename GridGeometry::GridView; + using ThisType = OnePNISpatialParams; + using ParentType = + FVPorousMediumFlowSpatialParamsOneP; + static const int dimWorld = GridView::dimensionworld; + using DimWorldMatrix = Dune::FieldMatrix; + using Element = typename GridView::template Codim<0>::Entity; + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + using FVElementGeometry = typename GridGeometry::LocalView; + using SubControlVolume = typename FVElementGeometry::SubControlVolume; + +public: + // export permeability type + using PermeabilityType = Scalar; + + OnePNISpatialParams(std::shared_ptr gridGeometry) + : ParentType(gridGeometry), + couplingParticipant_(Dumux::Precice::CouplingAdapter::getInstance()) {} + + /*! + * \brief Defines the intrinsic permeability \f$\mathrm{[m^2]}\f$. + * + * \param globalPos The global position + */ + PermeabilityType permeabilityAtPos(const GlobalPosition &globalPos) const + { + return getParam("Problem.Permeability"); + } + + /*! + * \brief Defines the porosity \f$\mathrm{[-]}\f$. + * + * \param globalPos The global position + */ + template + Scalar porosity(const Element &element, const SubControlVolume &scv, + const ElementSolution &elemSol) const + { + if (getParam("Precice.RunWithCoupling") == true) + return couplingParticipant_.getScalarQuantityOnFace( + "macro-mesh", "porosity", scv.elementIndex()); + else + return getParam("Problem.DefaultPorosity"); + } + + /*! + * \brief Defines the conductivity tensor \f$ K \f$. + */ + + DimWorldMatrix solidThermalConductivity(const Element &element, + const SubControlVolume &scv) const + { + DimWorldMatrix K; + + if (getParam("Precice.RunWithCoupling") == true) { + K[0][0] = couplingParticipant_.getScalarQuantityOnFace( + "macro-mesh", "k_00", scv.elementIndex()); + K[0][1] = couplingParticipant_.getScalarQuantityOnFace( + "macro-mesh", "k_01", scv.elementIndex()); + K[1][0] = couplingParticipant_.getScalarQuantityOnFace( + "macro-mesh", "k_10", scv.elementIndex()); + K[1][1] = couplingParticipant_.getScalarQuantityOnFace( + "macro-mesh", "k_11", scv.elementIndex()); + } else { + K[0][0] = getParam("Component.SolidThermalConductivity"); + K[0][1] = 0.0; + K[1][0] = 0.0; + K[1][1] = getParam("Component.SolidThermalConductivity"); + } + return K; + } + +private: + Dumux::Precice::CouplingAdapter &couplingParticipant_; +}; + +} // end namespace Dumux + +#endif diff --git a/two-scale-heat-conduction/macro-dumux/clean.sh b/two-scale-heat-conduction/macro-dumux/clean.sh new file mode 100755 index 000000000..db81de5db --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_dumux . diff --git a/two-scale-heat-conduction/macro-dumux/cmake/modules/CMakeLists.txt b/two-scale-heat-conduction/macro-dumux/cmake/modules/CMakeLists.txt new file mode 100644 index 000000000..bcf8dff3d --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/cmake/modules/CMakeLists.txt @@ -0,0 +1,3 @@ +set(modules "DumuxTuringMacros.cmake") + +install(FILES ${modules} DESTINATION ${DUNE_INSTALL_MODULEDIR}) diff --git a/two-scale-heat-conduction/macro-dumux/cmake/modules/MacroDumuxMacros.cmake b/two-scale-heat-conduction/macro-dumux/cmake/modules/MacroDumuxMacros.cmake new file mode 100644 index 000000000..613dfb664 --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/cmake/modules/MacroDumuxMacros.cmake @@ -0,0 +1 @@ +# File for module specific CMake tests. diff --git a/two-scale-heat-conduction/macro-dumux/config.h.cmake b/two-scale-heat-conduction/macro-dumux/config.h.cmake new file mode 100644 index 000000000..24a68b4d6 --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/config.h.cmake @@ -0,0 +1,45 @@ +/* begin macro-dumux + put the definitions for config.h specific to + your project here. Everything above will be + overwritten +*/ + +/* begin private */ +/* Name of package */ +#define PACKAGE "@DUNE_MOD_NAME@" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "@DUNE_MAINTAINER@" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "@DUNE_MOD_NAME@" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "@DUNE_MOD_NAME@ @DUNE_MOD_VERSION@" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "@DUNE_MOD_NAME@" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "@DUNE_MOD_URL@" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "@DUNE_MOD_VERSION@" + +/* end private */ + +/* Define to the version of macro-dumux */ +#define MACRO_DUMUX_VERSION "@MACRO_DUMUX_VERSION@" + +/* Define to the major version of macro-dumux */ +#define MACRO_DUMUX_VERSION_MAJOR @MACRO_DUMUX_VERSION_MAJOR@ + +/* Define to the minor version of macro-dumux */ +#define MACRO_DUMUX_VERSION_MINOR @MACRO_DUMUX_VERSION_MINOR@ + +/* Define to the revision of macro-dumux */ +#define MACRO_DUMUX_VERSION_REVISION @MACRO_DUMUX_VERSION_REVISION@ + +/* end macro-dumux + Everything below here will be overwritten +*/ diff --git a/two-scale-heat-conduction/macro-dumux/doc/CMakeLists.txt b/two-scale-heat-conduction/macro-dumux/doc/CMakeLists.txt new file mode 100644 index 000000000..be52cfccb --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/doc/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory("doxygen") diff --git a/two-scale-heat-conduction/macro-dumux/doc/doxygen/CMakeLists.txt b/two-scale-heat-conduction/macro-dumux/doc/doxygen/CMakeLists.txt new file mode 100644 index 000000000..f7b8ea5c9 --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/doc/doxygen/CMakeLists.txt @@ -0,0 +1,2 @@ +# shortcut for creating the Doxyfile.in and Doxyfile +add_doxygen_target() diff --git a/two-scale-heat-conduction/macro-dumux/doc/doxygen/Doxylocal b/two-scale-heat-conduction/macro-dumux/doc/doxygen/Doxylocal new file mode 100644 index 000000000..cee56557d --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/doc/doxygen/Doxylocal @@ -0,0 +1,30 @@ +# This file contains local changes to the doxygen configuration +# please use '+=' to add files/directories to the lists + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT += @top_srcdir@/dune/ +# see e.g. dune-grid for the examples of mainpage and modules +# INPUT += @srcdir@/mainpage \ +# @srcdir@/modules + +# The EXCLUDE tag can be used to specify files and/or directories that should +# be excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +# EXCLUDE += @top_srcdir@/dune/macro-dumux/test + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +# EXAMPLE_PATH += @top_srcdir@/src + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +# IMAGE_PATH += @top_srcdir@/dune/macro-dumux/pics diff --git a/two-scale-heat-conduction/macro-dumux/dune.module b/two-scale-heat-conduction/macro-dumux/dune.module new file mode 100644 index 000000000..6f92c69e4 --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/dune.module @@ -0,0 +1,12 @@ +################################ +# Dune module information file # +################################ + +# Name of the module +Module: macro-dumux +Version: 1.0 +Maintainer: mathis.kelm@iws.uni-stuttgart.de +# Required build dependencies +Depends: dumux-precice +# Optional build dependencies +#Suggests: diff --git a/two-scale-heat-conduction/macro-dumux/macro-dumux.pc.in b/two-scale-heat-conduction/macro-dumux/macro-dumux.pc.in new file mode 100644 index 000000000..31dfbf1ad --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/macro-dumux.pc.in @@ -0,0 +1,15 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +CXX=@CXX@ +CC=@CC@ +DEPENDENCIES=@REQUIRES@ + +Name: @PACKAGE_NAME@ +Version: @VERSION@ +Description: macro-dumux module +URL: http://dune-project.org/ +Requires: dumux-phasefield dumux-precice +Libs: -L${libdir} +Cflags: -I${includedir} diff --git a/two-scale-heat-conduction/macro-dumux/params.input b/two-scale-heat-conduction/macro-dumux/params.input new file mode 100644 index 000000000..660557e1c --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/params.input @@ -0,0 +1,45 @@ +[Component] +SolidDensity = 1.0 +SolidThermalConductivity = 1.0 +SolidHeatCapacity = 1.0 +LiquidDensity = 1.0 +LiquidThermalConductiviy = 1.0 #not used, conductivity tensor K communicated +LiquidHeatCapacity = 1.0 +LiquidReferenceTemperature = 0.5 +LiquidViscosity = 1.0 + +[Grid] +LowerLeft = 0.0 0.0 #not used! +UpperRight = 1 0.5 +Cells = 8 4 + +[TimeLoop] +TEnd = 0.25 +OutputInterval = 1 # output after every n timesteps +MaxDt = 0.01 +InitialDt = 0.01 + +[Problem] +Name = macro-heat +EnableGravity = false +Permeability = 1.0 +DefaultPorosity = 0.5 + +[BoundaryConditions] +BcTypeLeft = neumann +BcTypeRight = neumann +BcTypeTop = neumann +BcTypeBottom = neumann +BcLeft = 0.0 +BcRight = 0.0 +BcTop = 0.0 +BcBottom = 0.0 +UseHeatSourceBottomLeft = true +HeatSourceBottomLeft = 0.0 + +[InitialConditions] +Temperature = 0.5 +Pressure = 0.0 + +[Precice] +RunWithCoupling = true diff --git a/two-scale-heat-conduction/macro-dumux/run.sh b/two-scale-heat-conduction/macro-dumux/run.sh new file mode 100755 index 000000000..920352b8d --- /dev/null +++ b/two-scale-heat-conduction/macro-dumux/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +./macro_dumux params.input + +close_log diff --git a/two-scale-heat-conduction/macro-nutils/clean.sh b/two-scale-heat-conduction/macro-nutils/clean.sh new file mode 100755 index 000000000..6893c1ea5 --- /dev/null +++ b/two-scale-heat-conduction/macro-nutils/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_nutils . diff --git a/two-scale-heat-conduction/macro-nutils/macro.py b/two-scale-heat-conduction/macro-nutils/macro.py new file mode 100644 index 000000000..a0ebc9d09 --- /dev/null +++ b/two-scale-heat-conduction/macro-nutils/macro.py @@ -0,0 +1,165 @@ +#! /usr/bin/env python3 +# +# Heat conduction problem with two materials. + +from nutils import mesh, function, solver, export, cli +import treelog +import numpy as np +import precice + + +def main(): + """ + 2D heat conduction problem solved on a rectangular domain. + The material consists of a mixture of two materials "g" and "s". + """ + is_coupled_case = True # If False, single-physics problem is solved + + topo, geom = mesh.rectilinear([np.linspace(0, 1.0, 5), np.linspace(0, 0.5, 4)]) + + ns = function.Namespace(fallback_length=2) + ns.x = geom + ns.basis = topo.basis('std', degree=1) + ns.u = 'basis_n ?solu_n' # the field to be solved for + + ns.phi = 'basis_n ?solphi_n' # porosity, to be read from preCICE + phi = 0.5 # initial value of porosity + + ns.kbasis = topo.basis('std', degree=1).vector(topo.ndims).vector(topo.ndims) + # conductivity matrix, to be read from preCICE (read as two vectors and then patched to form a matrix) + ns.k_ij = 'kbasis_nij ?solk_n' + k = 1.0 # initial value of conductivity + + ns.rhos = 1.0 # density of material s + ns.rhog = 1.0 # density of material g + ns.dudt = 'basis_n (?solu_n - ?solu0_n) / ?dt' # implicit Euler time stepping formulation + + # Dirichlet boundary condition at lower left corner + ns.usource = 0.0 + + # Initial condition in the domain + ns.uinitial = 0.5 + + if is_coupled_case: + participant = precice.Participant("macro-heat", "../precice-config.xml", 0, 1) + mesh_name = "macro-mesh" + + # Define Gauss points on entire domain as coupling mesh (volume coupling from macro side) + couplingsample = topo.sample('gauss', degree=2) # mesh vertices are Gauss points + vertex_ids = participant.set_mesh_vertices(mesh_name, couplingsample.eval(ns.x)) + else: + sqrphi = topo.integral((ns.phi - phi) ** 2, degree=1) + solphi = solver.optimize('solphi', sqrphi, droptol=1E-12) + + sqrk = topo.integral(((ns.k - k * np.eye(2)) * (ns.k - k * np.eye(2))).sum([0, 1]), degree=2) + solk = solver.optimize('solk', sqrk, droptol=1E-12) + + # Define the weak form of the heat conduction problem with two materials + res = topo.integral('((rhos phi + (1 - phi) rhog) basis_n dudt + k_ij basis_n,i u_,j) d:x' @ ns, degree=2) + + # Set Dirichlet boundary conditions + sqr = topo.boundary['left'].boundary['bottom'].integral('(u - usource)^2 d:x' @ ns, degree=2) + cons = solver.optimize('solu', sqr, droptol=1e-15) + + # Set domain to initial condition + sqr = topo.integral('(u - uinitial)^2' @ ns, degree=2) + solu0 = solver.optimize('solu', sqr) + + if is_coupled_case: + if participant.requires_initial_data(): + concentrations = couplingsample.eval('u' @ ns, solu=solu0) + participant.write_data(mesh_name, "concentration", vertex_ids, concentrations) + + participant.initialize() + dt = solver_dt = participant.get_max_time_step_size() + else: + dt = 1.0E-2 + + ns.dt = dt + n = n_checkpoint = 0 + t = t_checkpoint = 0 + t_out = 0.01 + t_end = 0.25 # Only relevant when single physics case is run + n_out = int(t_out / dt) + n_t = int(t_end / dt) + + # Prepare the post processing sample + bezier = topo.sample('bezier', 2) + + # Output of initial state + x, u = bezier.eval(['x_i', 'u'] @ ns, solu=solu0) + with treelog.add(treelog.DataLog()): + export.vtk('macro-0', bezier.tri, x, u=u) + + if is_coupled_case: + is_coupling_ongoing = participant.is_coupling_ongoing() + else: + is_coupling_ongoing = True + + while is_coupling_ongoing: + if is_coupled_case: + if participant.requires_writing_checkpoint(): + solu_checkpoint = solu0 + t_checkpoint = t + n_checkpoint = n + + precice_dt = participant.get_max_time_step_size() + dt = min(precice_dt, solver_dt) + + # Read porosity and apply it to the existing solution + poro_data = participant.read_data(mesh_name, "porosity", vertex_ids, dt) + poro_coupledata = couplingsample.asfunction(poro_data) + sqrphi = couplingsample.integral((ns.phi - poro_coupledata) ** 2) + solphi = solver.optimize('solphi', sqrphi, droptol=1E-12) + + # Read conductivity and apply it to the existing solution + k_00_c = couplingsample.asfunction(participant.read_data(mesh_name, "k_00", vertex_ids, dt)) + k_01_c = couplingsample.asfunction(participant.read_data(mesh_name, "k_01", vertex_ids, dt)) + k_10_c = couplingsample.asfunction(participant.read_data(mesh_name, "k_10", vertex_ids, dt)) + k_11_c = couplingsample.asfunction(participant.read_data(mesh_name, "k_11", vertex_ids, dt)) + + conductivity = function.asarray([[k_00_c, k_01_c], [k_10_c, k_11_c]]) + sqrk = couplingsample.integral(((ns.k - conductivity) * (ns.k - conductivity)).sum([0, 1])) + solk = solver.optimize('solk', sqrk, droptol=1E-12) + + solu = solver.solve_linear('solu', res, constrain=cons, + arguments=dict(solu0=solu0, dt=dt, solphi=solphi, solk=solk)) + + if is_coupled_case: + # Collect values of field u and write them to preCICE + concentration = couplingsample.eval('u' @ ns, solu=solu) + participant.write_data(mesh_name, "concentration", vertex_ids, concentration) + + participant.advance(dt) + + n += 1 + t += dt + solu0 = solu + + if is_coupled_case: + is_coupling_ongoing = participant.is_coupling_ongoing() + + if participant.requires_reading_checkpoint(): + solu0 = solu_checkpoint + t = t_checkpoint + n = n_checkpoint + else: + if n % n_out == 0: + x, phi, k, u = bezier.eval(['x_i', 'phi', 'k', 'u'] @ ns, solphi=solphi, solk=solk, solu=solu) + with treelog.add(treelog.DataLog()): + export.vtk('macro-' + str(n), bezier.tri, x, u=u, phi=phi, K=k) + else: + if n % n_out == 0: + x, phi, k, u = bezier.eval(['x_i', 'phi', 'k', 'u'] @ ns, solphi=solphi, solk=solk, solu=solu) + with treelog.add(treelog.DataLog()): + export.vtk('macro-' + str(n), bezier.tri, x, u=u, phi=phi, K=k) + + if n >= n_t: + is_coupling_ongoing = False + + if is_coupled_case: + participant.finalize() + + +if __name__ == '__main__': + cli.run(main) diff --git a/two-scale-heat-conduction/macro-nutils/requirements.txt b/two-scale-heat-conduction/macro-nutils/requirements.txt new file mode 100644 index 000000000..cfd521c81 --- /dev/null +++ b/two-scale-heat-conduction/macro-nutils/requirements.txt @@ -0,0 +1,2 @@ +nutils==7 +pyprecice==3 diff --git a/two-scale-heat-conduction/macro-nutils/run.sh b/two-scale-heat-conduction/macro-nutils/run.sh new file mode 100755 index 000000000..5ae6ac050 --- /dev/null +++ b/two-scale-heat-conduction/macro-nutils/run.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 -m venv .venv +. .venv/bin/activate +pip install -r requirements.txt +python3 macro.py richoutput=no + +close_log diff --git a/two-scale-heat-conduction/micro-dumux/CMakeLists.txt b/two-scale-heat-conduction/micro-dumux/CMakeLists.txt new file mode 100644 index 000000000..63c5e2644 --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/CMakeLists.txt @@ -0,0 +1,28 @@ + +cmake_minimum_required(VERSION 3.13) +project(micro_sim CXX) + +if(NOT (dune-common_DIR OR dune-common_ROOT OR + "${CMAKE_PREFIX_PATH}" MATCHES ".*dune-common.*")) + string(REPLACE ${PROJECT_NAME} dune-common dune-common_DIR + ${PROJECT_BINARY_DIR}) +endif() + +#find dune-common and set the module path +find_package(dune-common REQUIRED) +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules" + ${dune-common_MODULE_PATH}) + +#include the dune macros +include(DuneMacros) + +# start a dune project with information from dune.module +dune_project() + +dune_enable_all_packages() + +add_subdirectory(appl) + +# finalize the dune project, e.g. generating config.h etc. +finalize_dune_project(GENERATE_CONFIG_H_CMAKE) + diff --git a/two-scale-heat-conduction/micro-dumux/appl/CMakeLists.txt b/two-scale-heat-conduction/micro-dumux/appl/CMakeLists.txt new file mode 100644 index 000000000..868069a59 --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/appl/CMakeLists.txt @@ -0,0 +1,17 @@ +execute_process(COMMAND pip show pybind11 + COMMAND grep Location + COMMAND cut -d " " -f2 + OUTPUT_VARIABLE SITE_PACKAGES_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE) +set(pybind11_DIR "${SITE_PACKAGES_DIR}/pybind11/share/cmake/pybind11/") + +find_package(pybind11 CONFIG REQUIRED) +pybind11_add_module(micro_sim micro_sim.cpp) + +#copy all source code to build directory to make available to pybind +add_custom_target(copy_micro_heat_all ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +# add a symlink for each input file +add_input_file_links() + diff --git a/two-scale-heat-conduction/micro-dumux/appl/cell_problem/indices.hh b/two-scale-heat-conduction/micro-dumux/appl/cell_problem/indices.hh new file mode 100644 index 000000000..063810198 --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/appl/cell_problem/indices.hh @@ -0,0 +1,37 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ + +#ifndef CELL_PROBLEM_INDICES_HH +#define CELL_PROBLEM_INDICES_HH + +namespace Dumux { + +template +struct CellProblemIndices { // Primary variable + // indices + static const int psi1Idx = 0; + static const int psi2Idx = 1; + + // number of indices + static const int numIdx = 2; +}; + +} // namespace Dumux + +#endif diff --git a/two-scale-heat-conduction/micro-dumux/appl/cell_problem/localresidual.hh b/two-scale-heat-conduction/micro-dumux/appl/cell_problem/localresidual.hh new file mode 100644 index 000000000..1b06bb27c --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/appl/cell_problem/localresidual.hh @@ -0,0 +1,211 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ + +#ifndef CELL_PROBLEM_LOCAL_RESIDUAL_HH +#define CELL_PROBLEM_LOCAL_RESIDUAL_HH + +#include +#include +#include +#include +#include + +#include "indices.hh" +#include "volumevariables.hh" + +namespace Dumux { + +template +class CellProblemLocalResidual : public CCLocalResidual { + using ParentType = CCLocalResidual; + using Scalar = GetPropType; + using Problem = GetPropType; + using NumEqVector = + Dumux::NumEqVector>; + using VolumeVariables = GetPropType; + using ElementVolumeVariables = + typename GetPropType::LocalView; + using ElementFluxVariablesCache = + typename GetPropType::LocalView; + using FVElementGeometry = + typename GetPropType::LocalView; + using SubControlVolume = typename FVElementGeometry::SubControlVolume; + using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; + using GridView = + typename GetPropType::GridView; + using Element = typename GridView::template Codim<0>::Entity; + using GridGeometry = GetPropType; + using Extrusion = Extrusion_t; + + using ModelTraits = GetPropType; + using Indices = typename ModelTraits::Indices; + + using DimWorldVector = Dune::FieldVector; + +public: + using ParentType::ParentType; + + /*! + * \brief Evaluate the rate of change of all conservation + * quantites (e.g. phase mass) within a sub-control volume. + * Cell problem is stationary, ergo storage is zero. + * + * \param problem The problem + * \param scv The sub control volume + * \param volVars The current or previous volVars + */ + NumEqVector computeStorage(const Problem &problem, + const SubControlVolume &scv, + const VolumeVariables &volVars) const + { + NumEqVector storage(0.0); + return storage; + } + + /*! + * \brief Evaluate the flux over a face of a sub control volume. + * \note Compare dumux/flux/cctpfa/darcyslaw.hh. + * This assembles the term + * \f$-|\sigma| \mathbf{n}^T \phi_0^\delta \left( \nabla psi_j + e_j + * \right)\f$, where \f$|\sigma|\f$ is the area of the face and + * \f$\mathbf{n}\f$ is the outer normal vector. + * + * \param problem The problem + * \param element The element + * \param fvGeometry The finite volume geometry context + * \param elemVolVars The volume variables for all flux stencil elements + * \param scvf The sub control volume face to compute the flux on + * \param elemFluxVarsCache The cache related to flux computation + */ + template + NumEqVector computeFlux(const Problem &problem, const Element &element, + const FVElementGeometry &fvGeometry, + const ElementVolumeVariables &elemVolVars, + const SubControlVolumeFace &scvf, + const ElementFluxVarsCache &elemFluxVarsCache) const + { + NumEqVector flux; + + for (int k = 0; k < Indices::numIdx; k++) { + //! Get the inside and outside volume variables + const auto &insideScv = fvGeometry.scv(scvf.insideScvIdx()); + const auto &outsideScv = fvGeometry.scv(scvf.outsideScvIdx()); + const auto &insideVolVars = elemVolVars[scvf.insideScvIdx()]; + const auto &outsideVolVars = elemVolVars[scvf.outsideScvIdx()]; + + //! Obtain inside and outside primary variables (psis) + const auto valInside = insideVolVars.priVar(k); + const auto valOutside = outsideVolVars.priVar(k); + + const auto &tij = calculateTransmissibility(problem, element, fvGeometry, + elemVolVars, scvf); + + //! unit vector in dimension k + NumEqVector e_k(0.0); + e_k[k] = -1.0; + + //! compute alpha := n^T*K*g + const auto alpha_inside = + vtmv(scvf.unitOuterNormal(), + insideVolVars.phi0delta(problem, insideScv), e_k) * + insideVolVars.extrusionFactor(); + + flux[k] = tij * (valInside - valOutside) + + Extrusion::area(fvGeometry, scvf) * alpha_inside; + + //! On interior faces we have to add phi0delta (K)-weighted e_k + //! contributions + if (!scvf.boundary()) { + const auto outsideK = outsideVolVars.phi0delta(problem, outsideScv); + const auto outsideTi = + fvGeometry.gridGeometry().isPeriodic() + ? computeTpfaTransmissibility( + fvGeometry, fvGeometry.flipScvf(scvf.index()), outsideScv, + outsideK, outsideVolVars.extrusionFactor()) + : -1.0 * computeTpfaTransmissibility( + fvGeometry, scvf, outsideScv, outsideK, + outsideVolVars.extrusionFactor()); + const auto alpha_outside = vtmv(scvf.unitOuterNormal(), outsideK, e_k) * + outsideVolVars.extrusionFactor(); + + flux[k] -= tij / outsideTi * (alpha_inside - alpha_outside); + } + } + return flux; + } + + //! The flux variables cache has to be bound to an element prior to flux + //! calculations During the binding, the transmissibility will be computed and + //! stored using the method below. + template + static Scalar + calculateTransmissibility(const Problem &problem, const Element &element, + const FVElementGeometry &fvGeometry, + const ElementVolumeVariables &elemVolVars, + const SubControlVolumeFace &scvf) + { + Scalar tij; + + const auto insideScvIdx = scvf.insideScvIdx(); + const auto &insideScv = fvGeometry.scv(insideScvIdx); + const auto &insideVolVars = elemVolVars[insideScvIdx]; + + const Scalar ti = + computeTpfaTransmissibility(fvGeometry, scvf, insideScv, + insideVolVars.phi0delta(problem, insideScv), + insideVolVars.extrusionFactor()); + + // on the boundary (dirichlet) we only need ti + if (scvf.boundary()) + tij = Extrusion::area(fvGeometry, scvf) * ti; + + // otherwise we compute a tpfa harmonic mean + else { + const auto outsideScvIdx = scvf.outsideScvIdx(); + // as we assemble fluxes from the neighbor to our element + // the outside index refers to the scv of our element + const auto &outsideScv = fvGeometry.scv(outsideScvIdx); + const auto &outsideVolVars = elemVolVars[outsideScvIdx]; + const Scalar tj = + fvGeometry.gridGeometry().isPeriodic() + ? computeTpfaTransmissibility( + fvGeometry, fvGeometry.flipScvf(scvf.index()), outsideScv, + outsideVolVars.phi0delta(problem, outsideScv), + outsideVolVars.extrusionFactor()) + : -1.0 * computeTpfaTransmissibility( + fvGeometry, scvf, outsideScv, + outsideVolVars.phi0delta(problem, outsideScv), + outsideVolVars.extrusionFactor()); + + // harmonic mean + if (ti * tj <= 0.0) + tij = 0.0; + else + tij = Extrusion::area(fvGeometry, scvf) * (ti * tj) / (ti + tj); + } + + return tij; + } +}; + +} // end namespace Dumux + +#endif \ No newline at end of file diff --git a/two-scale-heat-conduction/micro-dumux/appl/cell_problem/model.hh b/two-scale-heat-conduction/micro-dumux/appl/cell_problem/model.hh new file mode 100644 index 000000000..21e90609f --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/appl/cell_problem/model.hh @@ -0,0 +1,106 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ + +#ifndef CELL_PROBLEM_MODEL_HH +#define CELL_PROBLEM_MODEL_HH + +#include +#include +#include +#include + +#include "../spatialparams_cellproblem.hh" +#include "indices.hh" +#include "localresidual.hh" +#include "volumevariables.hh" + +namespace Dumux { + +struct CellProblemModelTraits { + using Indices = CellProblemIndices<>; + static constexpr int numEq() + { + return 2; + } + static constexpr int numComponents() + { + return 1; + } +}; + +template +struct CellProblemVolumeVariablesTraits { + using PrimaryVariables = PV; + using ModelTraits = MT; +}; + +namespace Properties { +namespace TTag { +struct CellModel { + using InheritsFrom = std::tuple; +}; +} // namespace TTag + +template +struct SpatialParams { +private: + using GridGeometry = GetPropType; + using Scalar = GetPropType; + +public: + using type = CellProblemSpatialParams; +}; + +template +struct LocalResidual { + using type = CellProblemLocalResidual; +}; + +template +struct ModelTraits { + using type = CellProblemModelTraits; +}; + +template +struct VolumeVariables { +private: + using PV = GetPropType; + using MT = GetPropType; + + using Traits = CellProblemVolumeVariablesTraits; + +public: + using type = CellProblemVolumeVariables; +}; + +template +struct FluxVariablesCache { + using type = FluxVariablesCaching::EmptyCache< + GetPropType>; +}; + +template +struct FluxVariablesCacheFiller { + using type = FluxVariablesCaching::EmptyCacheFiller; +}; + +} // end namespace Properties +} // end namespace Dumux + +#endif \ No newline at end of file diff --git a/two-scale-heat-conduction/micro-dumux/appl/cell_problem/volumevariables.hh b/two-scale-heat-conduction/micro-dumux/appl/cell_problem/volumevariables.hh new file mode 100644 index 000000000..3102add03 --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/appl/cell_problem/volumevariables.hh @@ -0,0 +1,41 @@ +// -*- mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ + +#ifndef CELL_PROBLEM_VOLUME_VARIABLES_HH +#define CELL_PROBLEM_VOLUME_VARIABLES_HH + +#include + +namespace Dumux { + +template +class CellProblemVolumeVariables : public PhasefieldVolumeVariables { + using Scalar = typename Traits::PrimaryVariables::value_type; + +public: + template + Scalar phi0delta(const Problem &problem, const Scv &scv) const + { + return problem.spatialParams().phi0delta(scv); + } +}; + +} // end namespace Dumux + +#endif diff --git a/two-scale-heat-conduction/micro-dumux/appl/micro_sim.cpp b/two-scale-heat-conduction/micro-dumux/appl/micro_sim.cpp new file mode 100644 index 000000000..13ef376e8 --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/appl/micro_sim.cpp @@ -0,0 +1,338 @@ +#include // numpy arrays +#include +#include // std::vector conversion + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include "properties_allencahn.hh" +#include "properties_cellproblem.hh" + +namespace py = pybind11; +namespace Dumux { +class MicroSimulation { + using AllenCahnTypeTag = Dumux::Properties::TTag::AllenCahn; + using CellProblemTypeTag = Dumux::Properties::TTag::CellProblem; + using ACSolutionVector = Dumux::GetPropType; + using CPSolutionVector = Dumux::GetPropType; + using ACProblem = Dumux::GetPropType; + using CPProblem = Dumux::GetPropType; + using ACGridVariables = Dumux::GetPropType; + using CPGridVariables = Dumux::GetPropType; + using ACAssembler = Dumux::FVAssembler; + using CPAssembler = Dumux::FVAssembler; + using LinearSolver = + Dumux::UMFPackIstlSolver>; + using CPLinearSolver = Dumux::UMFPackIstlSolver>; + using CPLinearPDESolver = Dumux::LinearPDESolver; + using ACNewtonSolver = Dumux::NewtonSolver; + using GridGeometry = Dumux::GetPropType; + using Scalar = Dumux::GetPropType; + using GridManager = Dumux::GridManager>; + using JacobianMatrix = Dumux::GetPropType; + using SolutionVector = Dumux::GetPropType; + +public: + MicroSimulation(int simulationID); + py::dict initialize(); + + // solve takes python dict for macro_write data, dt, and returns python dict for macro_read data + py::dict solve(py::dict macro_write_data, double dt); + + // void save_checkpoint(); + // void reload_checkpoint(); + + void setState(py::tuple phi); + py::tuple getState() const; + +private: + const double pi_ = 3.14159265358979323846; + double _k_00; + double _k_01; + double _k_10; + double _k_11; + double _porosity; + + ACSolutionVector _phi; // Solution of Allen Cahn Problem + ACSolutionVector _phiOld; // for checkpointing + CPSolutionVector _psi; // Solutions(s) of Cell Problem + + // shared pointers are necessary due to partitioned nature of micro simulation + std::shared_ptr _acNonLinearSolver; + std::shared_ptr _acLinearSolver; + std::shared_ptr _cpLinearSolver; + std::shared_ptr _cpLinearPDESolver; + std::shared_ptr _acAssembler; + std::shared_ptr _cpAssembler; + std::shared_ptr> _timeLoop; + std::shared_ptr _acProblem; + std::shared_ptr _cpProblem; + std::shared_ptr _cpGridVariables; + std::shared_ptr _acGridVariables; + std::shared_ptr _gridGeometry; + GridManager _gridManager; +}; + +// Constructor +MicroSimulation::MicroSimulation(int simulationID) +{ + using namespace Dumux; + + std::cout << "Initialize micro problem \n"; + + // parse the input file + Parameters::init("params.input"); + + // try to create a grid (from the given grid file or the input file) + _gridManager.init(); + + // we compute on the leaf grid view + const auto &leafGridView = _gridManager.grid().leafGridView(); + + // create the finite volume grid geometry + _gridGeometry = std::make_shared(leafGridView); + _gridGeometry->update(leafGridView); + + // get some time loop parameters + const auto tEnd = getParam("TimeLoop.TEnd"); + const auto maxDt = getParam("TimeLoop.MaxTimeStepSize"); + auto dt = getParam("TimeLoop.DtInitial"); + + // instantiate time loop + _timeLoop = std::make_shared>(0.0, dt, tEnd); + _timeLoop->setMaxTimeStepSize(maxDt); + + //////////////////////////////////// + // Set up the Allen-Cahn Problem // + //////////////////////////////////// + + // the AC problem + _acProblem = std::make_shared(_gridGeometry); + + // the AC solution vector + _acProblem->applyInitialSolution(_phi); + _phiOld = _phi; + + // the AC grid variables + _acGridVariables = std::make_shared(_acProblem, _gridGeometry); + _acGridVariables->init(_phi); + + // the AC assembler with time loop for the instationary problem + _acAssembler = std::make_shared(_acProblem, _gridGeometry, _acGridVariables, _timeLoop, _phiOld); + + // the non-linear (Newton) solver based on the linear solver for the AC problem + _acLinearSolver = std::make_shared(); + _acNonLinearSolver = std::make_shared(_acAssembler, _acLinearSolver); + + //////////////////////////////////////////////////////////// + // Set up the Cell Problem + //////////////////////////////////////////////////////////// + + // the cell problem + _cpProblem = std::make_shared(_gridGeometry); + + // the CP solution vector + CPSolutionVector psi(_gridGeometry->numDofs()); + _psi = psi; + + // the CP grid variables + _cpGridVariables = std::make_shared(_cpProblem, _gridGeometry); + _cpGridVariables->init(_psi); + + // the CP assembler for the stationary problem + _cpAssembler = std::make_shared(_cpProblem, _gridGeometry, _cpGridVariables); + + // the CP linear solver for the CP problem + _cpLinearSolver = std::make_shared(); + _cpLinearPDESolver = std::make_shared(_cpAssembler, _cpLinearSolver); + + // start tracking time + _timeLoop->start(); +}; + +// Initialize micro-data to be used in initial adaptivity +py::dict MicroSimulation::initialize() +{ + // update Phi in the cell problem + _cpProblem->spatialParams().updatePhi(_phi); + + // solve the cell problems + _cpLinearPDESolver->solve(_psi); + + // calculate porosity + _porosity = _acProblem->calculatePorosity(_phi); + + // compute the psi derivatives (required for conductivity tensor) + _cpProblem->computePsiDerivatives(*_cpProblem, *_cpAssembler, *_cpGridVariables, _psi); + + // calculate the conductivity tensor + _k_00 = _cpProblem->calculateConductivityTensorComponent(0, 0); + _k_11 = _cpProblem->calculateConductivityTensorComponent(1, 1); + + // create python dict for micro_write_data + py::dict micro_write_data; + + // add micro_scalar_data and micro_vector_data to micro_write_data + micro_write_data["k_00"] = _k_00; + micro_write_data["k_11"] = _k_11; + micro_write_data["porosity"] = _porosity; + + return micro_write_data; +} + +// Solve +py::dict MicroSimulation::solve(py::dict macro_write_data, double dt) +{ + // call leafgridView and point gridGeometry to it + const auto &leafGridView = _gridManager.grid().leafGridView(); + _gridGeometry->update(leafGridView); + + std::cout << "Solve timestep of micro problem \n"; + + // assert(dt != 0); + if (dt == 0) { + std::cout << "dt is zero\n"; + exit(1); + } + + _timeLoop->setTimeStepSize(dt); + + // read concentration from preCICE + double conc = macro_write_data["concentration"].cast(); + + // input macro concentration into allen-cahn problem + _acProblem->updateConcentration(conc); + + // linearize & solve the allen cahn problem + _acNonLinearSolver->solve(_phi, *_timeLoop); + + // u pdate Phi in the cell problem + _cpProblem->spatialParams().updatePhi(_phi); + + // solve the cell problems + _cpLinearPDESolver->solve(_psi); + + std::cout << "Compute upscaled quantities \n"; + + // calculate porosity + _porosity = _acProblem->calculatePorosity(_phi); + + // compute the psi derivatives (required for conductivity tensor) + _cpProblem->computePsiDerivatives(*_cpProblem, *_cpAssembler, *_cpGridVariables, _psi); + + // calculate the conductivity tensor + _k_00 = _cpProblem->calculateConductivityTensorComponent(0, 0); + _k_10 = _cpProblem->calculateConductivityTensorComponent(1, 0); + _k_01 = _cpProblem->calculateConductivityTensorComponent(0, 1); + _k_11 = _cpProblem->calculateConductivityTensorComponent(1, 1); + + // create python dict for micro_write_data + py::dict micro_write_data; + + // add micro_scalar_data and micro_vector_data to micro_write_data + micro_write_data["k_00"] = _k_00; + micro_write_data["k_10"] = _k_10; + micro_write_data["k_01"] = _k_01; + micro_write_data["k_11"] = _k_11; + micro_write_data["porosity"] = _porosity; + micro_write_data["grain_size"] = std::sqrt((1 - _porosity) / pi_); + + // write current primary variables to previous primary variables + _acGridVariables->advanceTimeStep(); + + // return micro_write_data + return micro_write_data; +} + +// This function needs to set the complete state of a micro simulation +void MicroSimulation::setState(py::tuple phi) +{ + py::list phi_py = phi[0]; + py::list phiOld_py = phi[1]; + + for (int i = 0; i < py::len(phi_py); ++i) { + _phi[i] = phi_py[i].cast(); + _phiOld[i] = phiOld_py[i].cast(); + } + _acGridVariables->update(_phiOld); + _acGridVariables->advanceTimeStep(); + _acGridVariables->update(_phi); +} + +// This function needs to return variables which can fully define the state of a micro simulation +py::tuple MicroSimulation::getState() const +{ + py::list phi_py; + py::list phiOld_py; + + for (const auto &x : this->_phi) { + phi_py.append(x[0]); + } + + for (const auto &xOld : this->_phiOld) { + phiOld_py.append(xOld[0]); + } + + return py::make_tuple(phi_py, phiOld_py); +} + +PYBIND11_MODULE(micro_sim, m) +{ + m.doc() = "pybind11 example plugin"; // optional module docstring + + py::class_(m, "MicroSimulation") + .def(py::init()) + .def("initialize", &MicroSimulation::initialize) + .def("solve", &MicroSimulation::solve) + //.def("save_checkpoint", &MicroSimulation::save_checkpoint) + //.def("reload_checkpoint", &MicroSimulation::reload_checkpoint) + .def("get_state", &MicroSimulation::getState) + .def("set_state", &MicroSimulation::setState) + .def(py::pickle( + [](const MicroSimulation &ms) { // __getstate__ + /* Return a tuple that fully encodes the state of the object */ + return ms.getState(); + }, + [](py::tuple t) { // __setstate__ + if (t.size() != 2) + throw std::runtime_error("Invalid state!"); + + /* Create a new C++ instance */ + MicroSimulation ms(0); + ms.initialize(); + ms.setState(t); + + return ms; + })); +} +} // end namespace Dumux diff --git a/two-scale-heat-conduction/micro-dumux/appl/problem_allencahn.hh b/two-scale-heat-conduction/micro-dumux/appl/problem_allencahn.hh new file mode 100644 index 000000000..c1bebe911 --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/appl/problem_allencahn.hh @@ -0,0 +1,196 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ + +#ifndef DUMUX_ALLENCAHN_PROBLEM_HH +#define DUMUX_ALLENCAHN_PROBLEM_HH + +#include +#include +#include +#include +#include +#include + +namespace Dumux { + +template +class AllenCahnProblem : public FVProblemWithSpatialParams { + using ParentType = FVProblemWithSpatialParams; + using GridView = + typename GetPropType::GridView; + using FVGridGeometry = GetPropType; + using Scalar = GetPropType; + using Indices = + typename GetPropType::Indices; + using BoundaryTypes = Dumux::BoundaryTypes< + GetPropType::numEq()>; + using PrimaryVariables = GetPropType; + using NumEqVector = Dumux::NumEqVector; + using ElementVolumeVariables = + typename GetPropType::LocalView; + using FVElementGeometry = + typename GetPropType::LocalView; + using SubControlVolume = typename FVElementGeometry::SubControlVolume; + using SolutionVector = GetPropType; + + static constexpr int phiIdx = Indices::phiIdx; + + using Element = typename GridView::template Codim<0>::Entity; + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + +public: + AllenCahnProblem(std::shared_ptr fvGridGeometry) + : ParentType(fvGridGeometry) + { + omega_ = getParam("Problem.omega"); + alpha_ = 1.0; + xi_ = getParam("Problem.xi"); + kt_ = getParam("Problem.kt"); + eqconc_ = getParam("Problem.eqconc"); + centerX_ = (getParam("Grid.UpperRight")[0] - + getParam("Grid.LowerLeft")[0]) / + 2; + centerY_ = (getParam("Grid.UpperRight")[1] - + getParam("Grid.LowerLeft")[1]) / + 2; + radius_ = getParam("Problem.Radius"); + factor_ = getParam("Problem.PhasefieldICScaling"); + maxPoro_ = getParam("Problem.MaxPorosity"); + } + + BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const + { + BoundaryTypes bcTypes; + + bcTypes.setAllNeumann(); + + return bcTypes; + } + + /*! + * \brief Calculates the derivative P' of the double-well potential \f$ P = 8 + * \phi^2 (1-\phi)^2\f$. + */ + Scalar pPrime(Scalar phi) const + { + return 16.0 * phi * (1.0 - phi) * (1.0 - 2.0 * phi); + } + + /*! + * \brief The source term is calculated as \f$ -\omega *P'(Phi) - 4*xi_ * Phi + * * (1-Phi)*F(T)\f$. + */ + NumEqVector source(const Element &element, + const FVElementGeometry &fvGeometry, + const ElementVolumeVariables &elemVolVars, + const SubControlVolume &scv) const + { + NumEqVector source; + + const auto &priVars = elemVolVars[scv].priVars(); + + source[phiIdx] = -omega_ * pPrime(priVars[phiIdx]); + source += + 4 * xi_ * priVars[phiIdx] * (1.0 - priVars[phiIdx]) * reactionRate(); + return source; + } + + /*! + * \brief Set the macro temperature/concentration + */ + void updateConcentration(Scalar conc) + { + conc_ = conc; + } + + /*! + * \brief Returns the interfaceVelocity to use in the source term (-F(T)) + */ + Scalar reactionRate() const + { + return -kt_ * + ((concentration() / eqconc_) * (concentration() / eqconc_) - 1); + } + + /*! + * \brief Returns the macro temperature/concentration + */ + Scalar concentration() const + { + return conc_; + } + + /*! + * \brief Returns the initial analytic value of the phasefield + * \note \f$ 1/(1+\exp(-4\lambda \sqrt{(y-y_0)² + (x-x_0)²}-R_0 )) \f$, + * where \f$|(x_0,y_0|\f$ is cell center + * and \f$ R_0\f$ is the initial radius of the grain. + */ + PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const + { + PrimaryVariables values; + + Scalar s = + std::sqrt((globalPos[0] - centerX_) * (globalPos[0] - centerX_) + + (globalPos[1] - centerY_) * (globalPos[1] - centerY_)) - + radius_; + values[phiIdx] = 1.0 / (1.0 + std::exp(-factor_ * s / xi_)); + return values; + } + + Scalar getAlpha() const + { + return alpha_; + } + + Scalar getOmega() const + { + return omega_; + } + + /*! + * \brief Calculates the upscaled porosity by integrating phi + */ + Scalar calculatePorosity(SolutionVector &sol) const + { + std::size_t order = 2; + Scalar poro = integrateGridFunction(this->gridGeometry(), sol, order); + if (poro <= maxPoro_) + return poro; + else + return maxPoro_; + } + +private: + Scalar xi_; + Scalar omega_; + Scalar alpha_; + Scalar kt_; + Scalar eqconc_; + std::vector poro_; + Scalar conc_; + Scalar maxPoro_; + + Scalar centerX_; + Scalar centerY_; + Scalar radius_; + Scalar factor_; +}; + +} // end namespace Dumux + +#endif diff --git a/two-scale-heat-conduction/micro-dumux/appl/problem_cellproblem.hh b/two-scale-heat-conduction/micro-dumux/appl/problem_cellproblem.hh new file mode 100644 index 000000000..efb1da4d4 --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/appl/problem_cellproblem.hh @@ -0,0 +1,273 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ + +#ifndef DUMUX_CELL_PROBLEM_HH +#define DUMUX_CELL_PROBLEM_HH + +#include +#include +#include +#include +#include + +namespace Dumux { + +template +class CellProblemProblem : public FVProblemWithSpatialParams { + using ParentType = FVProblemWithSpatialParams; + using GridView = + typename GetPropType::GridView; + using Element = typename GridView::template Codim<0>::Entity; + using GlobalPosition = typename Element::Geometry::GlobalCoordinate; + + using Scalar = GetPropType; + using PrimaryVariables = GetPropType; + using FVElementGeometry = + typename GetPropType::LocalView; + using SubControlVolume = typename FVElementGeometry::SubControlVolume; + using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; + using GridGeometry = GetPropType; + using BoundaryTypes = Dumux::BoundaryTypes; + using SolutionVector = GetPropType; + using DimWorldVector = Dune::FieldVector; + using Extrusion = Extrusion_t; + using ModelTraits = GetPropType; + using Indices = + typename GetPropType::Indices; + static constexpr auto numEq = ModelTraits::numEq(); + +public: + CellProblemProblem(std::shared_ptr gridGeometry) + : ParentType(gridGeometry) + { + // the partial derivatives of Psi + d0psi1_.resize(gridGeometry->numDofs()); + d1psi1_.resize(gridGeometry->numDofs()); + d0psi2_.resize(gridGeometry->numDofs()); + d1psi2_.resize(gridGeometry->numDofs()); + + // some memory for internal convenience + d_.resize(gridGeometry->numDofs()); + dPsi_.resize(gridGeometry->numDofs()); + delta_ij_.resize(gridGeometry->numDofs()); + } + + BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const + { + BoundaryTypes bcTypes; + + bcTypes.setAllNeumann(); + + return bcTypes; + } + + //! Enable internal Dirichlet constraints + static constexpr bool enableInternalDirichletConstraints() + { + return true; + } + + /*! + * \brief Tag a degree of freedom to carry internal Dirichlet constraints. + * If true is returned for a dof, the equation for this dof is replaced + * by the constraint that its primary variable values must match the + * user-defined values obtained from the function internalDirichlet(), + * which must be defined in the problem. + * + * \param element The finite element + * \param scv The sub-control volume + */ + std::bitset + hasInternalDirichletConstraint(const Element &element, + const SubControlVolume &scv) const + { + // the pure Neumann problem is only defined up to a constant + // we create a well-posed problem by fixing the pressure at one dof in the + // middle of the domain + std::bitset values; + if (scv.dofIndex() == + static_cast(this->gridGeometry().numDofs() - 1)) { + values.set(Indices::psi1Idx); + values.set(Indices::psi2Idx); + } + return values; + } + + /*! + * \brief Define the values of internal Dirichlet constraints for a degree of + * freedom. \param element The finite element \param scv The sub-control + * volume + */ + PrimaryVariables internalDirichlet(const Element &element, + const SubControlVolume &scv) const + { + return PrimaryVariables(1.0); + } + + /*! + * \brief Calculates the upscaled conductivity tensor components by + * integrating over the effective conductivity field \param psiIdx The + * index/dimension of the cell problem (0 or 1) \param derivIdx The + * index/dimension of the partial derivative (0 or 1) + */ + Scalar calculateConductivityTensorComponent(int psiIdx, int derivIdx) + { + std::size_t order = 4; + return integrateGridFunction(this->gridGeometry(), + effectiveConductivityField(psiIdx, derivIdx), + order); + } + + /*! + * \brief Calculates the effective conductivity field + * \note \f$ (\Phi*k_s + (1-\Phi)*kg_)*(\delta_{ij} + \partial y_i \Psi^{j}) + * \f$. \param psiIdx The index/dimension of the cell problem (0 or 1) = j + * \param derivIdx The index/dimension of the partial derivative (0 or 1) = i + */ + std::vector &effectiveConductivityField(int psiIdx, int derivIdx) + { + + if (psiIdx == derivIdx) + std::fill(delta_ij_.begin(), delta_ij_.end(), 1.0); + else + std::fill(delta_ij_.begin(), delta_ij_.end(), 0.0); + + dPsi_ = partialDerivativePsi(psiIdx, derivIdx); + + for (int elemIdx = 0; elemIdx < dPsi_.size(); ++elemIdx) { + d_[elemIdx] = this->spatialParams().phi0deltaIdx(elemIdx) * + (delta_ij_[elemIdx] + dPsi_[elemIdx]); + } + return d_; + } + + /*! + * \brief Returns the previously calculated partial derivative + */ + std::vector &partialDerivativePsi(int psiIdx, int derivIdx) + { + assert((psiIdx == 0) || (psiIdx == 1)); + assert((derivIdx == 0) || (derivIdx == 1)); + if ((psiIdx == 0) && (derivIdx == 0)) + return d0psi1_; + else if ((psiIdx == 0) && (derivIdx == 1)) + return d1psi1_; + else if ((psiIdx == 1) && (derivIdx == 0)) + return d0psi2_; + else + return d1psi2_; + } + + /*! + * \brief Computes the Psi Derivatives. + */ + template + void computePsiDerivatives(const Problem &problem, const Assembler &assembler, + const GridVariables &gridVars, + const SolutionVector &psi) + { + const auto &gridGeometry = this->gridGeometry(); + auto fvGeometry = localView(gridGeometry); + + const auto gridVolVars = assembler.gridVariables().curGridVolVars(); + auto elemVolVars = localView(gridVolVars); + + for (const auto &element : elements(gridGeometry.gridView())) { + + fvGeometry.bindElement(element); + elemVolVars.bindElement(element, fvGeometry, psi); + + for (int k = 0; k < Indices::numIdx; k++) { + + DimWorldVector cellDeriv(0.0); + Scalar scvVolume(0.0); + + for (const auto &scvf : scvfs(fvGeometry)) { + if (!scvf.boundary()) { + // Get the inside and outside volume variables + const auto &insideScv = fvGeometry.scv(scvf.insideScvIdx()); + const auto &outsideScv = fvGeometry.scv(scvf.outsideScvIdx()); + + const auto &insideVolVars = elemVolVars[scvf.insideScvIdx()]; + const auto valInside = insideVolVars.priVar(k); + + const Scalar ti = + computeTpfaTransmissibility(fvGeometry, scvf, insideScv, 1.0, + insideVolVars.extrusionFactor()); + + // faces might lie on the periodic boundary, requiring the matching + // scvf of the scv on the other side of the periodic boundary. + auto outsideFvGeometry = localView(gridGeometry); + const auto &periodicElement = + gridGeometry.element(outsideScv.elementIndex()); + outsideFvGeometry.bind(periodicElement); + auto outsideElemVolVars = localView(gridVolVars); + outsideElemVolVars.bindElement(periodicElement, outsideFvGeometry, + psi); + + Scalar tij = 0.0; + Scalar valOutside = 0.0; + for (const auto &outsideScvf : scvfs(outsideFvGeometry)) { + if (outsideScvf.unitOuterNormal() * scvf.unitOuterNormal() < + -1 + 1e-6) { + const auto &outsideVolVars = + outsideElemVolVars[outsideScvf.insideScvIdx()]; + + valOutside = outsideVolVars.priVar(k); + const Scalar tj = computeTpfaTransmissibility( + fvGeometry, outsideScvf, outsideScv, 1.0, + outsideVolVars.extrusionFactor()); + tij = scvf.area() * (tj) / (ti + tj); + break; + } + } + + cellDeriv += scvf.area() * (valOutside - valInside) * tij * + scvf.unitOuterNormal(); + scvVolume = insideScv.volume(); + } + } + + if (scvVolume > 0.0) + cellDeriv /= scvVolume; + const int eIdxGlobal = gridGeometry.elementMapper().index(element); + + if (k == 0) { + d0psi1_[eIdxGlobal] = cellDeriv[0]; + d1psi1_[eIdxGlobal] = cellDeriv[1]; + } else if (k == 1) { + d0psi2_[eIdxGlobal] = cellDeriv[0]; + d1psi2_[eIdxGlobal] = cellDeriv[1]; + } + } // end iteration over psiIdx + } // end iteration over elements + } + +private: + std::vector d0psi1_; + std::vector d1psi1_; + std::vector d0psi2_; + std::vector d1psi2_; + + std::vector d_; + std::vector delta_ij_; + std::vector dPsi_; +}; +} // end namespace Dumux + +#endif diff --git a/two-scale-heat-conduction/micro-dumux/appl/properties_allencahn.hh b/two-scale-heat-conduction/micro-dumux/appl/properties_allencahn.hh new file mode 100644 index 000000000..02c226e58 --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/appl/properties_allencahn.hh @@ -0,0 +1,58 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ + +#ifndef PROPERTIES_ALLENCAHN_HH +#define PROPERTIES_ALLENCAHN_HH + +#include +#include +#include +#include + +#include "problem_allencahn.hh" + +namespace Dumux::Properties { + +namespace TTag { +struct AllenCahn { + using InheritsFrom = std::tuple; +}; +} // namespace TTag + +template +struct Grid { + using type = Dune::SPGrid; +}; + +template +struct Problem { + using type = AllenCahnProblem; +}; + +template +struct EnableGridVolumeVariablesCache { + static constexpr bool value = true; +}; + +template +struct EnableGridGeometryCache { + static constexpr bool value = true; +}; + +} // end namespace Dumux::Properties + +#endif diff --git a/two-scale-heat-conduction/micro-dumux/appl/properties_cellproblem.hh b/two-scale-heat-conduction/micro-dumux/appl/properties_cellproblem.hh new file mode 100644 index 000000000..7be71ef34 --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/appl/properties_cellproblem.hh @@ -0,0 +1,60 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ + +// adapted from dumux/examples/1ptracer/properties.hh + +#ifndef DUMUX_CELL_PROBLEM_PROPERTIES_HH +#define DUMUX_CELL_PROBLEM_PROPERTIES_HH + +#include +#include +#include + +#include "cell_problem/model.hh" +#include "problem_cellproblem.hh" + +namespace Dumux::Properties { + +namespace TTag { +struct CellProblem { + using InheritsFrom = std::tuple; +}; +} // namespace TTag + +template +struct Grid { + using type = Dune::SPGrid; +}; + +template +struct Problem { + using type = CellProblemProblem; +}; + +template +struct EnableGridFluxVariablesCache { + static constexpr bool value = true; +}; + +template +struct EnableGridGeometryCache { + static constexpr bool value = true; +}; + +} // end namespace Dumux::Properties + +#endif diff --git a/two-scale-heat-conduction/micro-dumux/appl/spatialparams_cellproblem.hh b/two-scale-heat-conduction/micro-dumux/appl/spatialparams_cellproblem.hh new file mode 100644 index 000000000..d55d19ec9 --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/appl/spatialparams_cellproblem.hh @@ -0,0 +1,99 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *****************************************************************************/ + +#ifndef DUMUX_CELL_PROBLEM_SPATIAL_PARAMS_HH +#define DUMUX_CELL_PROBLEM_SPATIAL_PARAMS_HH + +#include + +namespace Dumux { + +template +class CellProblemSpatialParams + : public FVPorousMediumFlowSpatialParamsOneP< + GridGeometry, Scalar, + CellProblemSpatialParams> { + using GridView = typename GridGeometry::GridView; + using FVElementGeometry = typename GridGeometry::LocalView; + using SubControlVolume = typename FVElementGeometry::SubControlVolume; + using Element = typename GridView::template Codim<0>::Entity; + using ParentType = FVPorousMediumFlowSpatialParamsOneP< + GridGeometry, Scalar, CellProblemSpatialParams>; + static constexpr int dimWorld = GridView::dimensionworld; + using GlobalPosition = typename SubControlVolume::GlobalPosition; + + using AllenCahnTypeTag = Properties::TTag::AllenCahn; + using ACSolutionVector = + GetPropType; + using Vector = Dune::FieldVector; + using PhasefieldIndices = + typename GetPropType::Indices; + + enum { phiIdx = PhasefieldIndices::phiIdx }; + +public: + using PermeabilityType = Scalar; + + CellProblemSpatialParams(std::shared_ptr gridGeometry) + : ParentType(gridGeometry) + { + ks_ = getParam("Problem.ks"); + kg_ = getParam("Problem.kg"); + numDofs_ = gridGeometry->numDofs(); + phi_.resize(gridGeometry->numDofs()); + updatePhiCalled_ = false; + } + + void updatePhi(ACSolutionVector &sol) + { + for (int i = 0; i < numDofs_; i++) { + phi_[i] = sol[i]; + } + updatePhiCalled_ = true; + } + + Scalar phasefield(const SubControlVolume &scv) const + { + return phi_[scv.elementIndex()]; + } + + /*! + * \brief Returns \f$ \Phi*k_s + (1-\Phi)*k_g\f$ for by scv. + */ + Scalar phi0delta(const SubControlVolume &scv) const + { + return phasefield(scv) * ks_ + (1 - phasefield(scv)) * kg_; + } + + /*! + * \brief Returns \f$ \Phi*k_s + (1-\Phi)*k_g\f$ for by elementIndex. + */ + Scalar phi0deltaIdx(int idx) + { + return ks_ * phi_[idx] + kg_ * (1 - phi_[idx]); + } + +private: + std::vector phi_; + Scalar ks_; + Scalar kg_; + Scalar numDofs_; + bool updatePhiCalled_; +}; +} // end namespace Dumux + +#endif diff --git a/two-scale-heat-conduction/micro-dumux/clean.sh b/two-scale-heat-conduction/micro-dumux/clean.sh new file mode 100755 index 000000000..db81de5db --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_dumux . diff --git a/two-scale-heat-conduction/micro-dumux/config.h.cmake b/two-scale-heat-conduction/micro-dumux/config.h.cmake new file mode 100644 index 000000000..8896fa053 --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/config.h.cmake @@ -0,0 +1,45 @@ +/* begin micro_sim + put the definitions for config.h specific to + your project here. Everything above will be + overwritten +*/ + +/* begin private */ +/* Name of package */ +#define PACKAGE "@DUNE_MOD_NAME@" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "@DUNE_MAINTAINER@" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "@DUNE_MOD_NAME@" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "@DUNE_MOD_NAME@ @DUNE_MOD_VERSION@" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "@DUNE_MOD_NAME@" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "@DUNE_MOD_URL@" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "@DUNE_MOD_VERSION@" + +/* end private */ + +/* Define to the version of micro-sim */ +#define MICRO_SIM_VERSION "@MICRO_SIM_VERSION@" + +/* Define to the major version of micro-sim */ +#define MICRO_SIM_VERSION_MAJOR @MICRO_SIM_VERSION_MAJOR@ + +/* Define to the minor version of micro-sim */ +#define MICRO_SIM_VERSION_MINOR @MICRO_SIM_VERSION_MINOR@ + +/* Define to the revision of micro-sim */ +#define MICRO_SIM_VERSION_REVISION @MICRO_SIM_VERSION_REVISION@ + +/* end micro_sim + Everything below here will be overwritten +*/ diff --git a/two-scale-heat-conduction/micro-dumux/dune.module b/two-scale-heat-conduction/micro-dumux/dune.module new file mode 100644 index 000000000..02cf1a6bf --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/dune.module @@ -0,0 +1,12 @@ +################################ +# Dune module information file # +################################ + +# Name of the module +Module: micro_sim +Version: 1.0 +Maintainer: jun.chen@ipvs.uni-stuttgart.de +# Required build dependencies +Depends: dumux-phasefield +# Optional build dependencies +#Suggests: diff --git a/two-scale-heat-conduction/micro-dumux/micro-manager-config.json b/two-scale-heat-conduction/micro-dumux/micro-manager-config.json new file mode 100644 index 000000000..46a4e6822 --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/micro-manager-config.json @@ -0,0 +1,25 @@ +{ + "micro_file_name": "micro_sim", + "coupling_params": { + "participant_name": "Micro-Manager", + "config_file_name": "../precice-config.xml", + "macro_mesh_name": "macro-mesh", + "write_data_names": {"k_00": "scalar", "k_01": "scalar", "k_10": "scalar", "k_11": "scalar", "porosity": "scalar"}, + "read_data_names": {"concentration": "scalar"} + }, + "simulation_params": { + "macro_domain_bounds": [0.0, 1.0, 0.0, 0.5], + "adaptivity": { + "type": "global", + "data": ["k_00", "k_11", "porosity", "concentration"], + "history_param": 0.1, + "coarsening_constant": 0.2, + "refining_constant": 0.05, + "every_implicit_iteration": "False", + "similarity_measure": "L2rel" + } + }, + "diagnostics": { + "data_from_micro_sims": {"grain_size": "scalar"} + } +} diff --git a/two-scale-heat-conduction/micro-dumux/micro_sim.pc.in b/two-scale-heat-conduction/micro-dumux/micro_sim.pc.in new file mode 100644 index 000000000..566aba5e4 --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/micro_sim.pc.in @@ -0,0 +1,15 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +CXX=@CXX@ +CC=@CC@ +DEPENDENCIES=@REQUIRES@ + +Name: @PACKAGE_NAME@ +Version: @VERSION@ +Description: micro_sim module +URL: http://dune-project.org/ +Requires: dumux-phasefield dumux-precice +Libs: -L${libdir} +Cflags: -I${includedir} diff --git a/two-scale-heat-conduction/micro-dumux/params.input b/two-scale-heat-conduction/micro-dumux/params.input new file mode 100644 index 000000000..964a6896d --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/params.input @@ -0,0 +1,25 @@ +[Assembly] +Multithreading = false + +[TimeLoop] +TEnd = 0.25 # end time of the simulation +DtInitial = 0.01 # initial time step size +MaxTimeStepSize = 0.01 # maximal time step size + +[Grid] +LowerLeft = 0.0 0.0 # lower left (front) corner of the domain (keep this fixed at 0 0!) +UpperRight = 1.0 1.0 # upper right (back) corner of the domain +Cells = 80 80 # grid resolution in each coordinate direction +Periodic = 1 1 # Periodic Boundary conditions in both dimensions + +[Problem] +xi = 0.08 # phasefield parameter (lambda, set to around 4/Ncells) +omega = 0.01 # phasefield diffusivity/surface tension parameter (gamma) +kt = 1.0 # constant deciding speed of expansion/contraction +eqconc = 0.5 # equilibrium concentration +ks = 1.0 # conductivity of sand material +kg = 0.0 # conductivity of void material +Name = cell_phase # base name for VTK output files +Radius = 0.4 # initial radius of the grain +PhasefieldICScaling = 4.0 # factor in initial phasefield function +MaxPorosity = 0.9686 # porosity cap diff --git a/two-scale-heat-conduction/micro-dumux/run.sh b/two-scale-heat-conduction/micro-dumux/run.sh new file mode 100755 index 000000000..7ce4c9a0b --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/run.sh @@ -0,0 +1,29 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +usage() { echo "Usage: cmd [-s] [-p n]" 1>&2; exit 1; } + +# Check if no input argument was provided +if [ -z "$*" ] ; then + echo "No input argument provided. Micro Manager is launched in serial" + python3 run_micro_manager.py params.input +fi + +while getopts ":sp" opt; do + case ${opt} in + s) + python3 run_micro_manager.py params.input + ;; + p) + mpiexec -n "$2" python3 run_micro_manager.py params.input + ;; + *) + usage + ;; + esac +done + +close_log diff --git a/two-scale-heat-conduction/micro-dumux/run_micro_manager.py b/two-scale-heat-conduction/micro-dumux/run_micro_manager.py new file mode 100644 index 000000000..c1def36e8 --- /dev/null +++ b/two-scale-heat-conduction/micro-dumux/run_micro_manager.py @@ -0,0 +1,9 @@ +""" +Script to run the Micro Manager +""" + +from micro_manager import MicroManager + +manager = MicroManager("micro-manager-config.json") + +manager.solve() diff --git a/two-scale-heat-conduction/micro-nutils/clean.sh b/two-scale-heat-conduction/micro-nutils/clean.sh new file mode 100755 index 000000000..6893c1ea5 --- /dev/null +++ b/two-scale-heat-conduction/micro-nutils/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_nutils . diff --git a/two-scale-heat-conduction/micro-nutils/micro-manager-config.json b/two-scale-heat-conduction/micro-nutils/micro-manager-config.json new file mode 100644 index 000000000..74c1a4d4f --- /dev/null +++ b/two-scale-heat-conduction/micro-nutils/micro-manager-config.json @@ -0,0 +1,26 @@ +{ + "micro_file_name": "micro", + "coupling_params": { + "participant_name": "Micro-Manager", + "config_file_name": "../precice-config.xml", + "macro_mesh_name": "macro-mesh", + "write_data_names": {"k_00": "scalar", "k_01": "scalar", "k_10": "scalar", "k_11": "scalar", "porosity": "scalar"}, + "read_data_names": {"concentration": "scalar"} + }, + "simulation_params": { + "macro_domain_bounds": [0.0, 1.0, 0.0, 0.5], + "decomposition": [2, 1], + "adaptivity": { + "type": "global", + "data": ["k_00", "k_11", "porosity", "concentration"], + "history_param": 0.1, + "coarsening_constant": 0.2, + "refining_constant": 0.05, + "every_implicit_iteration": "False", + "similarity_measure": "L2rel" + } + }, + "diagnostics": { + "data_from_micro_sims": {"grain_size": "scalar"} + } +} diff --git a/two-scale-heat-conduction/micro-nutils/micro.py b/two-scale-heat-conduction/micro-nutils/micro.py new file mode 100644 index 000000000..9da25e1f9 --- /dev/null +++ b/two-scale-heat-conduction/micro-nutils/micro.py @@ -0,0 +1,289 @@ +""" +Micro simulation +In this script we solve the Laplace equation with a grain depicted by a phase field on a square domain :math:`Ω` +with boundary :math:`Γ`, subject to periodic boundary conditions in both dimensions +""" +import math + +from nutils import mesh, function, solver, export, cli +import treelog +import numpy as np +from copy import deepcopy + + +class MicroSimulation: + + def __init__(self, sim_id): + """ + Constructor of MicroSimulation class. + """ + self._sim_id = sim_id + + # Initial parameters + self._nelems = 6 # Elements in one direction + + self._ref_level = 3 # Number of levels of mesh refinement + self._r_initial = 0.4 # Initial radius of the grain + + # Interpolation order for phi and u + self._degree_phi = 2 + self._degree_u = 2 + + # Set up mesh with periodicity in both X and Y directions + self._topo, self._geom = mesh.rectilinear([np.linspace(-0.5, 0.5, self._nelems + 1)] * 2, periodic=(0, 1)) + self._topo_coarse = self._topo # Save original coarse topology to use to re-refinement + + self._solu = None # Solution of weights for which cell problem is solved for + self._solphi = None # Solution of phase field + self._solphinm1 = None # Solution of phase field at t_{n-1} + self._solphi_checkpoint = None # Save the current solution of the phase field as a checkpoint. + self._topo_checkpoint = None # Save the refined mesh as a checkpoint. + self._ucons = None + self._first_iter_done = False + self._initial_condition_is_set = False + self._k_nm1 = None # Average effective conductivity of last time step + + def initialize(self): + # Define initial namespace + self._ns = function.Namespace() + self._ns.x = self._geom + + self._ns.phibasis = self._topo.basis('std', degree=self._degree_phi) + self._ns.phi = 'phibasis_n ?solphi_n' # Initial phase field + self._ns.coarsephibasis = self._topo_coarse.basis('std', degree=self._degree_phi) + self._ns.coarsephi = 'coarsephibasis_n ?coarsesolphi_n' # Phase field on original coarse topology + self._ns.lam = (4 / self._nelems) / (2 ** self._ref_level) + self._ns.coarselam = 3 / self._nelems + + # Initialize phase field + solphi = self._get_analytical_phasefield( + self._topo, + self._ns, + self._degree_phi, + self._ns.coarselam, + self._r_initial) + + # Refine the mesh + self._topo, self._solphi = self._refine_mesh(self._topo, solphi) + self._reinitialize_namespace(self._topo) + self._initial_condition_is_set = True + + # Initialize phase field once more on refined topology + solphi = self._get_analytical_phasefield(self._topo, self._ns, self._degree_phi, self._ns.lam, self._r_initial) + + self._solphi = solphi # Save solution of phi + psi = self._get_avg_porosity(self._topo, solphi) + self._psi_nm1 = psi # Average porosity value of last time step + + # Solve the heat cell problem + solu = self._solve_heat_cell_problem(self._topo, solphi) + k = self._get_eff_conductivity(self._topo, solu, solphi) + + self._solu = solu # Save solution for output + + output_data = dict() + output_data["k_00"] = k[0][0] + output_data["k_11"] = k[1][1] + output_data["porosity"] = psi + + return output_data + + def _reinitialize_namespace(self, topo): + self._ns = None # Clear old namespace + self._ns = function.Namespace() + self._ns.x = self._geom + self._ns.ubasis = topo.basis('h-std', degree=self._degree_u).vector(topo.ndims) + self._ns.phibasis = topo.basis('h-std', degree=self._degree_phi) + self._ns.coarsephibasis = self._topo_coarse.basis('std', degree=self._degree_phi) + + self._ns.lam = (4 / self._nelems) / (2 ** self._ref_level) # Diffuse interface width + self._ns.gam = 0.05 + self._ns.kt = 1.0 + self._ns.eqconc = 0.5 # Equilibrium concentration + self._ns.kg = 0.0 # Conductivity of grain material + self._ns.ks = 1.0 # Conductivity of sand material + self._ns.reacrate = 'kt (?conc / eqconc)^2 - 1' # Constructed reaction rate based on macro temperature + self._ns.u = 'ubasis_ni ?solu_n' # Weights for which cell problem is solved for + self._ns.du_ij = 'u_i,j' # Gradient of weights field + self._ns.phi = 'phibasis_n ?solphi_n' # Phase field + self._ns.coarsephi = 'coarsephibasis_n ?coarsesolphi_n' # Phase field on original coarse topology + self._ns.ddwpdphi = '16 phi (1 - phi) (1 - 2 phi)' # gradient of double-well potential + self._ns.dphidt = 'phibasis_n (?solphi_n - ?solphinm1_n) / ?dt' # Implicit time evolution of phase field + + self._ucons = np.zeros(len(self._ns.ubasis), dtype=bool) + self._ucons[-1] = True # constrain u to zero at a point + + @staticmethod + def _analytical_phasefield(x, y, r, lam): + return 1. / (1. + np.exp(-4. / lam * (np.sqrt(x ** 2 + y ** 2) - r))) + + @staticmethod + def _get_analytical_phasefield(topo, ns, degree_phi, lam, r): + phi_ini = MicroSimulation._analytical_phasefield(ns.x[0], ns.x[1], r, lam) + sqrphi = topo.integral((ns.phi - phi_ini) ** 2, degree=degree_phi * 2) + solphi = solver.optimize('solphi', sqrphi, droptol=1E-12) + + return solphi + + # def output(self): + # bezier = self._topo.sample('bezier', 2) + # x, u, phi = bezier.eval(['x_i', 'u_i', 'phi'] @ self._ns, solu=self._solu, solphi=self._solphi) + # with treelog.add(treelog.DataLog()): + # export.vtk("micro-heat-{}".format(self._sim_id), bezier.tri, x, T=u, phi=phi) + + def get_state(self): + return [self._solphi.copy(), deepcopy(self._topo)] + + def set_state(self, state): + self._solphi = state[0] + self._topo = state[1] + self._reinitialize_namespace(self._topo) # The namespace also needs to reloaded to its earlier state + + def _refine_mesh(self, topo_nm1, solphi_nm1): + """ + At the time of the calling of this function a predicted solution exists in ns.phi + """ + if not self._initial_condition_is_set: + solphi = solphi_nm1 + # ----- Refine the coarse mesh according to the projected solution to get a predicted refined topology ---- + topo = self._topo_coarse + for level in range(self._ref_level): + # print("refinement level = {}".format(level)) + smpl = topo.sample('uniform', 5) + ielem, criterion = smpl.eval([topo.f_index, abs(self._ns.coarsephi - .5) < .4], coarsesolphi=solphi) + + # Refine the elements for which at least one point tests true. + topo = topo.refined_by(np.unique(ielem[criterion])) + + self._reinitialize_namespace(topo) + + phi_ini = MicroSimulation._analytical_phasefield(self._ns.x[0], self._ns.x[1], self._r_initial, + self._ns.lam) + sqrphi = topo.integral((self._ns.coarsephi - phi_ini) ** 2, degree=self._degree_phi * 2) + solphi = solver.optimize('coarsesolphi', sqrphi, droptol=1E-12) + # ---------------------------------------------------------------------------------------------------- + else: + # ----- Refine the coarse mesh according to the projected solution to get a predicted refined topology ---- + topo = self._topo_coarse + for level in range(self._ref_level): + # print("refinement level = {}".format(level)) + topo_union1 = topo_nm1 & topo + smpl = topo_union1.sample('uniform', 5) + ielem, criterion = smpl.eval([topo.f_index, abs(self._ns.phi - .5) < .4], solphi=solphi_nm1) + + # Refine the elements for which at least one point tests true. + topo = topo.refined_by(np.unique(ielem[criterion])) + # ---------------------------------------------------------------------------------------------------- + + # Create a new projection mesh which is the union of the previous refined mesh and the predicted mesh + topo_union = topo_nm1 & topo + + # ----- Project the solution of the last time step on the projection mesh ----- + self._ns.projectedphi = function.dotarg('projectedsolphi', topo.basis('h-std', degree=self._degree_phi)) + sqrphi = topo_union.integral((self._ns.projectedphi - self._ns.phi) ** 2, degree=self._degree_phi * 2) + solphi = solver.optimize('projectedsolphi', sqrphi, droptol=1E-12, arguments=dict(solphi=solphi_nm1)) + + # Clip values of phase field to be in [0 1] to avoid overshoots and undershoots due to projection + solphi = np.clip(solphi, 0, 1) + + return topo, solphi + + def _solve_allen_cahn(self, topo, phi_coeffs_nm1, concentration, dt): + """ + Solving the Allen-Cahn equation using a Newton solver. + Returns porosity of the micro domain. + """ + self._first_iter_done = True + resphi = topo.integral('(lam^2 phibasis_n dphidt + gam phibasis_n ddwpdphi + gam lam^2 phibasis_n,i phi_,i + ' + '4 lam reacrate phibasis_n phi (1 - phi)) d:x' @ self._ns, degree=self._degree_phi * 2) + + args = dict(solphinm1=phi_coeffs_nm1, dt=dt, conc=concentration) + phi_coeffs = solver.newton('solphi', resphi, lhs0=phi_coeffs_nm1, arguments=args).solve(tol=1E-12) + + return phi_coeffs + + def _get_avg_porosity(self, topo, phi_coeffs): + psi = topo.integral('phi d:x' @ self._ns, degree=self._degree_phi * 2).eval(solphi=phi_coeffs) + + return psi + + def _solve_heat_cell_problem(self, topo, phi_coeffs): + """ + Solving the P1 homogenized heat equation + Returns upscaled conductivity for the micro domain + """ + res = topo.integral('((phi ks + (1 - phi) kg) u_i,j ubasis_ni,j - ' + '(ks - kg) phi_,j $_ij ubasis_ni) d:x' @ self._ns, degree=self._degree_u * 2) + + args = dict(solphi=phi_coeffs) + u_coeffs = solver.solve_linear('solu', res, constrain=self._ucons, arguments=args) + + return u_coeffs + + def _get_eff_conductivity(self, topo, u_coeffs, phi_coeffs): + b = topo.integral( + self._ns.eval_ij('(phi ks + (1 - phi) kg) ($_ij + du_ij) d:x'), + degree=self._degree_u * + 2).eval( + solu=u_coeffs, + solphi=phi_coeffs) + + return b.export("dense") + + def solve(self, macro_data, dt): + if self._psi_nm1 < 0.95: + topo, solphi = self._refine_mesh(self._topo, self._solphi) + self._reinitialize_namespace(topo) + + assert ((solphi >= 0.0) & (solphi <= 1.0)).all() + + solphi = self._solve_allen_cahn(topo, solphi, macro_data["concentration"], dt) + psi = self._get_avg_porosity(topo, solphi) + + solu = self._solve_heat_cell_problem(topo, solphi) + k = self._get_eff_conductivity(topo, solu, solphi) + + # Save state variables + self._topo = topo + self._solphi = solphi + self._solu = solu + self._psi_nm1 = psi + self._k_nm1 = k + else: + # Micro simulation has reached max porosity limit and hence is not solved + k = self._k_nm1 + psi = self._psi_nm1 + + output_data = dict() + output_data["k_00"] = k[0][0] + output_data["k_01"] = k[0][1] + output_data["k_10"] = k[1][0] + output_data["k_11"] = k[1][1] + output_data["porosity"] = psi + output_data["grain_size"] = math.sqrt((1 - psi) / math.pi) + + return output_data + + +def main(): + micro_problem = MicroSimulation(0) + dt = 1e-3 + micro_problem.initialize() + concentrations = [0.5, 0.4] + t = 0.0 + n = 0 + concentration = dict() + + for conc in concentrations: + concentration["concentration"] = conc + + micro_sim_output = micro_problem.solve(concentration, dt) + + # micro_problem.output() + t += dt + n += 1 + print(micro_sim_output) + + +if __name__ == "__main__": + cli.run(main) diff --git a/two-scale-heat-conduction/micro-nutils/requirements.txt b/two-scale-heat-conduction/micro-nutils/requirements.txt new file mode 100644 index 000000000..7e22175a7 --- /dev/null +++ b/two-scale-heat-conduction/micro-nutils/requirements.txt @@ -0,0 +1,3 @@ +nutils==7 +pyprecice==3 +micro-manager-precice==0.4.0 diff --git a/two-scale-heat-conduction/micro-nutils/run.sh b/two-scale-heat-conduction/micro-nutils/run.sh new file mode 100755 index 000000000..f51583362 --- /dev/null +++ b/two-scale-heat-conduction/micro-nutils/run.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +usage() { echo "Usage: cmd [-s] [-p n]" 1>&2; exit 1; } + +python3 -m venv .venv +. .venv/bin/activate +pip install -r requirements.txt + +# Check if no input argument was provided +if [ -z "$*" ] ; then + echo "No input argument provided. Micro Manager is launched in serial" + python3 run_micro_manager.py +fi + +while getopts ":sp" opt; do + case ${opt} in + s) + python3 run_micro_manager.py + ;; + p) + mpiexec -n "$2" python3 run_micro_manager.py + ;; + *) + usage + ;; + esac +done + +close_log diff --git a/two-scale-heat-conduction/micro-nutils/run_micro_manager.py b/two-scale-heat-conduction/micro-nutils/run_micro_manager.py new file mode 100644 index 000000000..c1def36e8 --- /dev/null +++ b/two-scale-heat-conduction/micro-nutils/run_micro_manager.py @@ -0,0 +1,9 @@ +""" +Script to run the Micro Manager +""" + +from micro_manager import MicroManager + +manager = MicroManager("micro-manager-config.json") + +manager.solve() diff --git a/two-scale-heat-conduction/precice-config.xml b/two-scale-heat-conduction/precice-config.xml new file mode 100644 index 000000000..f2a08da32 --- /dev/null +++ b/two-scale-heat-conduction/precice-config.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/two-scale-heat-conduction/setup-dumux.sh b/two-scale-heat-conduction/setup-dumux.sh new file mode 100755 index 000000000..675ff45ce --- /dev/null +++ b/two-scale-heat-conduction/setup-dumux.sh @@ -0,0 +1,37 @@ +#!/bin/sh +set -e -u + +# This script sets up a DUNE environment in the working directory to solve the two-scale-heat-conduction problem with DuMuX on one or both scales + +# Clean any old leftover dumux or dune folders +rm -rfv dumux/ dumux-adapter/ dumux-phasefield/ +rm -rfv dune-*/ +rm -rfv install* + +# Get the DuMuX install script and install it +wget https://git.iws.uni-stuttgart.de/dumux-repositories/dumux/-/raw/releases/3.7/bin/installdumux.py +DUNE_CONTROL_PATH=. python3 installdumux.py +# clear build directories +cd dumux +rm -r dune-common/build-cmake/dune-env/lib/dunecontrol || true +DUNE_CONTROL_PATH=. ./dune-common/bin/dunecontrol exec rm -r build-cmake +cd .. + +# Take out all the module folders from the dumux/ folder and remove the dumux/ folder +mv dumux dumux-install +mv dumux-install/* ./ +rm -r dumux-install + +# Get additional required DUNE modules +# DuMux-preCICE adapter +git clone https://github.com/precice/dumux-adapter.git +# DuMux phasefield implementation +git clone -b cell_problems https://git.iws.uni-stuttgart.de/dumux-appl/dumux-phasefield.git +# DUNE SPGrid for periodic boundary conditions +DUNE_CONTROL_PATH=. python3 dumux/bin/installexternal.py spgrid + +# Re-build environment +DUNE_CONTROL_PATH=. ./dune-common/bin/dunecontrol --opts=./dumux/cmake.opts all + +# Compile and move macro-dumux and micro-dumux executables to the participant folder level +./compile-dumux-cases.sh diff --git a/volume-coupled-diffusion/README.md b/volume-coupled-diffusion/README.md index 28ec8f660..41d3ef6b4 100644 --- a/volume-coupled-diffusion/README.md +++ b/volume-coupled-diffusion/README.md @@ -13,29 +13,32 @@ This case illustrates how to implement volume coupling in a simple toy problem. ![Case setup of volume-coupled-diffusion case](images/tutorials-volume-coupled-diffusion-setup.png) -## Available solvers and dependencies +## Configuration -* FEniCS. Install [FEniCS](https://fenicsproject.org/download/) and the [FEniCS-adapter](https://github.com/precice/fenics-adapter). Additionally, you will need to have preCICE and the python bindings installed on your system. +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): -## Running the simulation +![preCICE configuration visualization](images/tutorials-volume-coupled-diffusion-precice-config.png) + +## Available solvers and dependencies -This tutorial is for FEniCS. You can find the corresponding `run.sh` script in the folder `fenics`. +Both participants (Source and Drain): -To choose whether you want to run the source or the drain solver, please provide the following command line input: +* FEniCS. Install [FEniCS](https://fenicsproject.org/download/) and the [FEniCS-adapter](https://github.com/precice/fenics-adapter). Additionally, you will need to have preCICE and the python bindings installed on your system. -* `-s` flag will create a source. -* `-d` flag will create a drain. +## Running the simulation -For running the case, open two terminals run: +FEniCS is used to run the simulation. Open two separate terminals and start the source and drain participant by calling the respective run script `run.sh` located in the participant directory. For example: ```bash -cd fenics -./run.sh -s +cd source-fenics +./run.sh ``` and ```bash -cd fenics -./run.sh -d +cd drain-fenics +./run.sh ``` + +in order to use FEniCS for both participants in this test case. diff --git a/volume-coupled-diffusion/drain-fenics/clean.sh b/volume-coupled-diffusion/drain-fenics/clean.sh new file mode 100755 index 000000000..3a8b4619d --- /dev/null +++ b/volume-coupled-diffusion/drain-fenics/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_fenics . diff --git a/volume-coupled-diffusion/fenics/precice-adapter-config-drain.json b/volume-coupled-diffusion/drain-fenics/precice-adapter-config.json similarity index 100% rename from volume-coupled-diffusion/fenics/precice-adapter-config-drain.json rename to volume-coupled-diffusion/drain-fenics/precice-adapter-config.json diff --git a/volume-coupled-diffusion/drain-fenics/run.sh b/volume-coupled-diffusion/drain-fenics/run.sh new file mode 100755 index 000000000..48f2832ad --- /dev/null +++ b/volume-coupled-diffusion/drain-fenics/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 ../solver-fenics/volume-coupled-diffusion.py --drain + +close_log diff --git a/volume-coupled-diffusion/fenics/.gitignore b/volume-coupled-diffusion/fenics/.gitignore deleted file mode 100644 index 1c6ed0137..000000000 --- a/volume-coupled-diffusion/fenics/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -venv -*.pyc -*.log -out diff --git a/volume-coupled-diffusion/fenics/run.sh b/volume-coupled-diffusion/fenics/run.sh deleted file mode 100755 index d15dd2163..000000000 --- a/volume-coupled-diffusion/fenics/run.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -set -e -u - -usage() { echo "Usage: cmd [-s] [-d]" 1>&2; exit 1; } - -# Check if no input argument was provided -if [ -z "$*" ] ; then - usage -fi - -# Select appropriate case -while getopts ":sd" opt; do - case ${opt} in - s) - python3 volume-coupled-diffusion.py --source - ;; - d) - python3 volume-coupled-diffusion.py --drain - ;; - *) - usage - ;; - esac -done diff --git a/volume-coupled-diffusion/images/tutorials-volume-coupled-diffusion-precice-config.png b/volume-coupled-diffusion/images/tutorials-volume-coupled-diffusion-precice-config.png new file mode 100644 index 000000000..496bdd23f Binary files /dev/null and b/volume-coupled-diffusion/images/tutorials-volume-coupled-diffusion-precice-config.png differ diff --git a/volume-coupled-diffusion/precice-config.xml b/volume-coupled-diffusion/precice-config.xml index a8c7b7a6d..b6c14d387 100644 --- a/volume-coupled-diffusion/precice-config.xml +++ b/volume-coupled-diffusion/precice-config.xml @@ -1,61 +1,62 @@ - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/volume-coupled-diffusion/fenics/volume-coupled-diffusion.py b/volume-coupled-diffusion/solver-fenics/volume-coupled-diffusion.py similarity index 85% rename from volume-coupled-diffusion/fenics/volume-coupled-diffusion.py rename to volume-coupled-diffusion/solver-fenics/volume-coupled-diffusion.py index eeffce490..034ebec2e 100644 --- a/volume-coupled-diffusion/fenics/volume-coupled-diffusion.py +++ b/volume-coupled-diffusion/solver-fenics/volume-coupled-diffusion.py @@ -26,10 +26,7 @@ def inside(self, x, on_boundary): command_group.add_argument("-d", "--drain", help="create a drain", dest="drain", action="store_true") args = parser.parse_args() -if args.source: - precice = Adapter(adapter_config_filename="precice-adapter-config-source.json") -elif args.drain: - precice = Adapter(adapter_config_filename="precice-adapter-config-drain.json") +precice = Adapter(adapter_config_filename="precice-adapter-config.json") mesh = UnitSquareMesh(10, 10) V = FunctionSpace(mesh, "P", 1) @@ -48,11 +45,11 @@ def inside(self, x, on_boundary): u_n = interpolate(u_ini, V) -dt = precice.initialize(AllDomain(), read_function_space=V, write_object=u_n) +precice.initialize(AllDomain(), read_function_space=V, write_object=u_n) volume_term = precice.create_coupling_expression() f = Function(V) - +dt = precice.get_max_time_step_size() dt_inv = Constant(1 / dt) diffusion_source = 1 @@ -87,16 +84,17 @@ def inside(self, x, on_boundary): # output solution and reference solution at t=0, n=0 n = 0 print('output u^%d and u_ref^%d' % (n, n)) -solution_out << u_n +solution_out << (u_n, t) ranks << mesh_rank while precice.is_coupling_ongoing(): # write checkpoint - if precice.is_action_required(precice.action_write_iteration_checkpoint()): + if precice.requires_writing_checkpoint(): precice.store_checkpoint(u_n, t, n) - read_data = precice.read_data() + dt = precice.get_max_time_step_size() + read_data = precice.read_data(dt) # Update the coupling expression with the new read data precice.update_coupling_expression(volume_term, read_data) @@ -111,10 +109,10 @@ def inside(self, x, on_boundary): # Write data to preCICE according to which problem is being solved precice.write_data(u_np1) - dt = precice.advance(dt) + precice.advance(dt) # roll back to checkpoint - if precice.is_action_required(precice.action_read_iteration_checkpoint()): + if precice.requires_reading_checkpoint(): u_cp, t_cp, n_cp = precice.retrieve_checkpoint() u_n.assign(u_cp) t = t_cp @@ -125,7 +123,7 @@ def inside(self, x, on_boundary): n += 1 if precice.is_time_window_complete(): - solution_out << u_n + solution_out << (u_n, t) # Hold plot precice.finalize() diff --git a/volume-coupled-diffusion/source-fenics/clean.sh b/volume-coupled-diffusion/source-fenics/clean.sh new file mode 100755 index 000000000..3a8b4619d --- /dev/null +++ b/volume-coupled-diffusion/source-fenics/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_fenics . diff --git a/volume-coupled-diffusion/fenics/precice-adapter-config-source.json b/volume-coupled-diffusion/source-fenics/precice-adapter-config.json similarity index 100% rename from volume-coupled-diffusion/fenics/precice-adapter-config-source.json rename to volume-coupled-diffusion/source-fenics/precice-adapter-config.json diff --git a/volume-coupled-diffusion/source-fenics/run.sh b/volume-coupled-diffusion/source-fenics/run.sh new file mode 100755 index 000000000..4dbf42539 --- /dev/null +++ b/volume-coupled-diffusion/source-fenics/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 ../solver-fenics/volume-coupled-diffusion.py --source + +close_log diff --git a/volume-coupled-flow/README.md b/volume-coupled-flow/README.md new file mode 100644 index 000000000..54731ef67 --- /dev/null +++ b/volume-coupled-flow/README.md @@ -0,0 +1,71 @@ +--- +title: Volume-coupled flow +permalink: tutorials-volume-coupled-flow.html +keywords: volume coupling, OpenFOAM, source terms +summary: A dummy source participant is coupled to a fluid in a uni-directional way over a region of the domain. The coupling enforces source terms on that region. +--- + +{% note %} +Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/volume-coupled-flow). Read how in the [tutorials introduction](https://www.precice.org/tutorials.html). +{% endnote %} + +## Setup + +We introduce flow into a fluid through a square-shaped source located between $$ (3.0, 1.0) $$ and $$ (3.5, 1.5) $$. The velocity at the source is constant in the x component $$ (U.x() = 10.0) $$. + +The state of the $$ U.x() $$ of the fluid at $$ t = 0.5s $$ (the source region is highlighted): + +![Ux](images/tutorials-volume-coupled-flow-Ux.png) + +This case is a convenient starting point for volume coupling where OpenFOAM is a reading participant. The writing Nutils participant (dummy source) can be replaced by a more complex solver according to the user's needs. + +## Configuration + +preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)): + +![preCICE configuration visualization](images/tutorials-volume-coupled-flow-precice-config.png) + +## Available solvers + +Fluid participant: + +* OpenFOAM (buoyantPimpleFoam). For more information, have a look at the [OpenFOAM adapter documentation](https://precice.org/adapter-openfoam-overview.html). + +Source participant: + +* Nutils. For more information, have a look at the [Nutils adapter documentation](https://www.precice.org/adapter-nutils.html). This Nutils solver requires at least Nutils v7.0. + +## Running the simulation + +Open two separate terminals and start the participants by calling the respective run scripts `run.sh` located in each of the participants' directory. For example: + +```bash +cd fluid-openfoam +./run.sh +``` + +and + +```bash +cd source-nutils +./run.sh +``` + +## Post-processing + +The fluid participants generates a `.foam` file which can be visualized using, e.g., ParaView. + +## Notes on the configuration + +This case uses OpenFOAM's `fvOptions` to enforce source terms. Additionally, the coupled variable `U` needs to be given an alternative name in order for this to work: + +```C++ +FF +{ + nameU U_vol; +}; +``` + +Since OpenFOAM already uses `U`, we need to create an additional velocity variable to use specifically for the coupling. That allows us to carry the desired value over to OpenFOAM and apply it at the correct moment in the iteration. A simplified view of the workflow: + +![reading-config](images/tutorials-volume-coupled-flow-config.png) diff --git a/volume-coupled-flow/clean-tutorial.sh b/volume-coupled-flow/clean-tutorial.sh new file mode 120000 index 000000000..4713f5092 --- /dev/null +++ b/volume-coupled-flow/clean-tutorial.sh @@ -0,0 +1 @@ +../tools/clean-tutorial-base.sh \ No newline at end of file diff --git a/volume-coupled-flow/fluid-openfoam/0/T b/volume-coupled-flow/fluid-openfoam/0/T new file mode 100644 index 000000000..03a8bbf6a --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/0/T @@ -0,0 +1,40 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} + +dimensions [ 0 0 0 1 0 0 0 ]; + +internalField uniform 300; + +boundaryField +{ + inlet + { + type fixedValue; + value $internalField; + } + outlet + { + type zeroGradient; + } + upperWall + { + type zeroGradient; + } + lowerWall + { + type zeroGradient; + } + frontAndBack + { + type empty; + } + defaultFaces + { + type empty; + } +} diff --git a/volume-coupled-flow/fluid-openfoam/0/U b/volume-coupled-flow/fluid-openfoam/0/U new file mode 100644 index 000000000..74f1b5960 --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/0/U @@ -0,0 +1,40 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} + +dimensions [ 0 1 -1 0 0 0 0 ]; + +internalField uniform ( 0.1 0 0 ); + +boundaryField +{ + inlet + { + type fixedValue; + value $internalField; + } + outlet + { + type zeroGradient; + } + upperWall + { + type noSlip; + } + lowerWall + { + type noSlip; + } + frontAndBack + { + type empty; + } + defaultFaces + { + type empty; + } +} diff --git a/volume-coupled-flow/fluid-openfoam/0/U_vol b/volume-coupled-flow/fluid-openfoam/0/U_vol new file mode 100644 index 000000000..d66054ec8 --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/0/U_vol @@ -0,0 +1,40 @@ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U_vol; +} + +dimensions [ 0 1 -1 0 0 0 0 ]; + +internalField uniform ( 0.1 0 0 ); + +boundaryField +{ + inlet + { + type fixedValue; + value $internalField; + } + outlet + { + type zeroGradient; + } + upperWall + { + type noSlip; + } + lowerWall + { + type noSlip; + } + frontAndBack + { + type empty; + } + defaultFaces + { + type empty; + } +} diff --git a/volume-coupled-flow/fluid-openfoam/0/alphat b/volume-coupled-flow/fluid-openfoam/0/alphat new file mode 100644 index 000000000..0fdc5b1a3 --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/0/alphat @@ -0,0 +1,43 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object alphat; +} + +dimensions [ 1 -1 -1 0 0 0 0 ]; + +internalField uniform 0; + +boundaryField +{ + inlet + { + type compressible::alphatWallFunction; + value uniform 0; + } + outlet + { + type compressible::alphatWallFunction; + value uniform 0; + } + upperWall + { + type compressible::alphatWallFunction; + value uniform 0; + } + lowerWall + { + type compressible::alphatWallFunction; + value uniform 0; + } + frontAndBack + { + type empty; + } + defaultFaces + { + type empty; + } +} diff --git a/volume-coupled-flow/fluid-openfoam/0/epsilon b/volume-coupled-flow/fluid-openfoam/0/epsilon new file mode 100644 index 000000000..434843c59 --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/0/epsilon @@ -0,0 +1,43 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object epsilon; +} + +dimensions [ 0 2 -3 0 0 0 0 ]; + +internalField uniform 0.01; + +boundaryField +{ + inlet + { + type epsilonWallFunction; + value uniform 0.01; + } + outlet + { + type epsilonWallFunction; + value uniform 0.01; + } + upperWall + { + type epsilonWallFunction; + value uniform 0.01; + } + lowerWall + { + type epsilonWallFunction; + value uniform 0.01; + } + frontAndBack + { + type empty; + } + defaultFaces + { + type empty; + } +} diff --git a/volume-coupled-flow/fluid-openfoam/0/k b/volume-coupled-flow/fluid-openfoam/0/k new file mode 100644 index 000000000..37d6a819b --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/0/k @@ -0,0 +1,43 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object k; +} + +dimensions [ 0 2 -2 0 0 0 0 ]; + +internalField uniform 0.1; + +boundaryField +{ + inlet + { + type kqRWallFunction; + value uniform 0.1; + } + outlet + { + type kqRWallFunction; + value uniform 0.1; + } + upperWall + { + type kqRWallFunction; + value uniform 0.1; + } + lowerWall + { + type kqRWallFunction; + value uniform 0.1; + } + frontAndBack + { + type empty; + } + defaultFaces + { + type empty; + } +} diff --git a/volume-coupled-flow/fluid-openfoam/0/nut b/volume-coupled-flow/fluid-openfoam/0/nut new file mode 100644 index 000000000..f5c45835b --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/0/nut @@ -0,0 +1,43 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object nut; +} + +dimensions [ 0 2 -1 0 0 0 0 ]; + +internalField uniform 0; + +boundaryField +{ + inlet + { + type nutkWallFunction; + value uniform 0; + } + outlet + { + type nutkWallFunction; + value uniform 0; + } + upperWall + { + type nutkWallFunction; + value uniform 0; + } + lowerWall + { + type nutkWallFunction; + value uniform 0; + } + frontAndBack + { + type empty; + } + defaultFaces + { + type empty; + } +} diff --git a/volume-coupled-flow/fluid-openfoam/0/p b/volume-coupled-flow/fluid-openfoam/0/p new file mode 100644 index 000000000..bbd499549 --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/0/p @@ -0,0 +1,43 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p; +} + +dimensions [ 1 -1 -2 0 0 0 0 ]; + +internalField uniform 103500; + +boundaryField +{ + inlet + { + type calculated; + value $internalField; + } + outlet + { + type calculated; + value $internalField; + } + upperWall + { + type calculated; + value $internalField; + } + lowerWall + { + type calculated; + value $internalField; + } + frontAndBack + { + type empty; + } + defaultFaces + { + type empty; + } +} diff --git a/volume-coupled-flow/fluid-openfoam/0/p_rgh b/volume-coupled-flow/fluid-openfoam/0/p_rgh new file mode 100644 index 000000000..57b7d70c3 --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/0/p_rgh @@ -0,0 +1,40 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p_rgh; +} + +dimensions [ 1 -1 -2 0 0 0 0 ]; + +internalField uniform 103500; + +boundaryField +{ + inlet + { + type zeroGradient; + } + outlet + { + type fixedValue; + value $internalField; + } + upperWall + { + type zeroGradient; + } + lowerWall + { + type zeroGradient; + } + frontAndBottom + { + type empty; + } + defaultFaces + { + type empty; + } +} diff --git a/volume-coupled-flow/fluid-openfoam/clean.sh b/volume-coupled-flow/fluid-openfoam/clean.sh new file mode 100755 index 000000000..c31d9fc76 --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . diff --git a/volume-coupled-flow/fluid-openfoam/constant/fvOptions b/volume-coupled-flow/fluid-openfoam/constant/fvOptions new file mode 100644 index 000000000..d43c960da --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/constant/fvOptions @@ -0,0 +1,42 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvOptions; +} + +codedSource +{ + type vectorCodedSource; + selectionMode cellSet; + cellSet box1; + + fields (U); + name sourceTime; + + codeConstrain //constrain + #{ + return; + #}; + + codeCorrect //correct + #{ + const labelList& cells = this->cells(); + const volVectorField& U_vol = mesh_.lookupObject("U_vol"); + for(auto cell : cells) + { + fld[cell].x() = U_vol[cell].x(); + } + #}; + + codeAddSup // source term + #{ + return; + #}; + + codeAddSupRho + #{ + return; + #}; +} \ No newline at end of file diff --git a/volume-coupled-flow/fluid-openfoam/constant/g b/volume-coupled-flow/fluid-openfoam/constant/g new file mode 100644 index 000000000..ca544e1f1 --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/constant/g @@ -0,0 +1,10 @@ +FoamFile +{ + version 2.0; + format ascii; + class uniformDimensionedVectorField; + object g; +} + +dimensions [0 1 -2 0 0 0 0]; +value (0 -9.81 0); diff --git a/volume-coupled-flow/fluid-openfoam/constant/thermophysicalProperties b/volume-coupled-flow/fluid-openfoam/constant/thermophysicalProperties new file mode 100644 index 000000000..7b93ee2ea --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/constant/thermophysicalProperties @@ -0,0 +1,37 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties; +} + +thermoType +{ + type heRhoThermo; + mixture pureMixture; + transport const; + thermo hConst; + equationOfState perfectGas; + specie specie; + energy sensibleEnthalpy; +} + +mixture +{ + specie + { + molWeight 24.0999; + } + thermodynamics + { + Cp 5000.0; + Hf 0; + } + transport + { + mu 0.0002; + Pr 0.01; + } +} diff --git a/volume-coupled-flow/fluid-openfoam/constant/turbulenceProperties b/volume-coupled-flow/fluid-openfoam/constant/turbulenceProperties new file mode 100644 index 000000000..b75c49530 --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/constant/turbulenceProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object turbulenceProperties; +} + +simulationType laminar; diff --git a/volume-coupled-flow/fluid-openfoam/run.sh b/volume-coupled-flow/fluid-openfoam/run.sh new file mode 100755 index 000000000..75b56f415 --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/run.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh +topoSet + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/volume-coupled-flow/fluid-openfoam/system/blockMeshDict b/volume-coupled-flow/fluid-openfoam/system/blockMeshDict new file mode 100644 index 000000000..baeacdef4 --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/system/blockMeshDict @@ -0,0 +1,87 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +x0 0.; +x1 6.; + +y0 0.; +y1 2.; + +z0 0; +z1 1; + +vertices +( + ($x0 $y0 $z0 ) // 0 + ($x1 $y0 $z0 ) // 1 + ($x0 $y1 $z0 ) // 2 + ($x1 $y1 $z0 ) // 3 + + ($x0 $y0 $z1 ) // 4 + ($x1 $y0 $z1 ) // 5 + ($x0 $y1 $z1 ) // 6 + ($x1 $y1 $z1 ) // 7 +); + + +// Grading +h1 60; +v1 20; + +blocks +( + hex ( 0 1 3 2 4 5 7 6 ) + ($h1 $v1 1 ) + simpleGrading (1 1 1) + +); + +boundary +( + inlet + { + type patch; + faces + ( + ( 0 2 6 4 ) + ); + } + outlet + { + type patch; + faces + ( + ( 1 3 7 5 ) + ); + } + upperWall + { + type wall; + faces + ( + ( 2 3 7 6 ) + ); + } + lowerWall + { + type wall; + faces + ( + ( 0 1 5 4 ) + ); + } + frontAndBack + { + type empty; + faces + ( + ( 0 1 3 2 ) + ( 4 5 7 6 ) + ); + } +); diff --git a/volume-coupled-flow/fluid-openfoam/system/controlDict b/volume-coupled-flow/fluid-openfoam/system/controlDict new file mode 100644 index 000000000..4565b2d4a --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/system/controlDict @@ -0,0 +1,46 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} + +application buoyantPimpleFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 4; + +deltaT 0.005; + +writeControl runTime; + +writeInterval 0.01; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable false; + +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + libs ("libpreciceAdapterFunctionObject.so"); + } +} diff --git a/volume-coupled-flow/fluid-openfoam/system/decomposeParDict b/volume-coupled-flow/fluid-openfoam/system/decomposeParDict new file mode 100644 index 000000000..0d1859e14 --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/system/decomposeParDict @@ -0,0 +1,16 @@ +FoamFile { + version 2.0; + class dictionary; + object decomposeParDict; + format ascii; +} + +numberOfSubdomains 2; + +method simple; + +simpleCoeffs +{ + n (2 1 1); + delta 0.001; +} diff --git a/volume-coupled-flow/fluid-openfoam/system/fvSchemes b/volume-coupled-flow/fluid-openfoam/system/fvSchemes new file mode 100644 index 000000000..fd48cb5b7 --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/system/fvSchemes @@ -0,0 +1,48 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ + default none; + div(phi,U) Gauss upwind; + div(phi,h) Gauss upwind; + div(phi,e) Gauss upwind; + div(phi,k) Gauss upwind; + div(phi,epsilon) Gauss upwind; + div(phi,R) Gauss upwind; + div(phi,K) Gauss linear; + div(phi,Ekp) Gauss linear; + div(R) Gauss linear; + div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/volume-coupled-flow/fluid-openfoam/system/fvSolution b/volume-coupled-flow/fluid-openfoam/system/fvSolution new file mode 100644 index 000000000..e7047fa96 --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/system/fvSolution @@ -0,0 +1,55 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} + +solvers +{ + "rho.*" + { + solver PCG; + preconditioner DIC; + tolerance 0; + relTol 0; + } + + p_rgh + { + solver PCG; + preconditioner DIC; + tolerance 1e-8; + relTol 0.01; + } + + p_rghFinal + { + $p_rgh; + relTol 0; + } + + "(U|h|e|k|epsilon|R)" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-6; + relTol 0.1; + } + + "(U|h|e|k|epsilon|R)Final" + { + $U; + relTol 0; + } +} + +PIMPLE +{ + momentumPredictor yes; + nOuterCorrectors 1; + nCorrectors 2; + nNonOrthogonalCorrectors 0; +} diff --git a/volume-coupled-flow/fluid-openfoam/system/preciceDict b/volume-coupled-flow/fluid-openfoam/system/preciceDict new file mode 100644 index 000000000..93d1204d6 --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/system/preciceDict @@ -0,0 +1,39 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Fluid; + +modules (FF); + +interfaces +{ + Interface1 + { + mesh Fluid-Mesh; + patches (); + cellSets (box1); + locations volumeCenters; + + readData + ( + Velocity + ); + + writeData + ( + ); + }; +}; + +FF +{ + nameU U_vol; +}; diff --git a/volume-coupled-flow/fluid-openfoam/system/topoSetDict b/volume-coupled-flow/fluid-openfoam/system/topoSetDict new file mode 100644 index 000000000..602cd60e7 --- /dev/null +++ b/volume-coupled-flow/fluid-openfoam/system/topoSetDict @@ -0,0 +1,20 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object topoSetDict; +} + +actions +( + { + name box1; + type cellSet; + action new; + source boxToCell; + box (3.0 1.0 0.0) (3.5 1.5 1.0); + } +); + + diff --git a/volume-coupled-flow/images/tutorials-volume-coupled-flow-Ux.png b/volume-coupled-flow/images/tutorials-volume-coupled-flow-Ux.png new file mode 100644 index 000000000..26a5edeaa Binary files /dev/null and b/volume-coupled-flow/images/tutorials-volume-coupled-flow-Ux.png differ diff --git a/volume-coupled-flow/images/tutorials-volume-coupled-flow-config.png b/volume-coupled-flow/images/tutorials-volume-coupled-flow-config.png new file mode 100644 index 000000000..bd9f8d341 Binary files /dev/null and b/volume-coupled-flow/images/tutorials-volume-coupled-flow-config.png differ diff --git a/volume-coupled-flow/images/tutorials-volume-coupled-flow-precice-config.png b/volume-coupled-flow/images/tutorials-volume-coupled-flow-precice-config.png new file mode 100644 index 000000000..e97633408 Binary files /dev/null and b/volume-coupled-flow/images/tutorials-volume-coupled-flow-precice-config.png differ diff --git a/volume-coupled-flow/precice-config.xml b/volume-coupled-flow/precice-config.xml new file mode 100644 index 000000000..eee520b18 --- /dev/null +++ b/volume-coupled-flow/precice-config.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/volume-coupled-flow/source-nutils/clean.sh b/volume-coupled-flow/source-nutils/clean.sh new file mode 100755 index 000000000..6893c1ea5 --- /dev/null +++ b/volume-coupled-flow/source-nutils/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_nutils . diff --git a/volume-coupled-flow/source-nutils/run.sh b/volume-coupled-flow/source-nutils/run.sh new file mode 100755 index 000000000..716fe373b --- /dev/null +++ b/volume-coupled-flow/source-nutils/run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +python3 source.py + +close_log diff --git a/volume-coupled-flow/source-nutils/source.py b/volume-coupled-flow/source-nutils/source.py new file mode 100644 index 000000000..42baabbbf --- /dev/null +++ b/volume-coupled-flow/source-nutils/source.py @@ -0,0 +1,69 @@ +#! /usr/bin/env python3 + + +from nutils import function, mesh, cli, solver, export +import treelog as log +import numpy as np +import precice +from mpi4py import MPI + + +def main(): + + print("Running Nutils") + + timestamp = 0.0 + + # define the Nutils mesh + nx = 60 + ny = 20 + + grid = np.linspace(0, 6, nx + 1), np.linspace(0, 2, ny + 1) + domain, geom = mesh.rectilinear(grid) + domain = domain.withboundary(inflow="left", outflow="right", wall="top,bottom") + + # cloud of Gauss points + uniform_grid = domain.sample("uniform", degree=1) + + # Nutils namespace + ns = function.Namespace(fallback_length=2) + ns.x = geom + + # preCICE setup + participant = precice.Participant("Source-Velocity", "../precice-config.xml", 0, 1) + + # define coupling mesh + mesh_name = "Source-Mesh" + vertices = uniform_grid.eval(ns.x) + vertex_ids = participant.set_mesh_vertices(mesh_name, vertices) + + source_values = np.full((vertices.shape[0], 2), [10.0, 0.0]) + + # coupling data + data_name = "Velocity" + + participant.initialize() + + timestep = 0 + solver_dt = 0.005 + + while participant.is_coupling_ongoing(): + + precice_dt = participant.get_max_time_step_size() + + # potentially adjust non-matching timestep sizes + dt = min(solver_dt, precice_dt) + + participant.write_data(mesh_name, data_name, vertex_ids, source_values) + # do the coupling + participant.advance(dt) + + # advance variables + timestep += 1 + timestamp += dt + + participant.finalize() + + +if __name__ == "__main__": + cli.run(main)