diff --git a/.github/workflows/packaging.yml b/.github/workflows/packaging.yml index 56b9a15b6..81c00649f 100644 --- a/.github/workflows/packaging.yml +++ b/.github/workflows/packaging.yml @@ -1,37 +1,37 @@ -name: packaging - -on: - # Make sure packaging process is not broken - push: - branches: [main, dev] - pull_request: - # Make a package for release - release: - types: [published] - -jobs: - build: - - runs-on: ubuntu-latest - strategy: - max-parallel: 4 - matrix: - python-version: [3.8] - - steps: - - uses: actions/checkout@v1 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip setuptools setuptools_scm twine wheel - - name: Create packages - run: python setup.py sdist bdist_wheel - - name: Run twine check - run: twine check dist/* - - uses: actions/upload-artifact@v2 - with: - name: tox-gh-actions-dist - path: dist +name: packaging + +on: + # Make sure packaging process is not broken + push: + branches: [main, dev] + pull_request: + # Make a package for release + release: + types: [published] + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + max-parallel: 4 + matrix: + python-version: ["3.10"] + + steps: + - uses: actions/checkout@v1 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip setuptools setuptools_scm twine wheel + - name: Create packages + run: python setup.py sdist bdist_wheel + - name: Run twine check + run: twine check dist/* + - uses: actions/upload-artifact@v2 + with: + name: tox-gh-actions-dist + path: dist diff --git a/.github/workflows/tox_checks.yml b/.github/workflows/tox_checks.yml index dfb77c983..4ce7e6d28 100644 --- a/.github/workflows/tox_checks.yml +++ b/.github/workflows/tox_checks.yml @@ -1,52 +1,52 @@ -# NB: this name is used in the status badge -name: tox checks - -on: - push: - branches: - - main - - dev - pull_request: - branches: - - main - - dev - workflow_dispatch: - schedule: - - cron: "0 5 * * 6" # 5:00 UTC every Saturday - -jobs: - lint: - name: ${{ matrix.toxenv }} - runs-on: ubuntu-latest - - strategy: - matrix: - toxenv: - - clean - - check - - docs - - steps: - - name: Git clone - uses: actions/checkout@v2 - - - name: Set up Python ${{ env.default_python || '3.8' }} - uses: actions/setup-python@v2 - with: - python-version: "${{ env.default_python || '3.8' }}" - - - name: Pip cache - uses: actions/cache@v2 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ matrix.toxenv }}-${{ hashFiles('tox.ini', 'setup.py') }} - restore-keys: | - ${{ runner.os }}-pip-${{ matrix.toxenv }}- - ${{ runner.os }}-pip- - - name: Install dependencies - run: | - python -m pip install -U pip - python -m pip install -U setuptools wheel - python -m pip install -U tox - - name: Run ${{ matrix.toxenv }} - run: python -m tox -e ${{ matrix.toxenv }} +# NB: this name is used in the status badge +name: tox checks + +on: + push: + branches: + - main + - dev + pull_request: + branches: + - main + - dev + workflow_dispatch: + schedule: + - cron: "0 5 * * 6" # 5:00 UTC every Saturday + +jobs: + lint: + name: ${{ matrix.toxenv }} + runs-on: ubuntu-latest + + strategy: + matrix: + toxenv: + - clean + - check + - docs + + steps: + - name: Git clone + uses: actions/checkout@v2 + + - name: Set up Python ${{ env.default_python || '3.10' }} + uses: actions/setup-python@v2 + with: + python-version: "${{ env.default_python || '3.10' }}" + + - name: Pip cache + uses: actions/cache@v2 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ matrix.toxenv }}-${{ hashFiles('tox.ini', 'setup.py') }} + restore-keys: | + ${{ runner.os }}-pip-${{ matrix.toxenv }}- + ${{ runner.os }}-pip- + - name: Install dependencies + run: | + python -m pip install -U pip + python -m pip install -U setuptools wheel + python -m pip install -U tox + - name: Run ${{ matrix.toxenv }} + run: python -m tox -e ${{ matrix.toxenv }} diff --git a/.github/workflows/tox_pytest.yml b/.github/workflows/tox_pytest.yml index dade3ebc6..e43b96dd4 100644 --- a/.github/workflows/tox_pytest.yml +++ b/.github/workflows/tox_pytest.yml @@ -1,45 +1,45 @@ -name: tox pytests - -on: - push: - branches: - - main - - dev - pull_request: - branches: - - main - - dev - workflow_dispatch: - schedule: - - cron: "0 5 * * 6" # 5:00 UTC every Saturday - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: [3.7, 3.8] - - steps: - - uses: actions/checkout@v1 - - name: Install xmllint - run: sudo apt install coinor-cbc - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install tox tox-gh-actions coverage coveralls - - name: Test with tox - run: tox - - - name: Check test coverage - run: coverage report -m --fail-under=${{ matrix.vcs == 'bzr' && 84 || 85 }} - - - name: Report to coveralls - run: coveralls - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - COVERALLS_SERVICE_NAME: github +name: tox pytests + +on: + push: + branches: + - main + - dev + pull_request: + branches: + - main + - dev + workflow_dispatch: + schedule: + - cron: "0 5 * * 6" # 5:00 UTC every Saturday + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.7", "3.8", "3.9", "3.10"] + + steps: + - uses: actions/checkout@v1 + - name: Install xmllint + run: sudo apt install coinor-cbc + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install tox tox-gh-actions coverage coveralls + - name: Test with tox + run: tox + + - name: Check test coverage + run: coverage report -m --fail-under=${{ matrix.vcs == 'bzr' && 84 || 85 }} + + - name: Report to coveralls + run: coveralls + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COVERALLS_SERVICE_NAME: github diff --git a/LICENSE b/LICENSE index 928c7b731..67fb8fdb0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2017-2021, oemof developer group - -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. +MIT License + +Copyright (c) 2017-2022, oemof developer group + +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. diff --git a/README.rst b/README.rst index 75361a6c8..5d1e70b7c 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,5 @@ Thermal Engineering Systems in Python ===================================== - TESPy stands for "Thermal Engineering Systems in Python" and provides a powerful simulation toolkit for thermal engineering plants such as power plants, district heating systems or heat pumps. It is an external extension @@ -97,7 +96,6 @@ Key Features Documentation ============= - You can find the full documentation at `readthedocs `_. Use the `project site `_ of readthedocs to @@ -109,7 +107,6 @@ To get the latest news visit and follow our `website `_. Installing TESPy ================ - If you have a working Python3 environment, use pypi to install the latest tespy version: @@ -119,7 +116,7 @@ tespy version: If you want to use the latest features, you might want to install the **developer version**. See section -`Developing TESPy `_ +`Developing TESPy `_ for more information. The developer version is not recommended for productive use. @@ -140,7 +137,6 @@ https://meet.jit.si/tespy_user_meeting. We are looking forward to seeing you! User forum ---------- - We have implemented a `discussion room on GitHub `__ as user forum. If you have issues with setting up your model or any other question @@ -159,7 +155,6 @@ repository. Citation ======== - The scope and functionalities of TESPy have been documented in a paper published in the Journal of Open Source Software with an OpenAccess license. Download the paper from https://doi.org/10.21105/joss.02178. As TESPy is a free @@ -167,10 +162,6 @@ software, we kindly ask that you add a reference to TESPy if you use the software for your scientific work. Please cite the article with the BibTeX citation below. -Additionally, you have the possibility to cite a specific version of TESPy to -make your work reproducible. The source code of every version is published on -zenodo. Find your version here: https://doi.org/10.5281/zenodo.2555866. - BibTeX citation:: @article{Witte2020, @@ -185,9 +176,33 @@ BibTeX citation:: journal = {Journal of Open Source Software} } +Furthermore, a paper on the exergy analysis feature has been published in +the mdpi journal energies. You can download the pdf at +https://doi.org/10.3390/en15114087. If you are using this feature specifically, +you can reference it with the following BibTeX citation: + +BibTeX citation:: + + @article{Witte2022, + doi = {10.3390/en15114087}, + year = {2022}, + publisher = {The Open Journal}, + volume = {15}, + number = {11}, + article-number = {4087}, + issn = {1996-1073}, + author = {Witte, Francesco and Hofmann, Mathias and Meier, Julius and Tuschy, Ilja and Tsatsaronis, George}, + title = {Generic and Open-Source Exergy Analysis—Extending the Simulation Framework TESPy}, + journal = {Energies} + } + + +Additionally, you have the possibility to cite a specific version of TESPy to +make your work reproducible. The source code of every version is published on +zenodo. Find your version here: https://doi.org/10.5281/zenodo.2555866. + License ======= - Copyright (c) 2017-2022 oemof developer group Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/docs/_build/_static/css/custom.css b/docs/_static/css/custom.css similarity index 100% rename from docs/_build/_static/css/custom.css rename to docs/_static/css/custom.css diff --git a/docs/api/_images/SEGS_flowsheet.svg b/docs/_static/images/advanced/exergy/flowsheet.svg similarity index 78% rename from docs/api/_images/SEGS_flowsheet.svg rename to docs/_static/images/advanced/exergy/flowsheet.svg index e2f7df148..812580de7 100644 --- a/docs/api/_images/SEGS_flowsheet.svg +++ b/docs/_static/images/advanced/exergy/flowsheet.svg @@ -1,3366 +1,3366 @@ - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HP1 - HP2 - LP1 - LP2 - LP3 - LP4 - LP5 - G - SolarField - FWT - CON - CP - FWP - EV - RH - FP - - - SH - ECO - DR - PCC - PTCC - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - 15 - 16 - 23 - 24 - 32 - 33 - 34 - 35 - 36 - 37 - 45 - 46 - 47 - 58 - 70 - 71 - 72 - 75 - 76 - 77 - 78 - 79 - - - 62 - 63 - 2 - - - - - - - - - 17 - 18 - 19 - 22 - 26 - 40 - 42 - 44 - 50 - 55 - - - - 61 - LPP1 - LPP2 - LPP3 - HPP1 - HPP2 - 1 - 3 - 4 - 5 - 1 - 7 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 5 - CWP - - M - - - M - - - M - - - M - - - - 2 - - 3 - - - - 4 - - - - - - - - - 60 - - - - - - - 20 - 21 - 25 - 64 - 65 - CT - 38 - 41 - 48 - 51 - 52 - 53 - 59 - - - - - 66 - - - - Fan - - M - - - - 73 - 74 - CWCC - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 27 - 28 - 29 - 30 - 31 - LPsub1 - LPsub2 - LPsub3 - HPsub1 - HPsub2 - 39 - 43 - 49 - 54 - 57 - 56 - - + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HP1 + HP2 + LP1 + LP2 + LP3 + LP4 + LP5 + G + SolarField + FWT + CON + CP + FWP + EV + RH + FP + + + SH + ECO + DR + PCC + PTCC + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 23 + 24 + 32 + 33 + 34 + 35 + 36 + 37 + 45 + 46 + 47 + 58 + 70 + 71 + 72 + 75 + 76 + 77 + 78 + 79 + + + 62 + 63 + 2 + + + + + + + + + 17 + 18 + 19 + 22 + 26 + 40 + 42 + 44 + 50 + 55 + + + + 61 + LPP1 + LPP2 + LPP3 + HPP1 + HPP2 + 1 + 3 + 4 + 5 + 1 + 7 + + 1 + + 2 + + 3 + + 4 + + 5 + + 6 + + 5 + CWP + + M + + + M + + + M + + + M + + + + 2 + + 3 + + + + 4 + + + + + + + + + 60 + + + + + + + 20 + 21 + 25 + 64 + 65 + CT + 38 + 41 + 48 + 51 + 52 + 53 + 59 + + + + + 66 + + + + Fan + + M + + + + 73 + 74 + CWCC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 27 + 28 + 29 + 30 + 31 + LPsub1 + LPsub2 + LPsub3 + HPsub1 + HPsub2 + 39 + 43 + 49 + 54 + 57 + 56 + + diff --git a/docs/_static/images/advanced/exergy/flowsheet_darkmode.svg b/docs/_static/images/advanced/exergy/flowsheet_darkmode.svg new file mode 100644 index 000000000..cef608186 --- /dev/null +++ b/docs/_static/images/advanced/exergy/flowsheet_darkmode.svg @@ -0,0 +1,3125 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HP1 + HP2 + LP1 + LP2 + LP3 + LP4 + LP5 + G + SolarField + FWT + CON + CP + FWP + EV + RH + FP + + + SH + ECO + DR + PCC + PTCC + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 23 + 24 + 32 + 33 + 34 + 35 + 36 + 37 + 45 + 46 + 47 + 58 + 70 + 71 + 72 + 75 + 76 + 77 + 78 + 79 + + + 62 + 63 + 2 + + + + + + + + + 17 + 18 + 19 + 22 + 26 + 40 + 42 + 44 + 50 + 55 + + + + 61 + LPP1 + LPP2 + LPP3 + HPP1 + HPP2 + 1 + 3 + 4 + 5 + 1 + 7 + + 1 + + 2 + + 3 + + 4 + + 5 + + 6 + + 5 + CWP + + M + + + M + + + M + + + M + + + + 2 + + 3 + + + + 4 + + + + + + + + + 60 + + + + + + + 20 + 21 + 25 + 64 + 65 + CT + 38 + 41 + 48 + 51 + 52 + 53 + 59 + + + + + 66 + + + + Fan + + M + + + + 73 + 74 + CWCC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 27 + 28 + 29 + 30 + 31 + LPsub1 + LPsub2 + LPsub3 + HPsub1 + HPsub2 + 39 + 43 + 49 + 54 + 57 + 56 + + diff --git a/docs/_static/images/advanced/exergy/sankey.svg b/docs/_static/images/advanced/exergy/sankey.svg new file mode 100644 index 000000000..c47a033b4 --- /dev/null +++ b/docs/_static/images/advanced/exergy/sankey.svg @@ -0,0 +1,949 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + E_F + + + + + + + SG + + + + + + + E_D + + + + + + + E_P + + + + + + + E_L + + + + + + + FWP + + + + + + + SF + + + + + + + HPT + + + + + + + RH + + + + + + + LPT + + + + + + + total output power + + + + + + + CW + + + + + + + LPP + + + + + + + HPP + + + + + diff --git a/docs/_static/images/basics/district_heating.svg b/docs/_static/images/basics/district_heating.svg new file mode 100644 index 000000000..e987624c9 --- /dev/null +++ b/docs/_static/images/basics/district_heating.svg @@ -0,0 +1,397 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + consumer + control valve + return pipe + feed pipe + feed pump + heat source + 1 + 0 + 2 + 3 + 4 + 5 + 6 + + diff --git a/docs/_static/images/basics/district_heating_darkmode.svg b/docs/_static/images/basics/district_heating_darkmode.svg new file mode 100644 index 000000000..2b5547013 --- /dev/null +++ b/docs/_static/images/basics/district_heating_darkmode.svg @@ -0,0 +1,397 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + consumer + control valve + return pipe + feed pipe + feed pump + heat source + 1 + 0 + 2 + 3 + 4 + 5 + 6 + + diff --git a/docs/_static/images/basics/district_heating_partload.svg b/docs/_static/images/basics/district_heating_partload.svg new file mode 100644 index 000000000..afff99f3f --- /dev/null +++ b/docs/_static/images/basics/district_heating_partload.svg @@ -0,0 +1,2292 @@ + + + + + + + + 2022-08-31T21:27:43.253372 + image/svg+xml + + + Matplotlib v3.4.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/basics/district_heating_partload_darkmode.svg b/docs/_static/images/basics/district_heating_partload_darkmode.svg new file mode 100644 index 000000000..41ed97c15 --- /dev/null +++ b/docs/_static/images/basics/district_heating_partload_darkmode.svg @@ -0,0 +1,2292 @@ + + + + + + + + 2022-09-23T14:39:34.855157 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/basics/gas_turbine.svg b/docs/_static/images/basics/gas_turbine.svg new file mode 100644 index 000000000..e35d59866 --- /dev/null +++ b/docs/_static/images/basics/gas_turbine.svg @@ -0,0 +1,350 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + compressor + combustion chamber + 2 + + turbine + 1 + + + + 3 + 4 + 5 + + + + + + + + + + + G + + diff --git a/docs/_static/images/basics/gas_turbine_darkmode.svg b/docs/_static/images/basics/gas_turbine_darkmode.svg new file mode 100644 index 000000000..c481c420c --- /dev/null +++ b/docs/_static/images/basics/gas_turbine_darkmode.svg @@ -0,0 +1,350 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + compressor + combustion chamber + 2 + + turbine + 1 + + + + 3 + 4 + 5 + + + + + + + + + + + G + + diff --git a/docs/_static/images/basics/gas_turbine_fuel_composition.svg b/docs/_static/images/basics/gas_turbine_fuel_composition.svg new file mode 100644 index 000000000..71fa354b8 --- /dev/null +++ b/docs/_static/images/basics/gas_turbine_fuel_composition.svg @@ -0,0 +1,1135 @@ + + + + + + + + 2022-08-30T21:38:50.684785 + image/svg+xml + + + Matplotlib v3.4.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/basics/gas_turbine_fuel_composition_darkmode.svg b/docs/_static/images/basics/gas_turbine_fuel_composition_darkmode.svg new file mode 100644 index 000000000..3eed407fe --- /dev/null +++ b/docs/_static/images/basics/gas_turbine_fuel_composition_darkmode.svg @@ -0,0 +1,1135 @@ + + + + + + + + 2022-09-23T14:40:19.299228 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/basics/gas_turbine_oxygen.svg b/docs/_static/images/basics/gas_turbine_oxygen.svg new file mode 100644 index 000000000..8bf5af372 --- /dev/null +++ b/docs/_static/images/basics/gas_turbine_oxygen.svg @@ -0,0 +1,1100 @@ + + + + + + + + 2022-08-30T21:38:39.150003 + image/svg+xml + + + Matplotlib v3.4.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/basics/gas_turbine_oxygen_darkmode.svg b/docs/_static/images/basics/gas_turbine_oxygen_darkmode.svg new file mode 100644 index 000000000..2a719b25a --- /dev/null +++ b/docs/_static/images/basics/gas_turbine_oxygen_darkmode.svg @@ -0,0 +1,1100 @@ + + + + + + + + 2022-09-23T14:40:09.282863 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/basics/gas_turbine_parametric.svg b/docs/_static/images/basics/gas_turbine_parametric.svg new file mode 100644 index 000000000..1b5f35181 --- /dev/null +++ b/docs/_static/images/basics/gas_turbine_parametric.svg @@ -0,0 +1,1903 @@ + + + + + + + + 2022-08-30T21:38:36.540618 + image/svg+xml + + + Matplotlib v3.4.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/basics/gas_turbine_parametric_darkmode.svg b/docs/_static/images/basics/gas_turbine_parametric_darkmode.svg new file mode 100644 index 000000000..5c42e5ddd --- /dev/null +++ b/docs/_static/images/basics/gas_turbine_parametric_darkmode.svg @@ -0,0 +1,1903 @@ + + + + + + + + 2022-09-23T14:40:06.522079 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/basics/heat_pump.svg b/docs/_static/images/basics/heat_pump.svg new file mode 100644 index 000000000..d01fd54b3 --- /dev/null +++ b/docs/_static/images/basics/heat_pump.svg @@ -0,0 +1,336 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + compressor + condenser + evaporator + expansion valve + + 0 + 1 + 2 + 3 + 4 + + diff --git a/docs/_static/images/basics/heat_pump_darkmode.svg b/docs/_static/images/basics/heat_pump_darkmode.svg new file mode 100644 index 000000000..e20568e09 --- /dev/null +++ b/docs/_static/images/basics/heat_pump_darkmode.svg @@ -0,0 +1,336 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + compressor + condenser + evaporator + expansion valve + + 0 + 1 + 2 + 3 + 4 + + diff --git a/docs/_static/images/basics/heat_pump_parametric.svg b/docs/_static/images/basics/heat_pump_parametric.svg new file mode 100644 index 000000000..35cf888a6 --- /dev/null +++ b/docs/_static/images/basics/heat_pump_parametric.svg @@ -0,0 +1,1784 @@ + + + + + + + + 2022-09-01T21:28:12.795768 + image/svg+xml + + + Matplotlib v3.4.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/basics/heat_pump_parametric_darkmode.svg b/docs/_static/images/basics/heat_pump_parametric_darkmode.svg new file mode 100644 index 000000000..7c41880c8 --- /dev/null +++ b/docs/_static/images/basics/heat_pump_parametric_darkmode.svg @@ -0,0 +1,1784 @@ + + + + + + + + 2022-09-23T14:40:50.524312 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/basics/modeling_concept.svg b/docs/_static/images/basics/modeling_concept.svg new file mode 100644 index 000000000..5ea1dbdfd --- /dev/null +++ b/docs/_static/images/basics/modeling_concept.svg @@ -0,0 +1,347 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + compressor + condenser + evaporator + expansion valve + 0 + 1 + 2 + 3 + 4 + + + + network + + diff --git a/docs/_static/images/basics/rankine_cycle.svg b/docs/_static/images/basics/rankine_cycle.svg new file mode 100644 index 000000000..0233b15a1 --- /dev/null +++ b/docs/_static/images/basics/rankine_cycle.svg @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + feed pump + condenser + steamgenerator + turbine + + 0 + 1 + 2 + 3 + 4 + + + 11 + 12 + + diff --git a/docs/_static/images/basics/rankine_cycle_darkmode.svg b/docs/_static/images/basics/rankine_cycle_darkmode.svg new file mode 100644 index 000000000..63e123f02 --- /dev/null +++ b/docs/_static/images/basics/rankine_cycle_darkmode.svg @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + feed pump + condenser + steamgenerator + turbine + + 0 + 1 + 2 + 3 + 4 + + + 11 + 12 + + diff --git a/docs/_static/images/basics/rankine_parametric.svg b/docs/_static/images/basics/rankine_parametric.svg new file mode 100644 index 000000000..cd141324f --- /dev/null +++ b/docs/_static/images/basics/rankine_parametric.svg @@ -0,0 +1,2010 @@ + + + + + + + + 2022-08-28T17:24:56.132752 + image/svg+xml + + + Matplotlib v3.4.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/basics/rankine_parametric_darkmode.svg b/docs/_static/images/basics/rankine_parametric_darkmode.svg new file mode 100644 index 000000000..6c88388d5 --- /dev/null +++ b/docs/_static/images/basics/rankine_parametric_darkmode.svg @@ -0,0 +1,1997 @@ + + + + + + + + 2022-09-23T14:40:35.129321 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/basics/rankine_partload.svg b/docs/_static/images/basics/rankine_partload.svg new file mode 100644 index 000000000..f28446f52 --- /dev/null +++ b/docs/_static/images/basics/rankine_partload.svg @@ -0,0 +1,1001 @@ + + + + + + + + 2022-08-28T17:24:59.624666 + image/svg+xml + + + Matplotlib v3.4.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/basics/rankine_partload_darkmode.svg b/docs/_static/images/basics/rankine_partload_darkmode.svg new file mode 100644 index 000000000..55fe9df64 --- /dev/null +++ b/docs/_static/images/basics/rankine_partload_darkmode.svg @@ -0,0 +1,1001 @@ + + + + + + + + 2022-09-23T14:40:39.514183 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/examples/GRC_electrical_power_output.svg b/docs/_static/images/examples/GRC_electrical_power_output.svg new file mode 100644 index 000000000..4ce9b8ca0 --- /dev/null +++ b/docs/_static/images/examples/GRC_electrical_power_output.svg @@ -0,0 +1,2580 @@ + + + + + + + + 2022-09-26T17:55:01.972857 + image/svg+xml + + + Matplotlib v3.6.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/examples/GRC_electrical_power_output_darkmode.svg b/docs/_static/images/examples/GRC_electrical_power_output_darkmode.svg new file mode 100644 index 000000000..34c94d2ec --- /dev/null +++ b/docs/_static/images/examples/GRC_electrical_power_output_darkmode.svg @@ -0,0 +1,1135 @@ + + + + + + + + 2022-09-26T17:55:18.477115 + image/svg+xml + + + Matplotlib v3.6.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/api/_images/logo_tespy_big.svg b/docs/_static/images/logo_tespy_big.svg similarity index 98% rename from docs/api/_images/logo_tespy_big.svg rename to docs/_static/images/logo_tespy_big.svg index c19f8fed1..605ce4f20 100644 --- a/docs/api/_images/logo_tespy_big.svg +++ b/docs/_static/images/logo_tespy_big.svg @@ -12,9 +12,9 @@ height="285" id="svg2" version="1.1" - inkscape:version="1.0.2 (1.0.2+r75+1)" - sodipodi:docname="logo_tespy_big_editable_font.svg" - inkscape:export-filename="/home/leppi/Dokumente/ZNES/Oemof/oemof_logo/done/logo_oemof_vec_inkscape_big_300DPI.png" + inkscape:version="1.0.2-2 (e86c870879, 2021-01-15)" + sodipodi:docname="logo_tespy_big.svg" + inkscape:export-xdpi="300" inkscape:export-ydpi="300"> + inkscape:snap-smooth-nodes="true" + inkscape:snap-grids="false" + inkscape:snap-to-guides="false" + inkscape:snap-page="true"> image/svg+xml - + @@ -379,6 +382,13 @@ id="layer1" transform="translate(0,-767.3622)" style="display:inline"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/api/_images/logo_tespy_big_editable_font.svg b/docs/_static/images/logo_tespy_big_editable_font.svg similarity index 97% rename from docs/api/_images/logo_tespy_big_editable_font.svg rename to docs/_static/images/logo_tespy_big_editable_font.svg index 10f66e93c..0d20e09cc 100644 --- a/docs/api/_images/logo_tespy_big_editable_font.svg +++ b/docs/_static/images/logo_tespy_big_editable_font.svg @@ -1,477 +1,477 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - -   - - ['tɛs.paɪ] - open energy modelling framework - - - - - - - - tespy - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + +   + + ['tɛs.paɪ] + open energy modelling framework + + + + + + + + tespy + + diff --git a/docs/api/_images/logo_tespy_mid.svg b/docs/_static/images/logo_tespy_mid.svg similarity index 97% rename from docs/api/_images/logo_tespy_mid.svg rename to docs/_static/images/logo_tespy_mid.svg index 8cae5d46b..ed5b023ef 100644 --- a/docs/api/_images/logo_tespy_mid.svg +++ b/docs/_static/images/logo_tespy_mid.svg @@ -1,484 +1,484 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/logo_tespy_mid_darkmode.svg b/docs/_static/images/logo_tespy_mid_darkmode.svg new file mode 100644 index 000000000..2f938730c --- /dev/null +++ b/docs/_static/images/logo_tespy_mid_darkmode.svg @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/api/_images/logo_tespy_mid_editable_font.svg b/docs/_static/images/logo_tespy_mid_editable_font.svg similarity index 97% rename from docs/api/_images/logo_tespy_mid_editable_font.svg rename to docs/_static/images/logo_tespy_mid_editable_font.svg index 2c11e569d..5afc4f908 100644 --- a/docs/api/_images/logo_tespy_mid_editable_font.svg +++ b/docs/_static/images/logo_tespy_mid_editable_font.svg @@ -1,436 +1,436 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - -   - - ['tɛs.paɪ] - tespy - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + +   + + ['tɛs.paɪ] + tespy + + + + + + + diff --git a/docs/api/_images/logo_tespy_small.svg b/docs/_static/images/logo_tespy_small.svg similarity index 97% rename from docs/api/_images/logo_tespy_small.svg rename to docs/_static/images/logo_tespy_small.svg index f2f4f9689..77adaedfa 100644 --- a/docs/api/_images/logo_tespy_small.svg +++ b/docs/_static/images/logo_tespy_small.svg @@ -1,397 +1,397 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/docs/api/_images/Ts_diagram_states.svg b/docs/_static/images/modules/Ts_diagram_states.svg similarity index 96% rename from docs/api/_images/Ts_diagram_states.svg rename to docs/_static/images/modules/Ts_diagram_states.svg index d3b76a4e1..c33043f75 100644 --- a/docs/api/_images/Ts_diagram_states.svg +++ b/docs/_static/images/modules/Ts_diagram_states.svg @@ -1,5006 +1,5006 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/modules/characteristics.svg b/docs/_static/images/modules/characteristics.svg new file mode 100644 index 000000000..2d6c844f0 --- /dev/null +++ b/docs/_static/images/modules/characteristics.svg @@ -0,0 +1,266 @@ + + + + + + + + + + 2021-04-28T14:52:48.810737 + image/svg+xml + + + Matplotlib v3.3.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/modules/characteristics_darkmode.svg b/docs/_static/images/modules/characteristics_darkmode.svg new file mode 100644 index 000000000..ac35c4766 --- /dev/null +++ b/docs/_static/images/modules/characteristics_darkmode.svg @@ -0,0 +1,212 @@ + + + + + + + + + + 2021-04-28T14:52:48.810737 + image/svg+xml + + + Matplotlib v3.3.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/modules/connections.svg b/docs/_static/images/modules/connections.svg new file mode 100644 index 000000000..e3332db16 --- /dev/null +++ b/docs/_static/images/modules/connections.svg @@ -0,0 +1,258 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + 5.3 kg/s + 10.2 bar + 213.7 kJ/kg + + + 2.1 kg/s + 1.1 bar + 57.9 kJ/kg + + + diff --git a/docs/_static/images/modules/connections_darkmode.svg b/docs/_static/images/modules/connections_darkmode.svg new file mode 100644 index 000000000..eec924cd7 --- /dev/null +++ b/docs/_static/images/modules/connections_darkmode.svg @@ -0,0 +1,258 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + 5.3 kg/s + 10.2 bar + 213.7 kJ/kg + + + 2.1 kg/s + 1.1 bar + 57.9 kJ/kg + + + diff --git a/docs/_static/images/modules/fluid_properties.svg b/docs/_static/images/modules/fluid_properties.svg new file mode 100644 index 000000000..69541bda1 --- /dev/null +++ b/docs/_static/images/modules/fluid_properties.svg @@ -0,0 +1,1197 @@ + +image/svg+xml0.00135739 +m +3 +kg + + + + +2.0 +m +3 +kg + + + + + + + + + + +225.0 °C +250.0 °C +275.0 °C +300.0 °C +325.0 °C + + + + + + + + + + + +1 +2 +3 +4 +5 +6 + diff --git a/docs/_static/images/modules/fluid_properties_darkmode.svg b/docs/_static/images/modules/fluid_properties_darkmode.svg new file mode 100644 index 000000000..0f3abd832 --- /dev/null +++ b/docs/_static/images/modules/fluid_properties_darkmode.svg @@ -0,0 +1,1044 @@ + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 +2 +3 +4 +5 +6 + diff --git a/docs/api/_images/logph_diagram_states.svg b/docs/_static/images/modules/logph_diagram_states.svg similarity index 96% rename from docs/api/_images/logph_diagram_states.svg rename to docs/_static/images/modules/logph_diagram_states.svg index a8cda0ddd..61125267d 100644 --- a/docs/api/_images/logph_diagram_states.svg +++ b/docs/_static/images/modules/logph_diagram_states.svg @@ -1,5435 +1,5435 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/modules/subsystem_waste_heat_generator.svg b/docs/_static/images/modules/subsystem_waste_heat_generator.svg new file mode 100644 index 000000000..5c06d0533 --- /dev/null +++ b/docs/_static/images/modules/subsystem_waste_heat_generator.svg @@ -0,0 +1,357 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + evaporator + drum + + + + + + + + + + + + + + + + + + + + + + + + superheater + economizer + + diff --git a/docs/_static/images/modules/subsystem_waste_heat_generator_darkmode.svg b/docs/_static/images/modules/subsystem_waste_heat_generator_darkmode.svg new file mode 100644 index 000000000..294f07948 --- /dev/null +++ b/docs/_static/images/modules/subsystem_waste_heat_generator_darkmode.svg @@ -0,0 +1,358 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + evaporator + drum + + + + + + + + + + + + + + + + + + + + + + + + superheater + economizer + + diff --git a/docs/_static/images/modules/ude.svg b/docs/_static/images/modules/ude.svg new file mode 100644 index 000000000..9b0fdf3fe --- /dev/null +++ b/docs/_static/images/modules/ude.svg @@ -0,0 +1,1426 @@ + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/modules/ude_darkmode.svg b/docs/_static/images/modules/ude_darkmode.svg new file mode 100644 index 000000000..d0aa67d39 --- /dev/null +++ b/docs/_static/images/modules/ude_darkmode.svg @@ -0,0 +1,1478 @@ + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/api/_images/dhs.svg b/docs/_static/images/tutorials/district_heating_system/dhs.svg similarity index 97% rename from docs/api/_images/dhs.svg rename to docs/_static/images/tutorials/district_heating_system/dhs.svg index 230fe0ae9..17391b4e5 100644 --- a/docs/api/_images/dhs.svg +++ b/docs/_static/images/tutorials/district_heating_system/dhs.svg @@ -1,745 +1,745 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - heatgeneration - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - industrialarea - housingarea 1 - - - sportscentre - - housingarea 2 - - housingarea 3 - - housingarea 4 - - pipes - - fork - - K1 - K2 - K3 - K4 - - + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + heatgeneration + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + industrialarea + housingarea 1 + + + sportscentre + + housingarea 2 + + housingarea 3 + + housingarea 4 + + pipes + + fork + + K1 + K2 + K3 + K4 + + diff --git a/docs/api/_images/dhs_closed.svg b/docs/_static/images/tutorials/district_heating_system/dhs_closed.svg similarity index 97% rename from docs/api/_images/dhs_closed.svg rename to docs/_static/images/tutorials/district_heating_system/dhs_closed.svg index a507fbb44..fd9fb38d5 100644 --- a/docs/api/_images/dhs_closed.svg +++ b/docs/_static/images/tutorials/district_heating_system/dhs_closed.svg @@ -1,407 +1,407 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - connectingpipes - - - - - - - - - - - - - consumer - - - controlvalve - Subsystem 0 - - - - - - - - - - - - Subsystem 1, 2, ... - - Subsystem n - inlet 1 - outlet 1 - - - - - - + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + connectingpipes + + + + + + + + + + + + + consumer + + + controlvalve + Subsystem 0 + + + + + + + + + + + + Subsystem 1, 2, ... + + Subsystem n + inlet 1 + outlet 1 + + + + + + diff --git a/docs/api/_images/dhs_forks.svg b/docs/_static/images/tutorials/district_heating_system/dhs_forks.svg similarity index 97% rename from docs/api/_images/dhs_forks.svg rename to docs/_static/images/tutorials/district_heating_system/dhs_forks.svg index 087c33a75..b86805c00 100644 --- a/docs/api/_images/dhs_forks.svg +++ b/docs/_static/images/tutorials/district_heating_system/dhs_forks.svg @@ -1,289 +1,289 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - controlvalves - - - - - - - - feed flow - back flow - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + controlvalves + + + + + + + + feed flow + back flow + + + + + + + + diff --git a/docs/api/_images/dhs_open.svg b/docs/_static/images/tutorials/district_heating_system/dhs_open.svg similarity index 97% rename from docs/api/_images/dhs_open.svg rename to docs/_static/images/tutorials/district_heating_system/dhs_open.svg index b8511772f..03f85e0ca 100644 --- a/docs/api/_images/dhs_open.svg +++ b/docs/_static/images/tutorials/district_heating_system/dhs_open.svg @@ -1,437 +1,437 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - connectingpipes - - - - - - - - - - - - - consumer - - - controlvalve - Subsystem 0 - - - - - - - - - - - - - - - Subsystem 1, 2, ... - - Subsystem n - inlet 1 - outlet 1 - outlet 2 - inlet 2 - - - - - + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + connectingpipes + + + + + + + + + + + + + consumer + + + controlvalve + Subsystem 0 + + + + + + + + + + + + + + + Subsystem 1, 2, ... + + Subsystem n + inlet 1 + outlet 1 + outlet 2 + inlet 2 + + + + + diff --git a/docs/api/_images/NH3_logph.svg b/docs/_static/images/tutorials/heat_pump_exergy/NH3_logph.svg similarity index 100% rename from docs/api/_images/NH3_logph.svg rename to docs/_static/images/tutorials/heat_pump_exergy/NH3_logph.svg diff --git a/docs/api/_images/NH3_sankey.svg b/docs/_static/images/tutorials/heat_pump_exergy/NH3_sankey.svg similarity index 100% rename from docs/api/_images/NH3_sankey.svg rename to docs/_static/images/tutorials/heat_pump_exergy/NH3_sankey.svg diff --git a/docs/_static/images/tutorials/heat_pump_exergy/diagram_E_D.svg b/docs/_static/images/tutorials/heat_pump_exergy/diagram_E_D.svg new file mode 100644 index 000000000..b3963ca96 --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_exergy/diagram_E_D.svg @@ -0,0 +1,2195 @@ + + + + + + + + 2022-09-07T09:09:50.566835 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/tutorials/heat_pump_exergy/diagram_E_D_darkmode.svg b/docs/_static/images/tutorials/heat_pump_exergy/diagram_E_D_darkmode.svg new file mode 100644 index 000000000..60de02a98 --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_exergy/diagram_E_D_darkmode.svg @@ -0,0 +1,2195 @@ + + + + + + + + 2022-09-07T09:08:19.587231 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/tutorials/heat_pump_exergy/diagram_cop_eps_Tgeo_Q.svg b/docs/_static/images/tutorials/heat_pump_exergy/diagram_cop_eps_Tgeo_Q.svg new file mode 100644 index 000000000..aef774b73 --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_exergy/diagram_cop_eps_Tgeo_Q.svg @@ -0,0 +1,1926 @@ + + + + + + + + 2022-09-07T09:09:52.284731 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/tutorials/heat_pump_exergy/diagram_cop_eps_Tgeo_Q_darkmode.svg b/docs/_static/images/tutorials/heat_pump_exergy/diagram_cop_eps_Tgeo_Q_darkmode.svg new file mode 100644 index 000000000..3319876b3 --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_exergy/diagram_cop_eps_Tgeo_Q_darkmode.svg @@ -0,0 +1,1926 @@ + + + + + + + + 2022-09-07T09:08:21.461847 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/tutorials/heat_pump_exergy/diagram_cop_eps_Tgeo_Ths.svg b/docs/_static/images/tutorials/heat_pump_exergy/diagram_cop_eps_Tgeo_Ths.svg new file mode 100644 index 000000000..465ff7e19 --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_exergy/diagram_cop_eps_Tgeo_Ths.svg @@ -0,0 +1,2151 @@ + + + + + + + + 2022-09-07T09:09:51.669444 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/tutorials/heat_pump_exergy/diagram_cop_eps_Tgeo_Ths_darkmode.svg b/docs/_static/images/tutorials/heat_pump_exergy/diagram_cop_eps_Tgeo_Ths_darkmode.svg new file mode 100644 index 000000000..92949bff8 --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_exergy/diagram_cop_eps_Tgeo_Ths_darkmode.svg @@ -0,0 +1,2151 @@ + + + + + + + + 2022-09-07T09:08:20.624387 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/tutorials/heat_pump_exergy/diagram_eps_Tamb_Tgeo.svg b/docs/_static/images/tutorials/heat_pump_exergy/diagram_eps_Tamb_Tgeo.svg new file mode 100644 index 000000000..f7026a097 --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_exergy/diagram_eps_Tamb_Tgeo.svg @@ -0,0 +1,1851 @@ + + + + + + + + 2022-09-07T09:09:51.038006 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/tutorials/heat_pump_exergy/diagram_eps_Tamb_Tgeo_darkmode.svg b/docs/_static/images/tutorials/heat_pump_exergy/diagram_eps_Tamb_Tgeo_darkmode.svg new file mode 100644 index 000000000..247ff154e --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_exergy/diagram_eps_Tamb_Tgeo_darkmode.svg @@ -0,0 +1,1851 @@ + + + + + + + + 2022-09-07T09:08:20.041805 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/tutorials/heat_pump_exergy/flowsheet.svg b/docs/_static/images/tutorials/heat_pump_exergy/flowsheet.svg new file mode 100644 index 000000000..cdd27b9cc --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_exergy/flowsheet.svg @@ -0,0 +1,577 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + compressor + condenser + evaporator + expansion valve + 0 + 1 + 2 + 3 + 4 + + + + + + + + + + + + + + consumer + 11 + 12 + 13 + 21 + 22 + 23 + + + ground heat feed flow + ground heatreturn flow + heating systemreturn flow + + diff --git a/docs/_static/images/tutorials/heat_pump_exergy/flowsheet_darkmode.svg b/docs/_static/images/tutorials/heat_pump_exergy/flowsheet_darkmode.svg new file mode 100644 index 000000000..c45b14392 --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_exergy/flowsheet_darkmode.svg @@ -0,0 +1,577 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + compressor + condenser + evaporator + expansion valve + 0 + 1 + 2 + 3 + 4 + + + + + + + + + + + + + + consumer + 11 + 12 + 13 + 21 + 22 + 23 + + + ground heat feed flow + ground heatreturn flow + heating systemreturn flow + + diff --git a/docs/_static/images/tutorials/heat_pump_starting_values/COP_by_wf.svg b/docs/_static/images/tutorials/heat_pump_starting_values/COP_by_wf.svg new file mode 100644 index 000000000..a254ae375 --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_starting_values/COP_by_wf.svg @@ -0,0 +1,1086 @@ + + + + + + + + 2022-09-03T14:25:58.157590 + image/svg+xml + + + Matplotlib v3.4.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/tutorials/heat_pump_starting_values/COP_by_wf_darkmode.svg b/docs/_static/images/tutorials/heat_pump_starting_values/COP_by_wf_darkmode.svg new file mode 100644 index 000000000..ab52d3504 --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_starting_values/COP_by_wf_darkmode.svg @@ -0,0 +1,1086 @@ + + + + + + + + 2022-09-07T08:42:29.766262 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/tutorials/heat_pump_starting_values/flowsheet.svg b/docs/_static/images/tutorials/heat_pump_starting_values/flowsheet.svg new file mode 100644 index 000000000..fb2c4c63d --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_starting_values/flowsheet.svg @@ -0,0 +1,597 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + compressor + condenser + evaporator + expansion valve + 0 + 1 + 2 + 3 + 4 + + + + + + + + + + + + + + heat sink + 11 + 12 + 13 + 20 + 21 + 22 + 23 + + + + + + + + + 5 + 6 + + diff --git a/docs/_static/images/tutorials/heat_pump_starting_values/flowsheet_darkmode.svg b/docs/_static/images/tutorials/heat_pump_starting_values/flowsheet_darkmode.svg new file mode 100644 index 000000000..d2e1ac6fe --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_starting_values/flowsheet_darkmode.svg @@ -0,0 +1,597 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + compressor + condenser + evaporator + expansion valve + 0 + 1 + 2 + 3 + 4 + + + + + + + + + + + + + + heat sink + 11 + 12 + 13 + 20 + 21 + 22 + 23 + + + + + + + + + 5 + 6 + + diff --git a/docs/_static/images/tutorials/heat_pump_starting_values/logph.svg b/docs/_static/images/tutorials/heat_pump_starting_values/logph.svg new file mode 100644 index 000000000..8c150aad5 --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_starting_values/logph.svg @@ -0,0 +1,2571 @@ + + + +image/svg+xml0 +500 +1000 +1500 +2000 +h in +kJkg +10 +0 +10 +1 +10 +2 +p in bar +0.00135739 +m +3 +kg +0.002 +m +3 +kg +0.005 +m +3 +kg +0.01 +m +3 +kg +0.02 +m +3 +kg +0.05 +m +3 +kg +0.1 +m +3 +kg +0.2 +m +3 +kg +0.5 +m +3 +kg +1.0 +m +3 +kg +2.0 +m +3 +kg +-25.0 °C +0.0 °C +25.0 °C +50.0 °C +75.0 °C +100.0 °C +125.0 °C +150.0 °C +175.0 °C +200.0 °C +225.0 °C +250.0 °C +275.0 °C +300.0 °C +325.0 °C +1000.0 +JkgK +1500.0 +JkgK +2000.0 +JkgK +2500.0 +JkgK +3000.0 +JkgK +3500.0 +JkgK +4000.0 +JkgK +4500.0 +JkgK +5000.0 +JkgK +5500.0 +JkgK +6000.0 +JkgK +6500.0 +JkgK +7000.0 +JkgK +7500.0 +JkgK +0.0 - +0.1 - +0.2 - +0.3 - +0.4 - +0.5 - +0.6 - +0.7 - +0.8 - +0.9 - +1.0 - +1 +2 +3 +4 +5 +6 +1 +: Internal Heat Exchanger hot +2 +: Valve +3 +: Evaporator +4 +: Internal Heat Exchanger cold +5 +: Compressor +6 +: Condenser + \ No newline at end of file diff --git a/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet.svg b/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet.svg new file mode 100644 index 000000000..f4d6f2f2a --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet.svg @@ -0,0 +1,873 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + compressor 1 + condenser + evaporator + expansion valve + 1 + 6 + + + + + + + + consumer + 20 + 21 + 22 + + + 23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 2 + 3 + 4 + 5 + 7 + 8 + 9 + 11 + 12 + 14 + 15 + 16 + 17 + 13 + 18 + 19 + superheater + compressor 2 + + + + + diff --git a/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet_darkmode.svg b/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet_darkmode.svg new file mode 100644 index 000000000..55fbcea50 --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet_darkmode.svg @@ -0,0 +1,873 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + compressor 1 + condenser + evaporator + expansion valve + 1 + 6 + + + + + + + + consumer + 20 + 21 + 22 + + + 23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 2 + 3 + 4 + 5 + 7 + 8 + 9 + 11 + 12 + 14 + 15 + 16 + 17 + 13 + 18 + 19 + superheater + compressor 2 + + + + + diff --git a/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet_p1.svg b/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet_p1.svg new file mode 100644 index 000000000..8ac730c88 --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet_p1.svg @@ -0,0 +1,873 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + compressor 1 + condenser + evaporator + expansion valve + 1 + 6 + + + + + + + + consumer + 20 + 21 + 22 + + + 23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 2 + 3 + 4 + 5 + 7 + 8 + 9 + 11 + 12 + 14 + 15 + 16 + 17 + 13 + 18 + 19 + superheater + compressor 2 + + + + + diff --git a/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet_p1_darkmode.svg b/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet_p1_darkmode.svg new file mode 100644 index 000000000..67f553c32 --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet_p1_darkmode.svg @@ -0,0 +1,873 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + compressor 1 + condenser + evaporator + expansion valve + 1 + 6 + + + + + + + + consumer + 20 + 21 + 22 + + + 23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 2 + 3 + 4 + 5 + 7 + 8 + 9 + 11 + 12 + 14 + 15 + 16 + 17 + 13 + 18 + 19 + superheater + compressor 2 + + + + + + diff --git a/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet_p2.svg b/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet_p2.svg new file mode 100644 index 000000000..2fef054ee --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet_p2.svg @@ -0,0 +1,880 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + compressor 1 + condenser + evaporator + expansion valve + 1 + 6 + + + + + + + + consumer + 20 + 21 + 22 + + + 23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 2 + 3 + 4 + 5 + 7 + 8 + 9 + 11 + 12 + 14 + 15 + 16 + 17 + 13 + 18 + 19 + superheater + compressor 2 + + + + + diff --git a/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet_p2_darkmode.svg b/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet_p2_darkmode.svg new file mode 100644 index 000000000..bad3e9888 --- /dev/null +++ b/docs/_static/images/tutorials/heat_pump_stepwise/flowsheet_p2_darkmode.svg @@ -0,0 +1,880 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + compressor 1 + condenser + evaporator + expansion valve + 1 + 6 + + + + + + + + consumer + 20 + 21 + 22 + + + 23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 2 + 3 + 4 + 5 + 7 + 8 + 9 + 11 + 12 + 14 + 15 + 16 + 17 + 13 + 18 + 19 + superheater + compressor 2 + + + + + + diff --git a/docs/_static/images/tutorials/pygmo_optimization/flowsheet.svg b/docs/_static/images/tutorials/pygmo_optimization/flowsheet.svg new file mode 100644 index 000000000..97b4ad2a1 --- /dev/null +++ b/docs/_static/images/tutorials/pygmo_optimization/flowsheet.svg @@ -0,0 +1,693 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + 2 + G + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + + + 41 + 42 + 12 + 13 + 21 + 23 + 24 + 33 + 32 + 31 + + + + + + diff --git a/docs/_static/images/tutorials/pygmo_optimization/flowsheet_darkmode.svg b/docs/_static/images/tutorials/pygmo_optimization/flowsheet_darkmode.svg new file mode 100644 index 000000000..ac0259092 --- /dev/null +++ b/docs/_static/images/tutorials/pygmo_optimization/flowsheet_darkmode.svg @@ -0,0 +1,675 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + 2 + G + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + + + 41 + 42 + 12 + 13 + 21 + 23 + 24 + 33 + 32 + 31 + + + + diff --git a/docs/_static/images/tutorials/pygmo_optimization/pygmo_optimization.svg b/docs/_static/images/tutorials/pygmo_optimization/pygmo_optimization.svg new file mode 100644 index 000000000..7e4f02431 --- /dev/null +++ b/docs/_static/images/tutorials/pygmo_optimization/pygmo_optimization.svg @@ -0,0 +1,4114 @@ + + + + + + + + 2022-09-06T17:50:12.894236 + image/svg+xml + + + Matplotlib v3.4.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/images/tutorials/pygmo_optimization/pygmo_optimization_darkmode.svg b/docs/_static/images/tutorials/pygmo_optimization/pygmo_optimization_darkmode.svg new file mode 100644 index 000000000..024a65beb --- /dev/null +++ b/docs/_static/images/tutorials/pygmo_optimization/pygmo_optimization_darkmode.svg @@ -0,0 +1,4102 @@ + + + + + + + + 2022-09-07T08:57:41.884127 + image/svg+xml + + + Matplotlib v3.5.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_templates/index.html b/docs/_templates/index.html new file mode 100644 index 000000000..e69de29bb diff --git a/docs/analyses/exergy.rst b/docs/advanced/exergy.rst similarity index 90% rename from docs/analyses/exergy.rst rename to docs/advanced/exergy.rst index 8eff1c850..66506ff46 100644 --- a/docs/analyses/exergy.rst +++ b/docs/advanced/exergy.rst @@ -1,8 +1,20 @@ +.. _tespy_advanced_exergy_label: + +~~~~~~~~~~~~~~~ Exergy analysis -=============== +~~~~~~~~~~~~~~~ + +Performing thermodynamic cycle analyses making use of the second law of +thermodynamics provides further process information and uncovers potentials for +improvement in power plant engineering. Therefore, TESPy's analyses module +provides you with an inbuilt and fully automatic exergy analysis. + +We have published a paper with the features described in this section. The +publication is licensed under an open-access license, download the pdf +at https://doi.org/10.3390/en15114087, also see :cite:`Witte2022`. Fundamentals of exergy analysis -------------------------------- +=============================== Energy is a concept of the first law of thermodynamics. It cannot be destroyed. But regarding the design and analysis of thermal systems, the idea that something can be destroyed is useful. According to the second law of @@ -28,7 +40,7 @@ In literature, exergy is defined as follows: :cite:`Bejan1996` Terminology ------------ +=========== The definitions and nomenclature of the exergy analysis in TESPy are based on :cite:`Tsatsaronis2007`. The exergy destruction ratios are described in more detail in :cite:`Bejan1996`. Since the current version of the exergy analysis @@ -102,7 +114,7 @@ potential exergy are neglected and therefore not considered as well. temperature are implemented as well, but are not yet fully tested. Tutorial --------- +======== In this short tutorial, an exergy analysis is carried out for the so called "Solar Energy Generating System" (SEGS). The full python script is available on GitHub in an individual repository: https://github.com/fwitte/SEGS_exergy. @@ -113,7 +125,7 @@ Two other full code examples are to be found at: - Refrigeration machine: https://github.com/fwitte/refrigeration_cycle_exergy SEGS consists of three main systems, the solar field, the steam cycle and the -cooling water system. In the solar field Therminol VP1 is used as heat transfer +cooling water system. In the solar field Therminol VP1 (TVP1) is used as heat transfer fluid. In the steam generator and reheater the TVP1 is cooled down to evaporate and overheat/reheat the water of the steam cycle. The turbine is divided in a high pressure turbine and a low pressure turbine, which are further subdivided @@ -122,9 +134,15 @@ exctracted for preheating. Finally, the main condenser of the steam cycle is connected to an air cooling tower. The figure below shows the topology of the model. -.. figure:: /api/_images/SEGS_flowsheet.svg +.. figure:: /_static/images/advanced/exergy/flowsheet.svg :align: center :alt: Topology of the Solar Energy Generating System (SEGS) + :figclass: only-light + +.. figure:: /_static/images/advanced/exergy/flowsheet_darkmode.svg + :align: center + :alt: Topology of the Solar Energy Generating System (SEGS) + :figclass: only-dark The input data are based on literature :cite:`Kearney1988`, which provides measured data. Some parameters are however taken from a follow-up publication, @@ -133,7 +151,7 @@ pressure turbine's last stage outlet than at its inlet :cite:`Lippke1995`. As mentioned, you can find all data in the respective GitHub repository. TESPy model -^^^^^^^^^^^ +----------- The TESPy model consists of 53 components. The feed water tank serves as mixing preheater, thus can be modeled using a merge. All other components are modeled highlighted in the flowsheet. The preheaters and the main condenser are modeled @@ -174,14 +192,14 @@ these values in the script provided. For the exact values of the component parameters please see in the referenced python script. -Due to the complexity of the plant, the solver sometimes struggles given bad +Due to the complexity of the plant, the solver sometimes struggles when given bad starting values. Therefore, the TESPy model is built in two steps. After solving the initial setup without both of the high pressure preheater subcoolers, the missing connections and components are added in a second step and the model is again solved. Analysis setup -^^^^^^^^^^^^^^ +-------------- After the simulation of the plant, the exergy analysis can be carried out. To perform it, all exergy streams leaving or entering the network's system boundaries have to be defined by the user. These are: @@ -203,18 +221,20 @@ loss. .. code-block:: python power = Bus('total output power') - power.add_comps({'comp': hpt1, 'char': 0.97, 'base': 'component'}, - {'comp': hpt2, 'char': 0.97, 'base': 'component'}, - {'comp': lpt1, 'char': 0.97, 'base': 'component'}, - {'comp': lpt2, 'char': 0.97, 'base': 'component'}, - {'comp': lpt3, 'char': 0.97, 'base': 'component'}, - {'comp': lpt4, 'char': 0.97, 'base': 'component'}, - {'comp': lpt5, 'char': 0.97, 'base': 'component'}, - {'comp': fwp, 'char': 0.95, 'base': 'bus'}, - {'comp': condpump, 'char': 0.95, 'base': 'bus'}, - {'comp': ptpump, 'char': 0.95, 'base': 'bus'}, - {'comp': cwp, 'char': 0.95, 'base': 'bus'}, - {'comp': fan, 'char': 0.95, 'base': 'bus'}) + power.add_comps( + {'comp': hpt1, 'char': 0.97, 'base': 'component'}, + {'comp': hpt2, 'char': 0.97, 'base': 'component'}, + {'comp': lpt1, 'char': 0.97, 'base': 'component'}, + {'comp': lpt2, 'char': 0.97, 'base': 'component'}, + {'comp': lpt3, 'char': 0.97, 'base': 'component'}, + {'comp': lpt4, 'char': 0.97, 'base': 'component'}, + {'comp': lpt5, 'char': 0.97, 'base': 'component'}, + {'comp': fwp, 'char': 0.95, 'base': 'bus'}, + {'comp': condpump, 'char': 0.95, 'base': 'bus'}, + {'comp': ptpump, 'char': 0.95, 'base': 'bus'}, + {'comp': cwp, 'char': 0.95, 'base': 'bus'}, + {'comp': fan, 'char': 0.95, 'base': 'bus'} + ) heat_input_bus = Bus('heat input') heat_input_bus.add_comps({'comp': pt, 'base': 'bus'}) @@ -264,7 +284,7 @@ state temperature value to 15 °C. :code:`ExergyAnalysis` class needs to be defined. Checking consistency -^^^^^^^^^^^^^^^^^^^^ +-------------------- An automatic check of consistency is performed by the analysis. The sum of all exergy destruction values of the network's components and the exergy destruction on the respective busses is calculated. On top of that, fuel and @@ -317,7 +337,7 @@ deselect the tables, e.g. by passing :code:`groups=False` to the method call. ean.print_results(groups=False, connections=False) For the component related tables, i.e. busses, components, aggregation and -groups, the data are sorted descending regarding the exergy destruction value +groups, the data are sorted in descending order for the given exergy destruction value of the individual entry. The component data contain fuel exergy, product exergy and exergy destruction values related to the component itself ignoring losses that might occur on the busses, for example, mechanical or electrical @@ -340,7 +360,7 @@ exergy, while the product is the electrical energy. in the form of a Grassmann diagram. Accessing the data -^^^^^^^^^^^^^^^^^^ +------------------ The underlying data for the tabular printouts are stored in `pandas DataFrames `_. Therefore, you can easily access and process these data. To access these use @@ -359,7 +379,7 @@ Lastly, the analysis also provides an input data generator for plotly's `sankey diagram `_. Plotting -^^^^^^^^ +-------- To use the plotly library, you'll need to install it first. Please check the respective documentation on plotly's documentation. Generating a sankey diagram is then easily done: @@ -375,11 +395,13 @@ diagram is then easily done: node={ 'label': nodes, 'pad':11, - 'color': 'orange'}, - link=links)) + 'color': 'orange' + }, + link=links + )) fig.show() -.. figure:: /api/_images/SEGS_sankey.png +.. figure:: /_static/images/advanced/exergy/sankey.svg :align: center :alt: Sankey diagram of the Soler Energy Generating System (SEGS) @@ -442,7 +464,7 @@ handle the data by yourself. Conclusion ----------- +========== An additional example is available in the API documentation of the :py:class:`tespy.tools.analyses.ExergyAnalysis` class. Full testing of exergy analysis at temperature levels below the ambient temperature will be diff --git a/docs/advanced/optimization.rst b/docs/advanced/optimization.rst new file mode 100644 index 000000000..dfee0e25d --- /dev/null +++ b/docs/advanced/optimization.rst @@ -0,0 +1,4 @@ +.. _tespy_advanced_optimization_label: + +Optimization with pygmo +======================= diff --git a/docs/api.rst b/docs/api.rst index 1c6e253b9..6a2d34f7f 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1,16 +1,16 @@ -~~~~~~~~~~~~~~~~~ -API Documentation -~~~~~~~~~~~~~~~~~ - -All component and connection property equations derive from balance equations -for fluid composition, mass flow and energy in regarding thermal as well as -hydraulic state and thermodynamic fluid property equations respectively. -Standard literature is for example :cite:`Baehr2016,Epple2012,Bswirth2012` -(german) :cite:`Epple2017` (english). Equations and properties from other -sources are cited individually. - -.. toctree:: - :maxdepth: 1 - :glob: - - api/* +~~~~~~~~~~~~~~~~~ +API Documentation +~~~~~~~~~~~~~~~~~ + +All component and connection property equations derive from balance equations +for fluid composition, mass flow and energy in regarding thermal as well as +hydraulic state and thermodynamic fluid property equations respectively. +Standard literature is for example :cite:`Baehr2016,Epple2012,Bswirth2012` +(german) :cite:`Epple2017` (english). Equations and properties from other +sources are cited individually. + +.. toctree:: + :maxdepth: 1 + :glob: + + api/* diff --git a/docs/api/_images/CombustionChamber.svg b/docs/api/_images/CombustionChamber.svg index a63c5261a..83e9fc25e 100644 --- a/docs/api/_images/CombustionChamber.svg +++ b/docs/api/_images/CombustionChamber.svg @@ -1,144 +1,222 @@ + viewBox="0 0 94.999975 68.50001" + height="68.500008mm" + width="94.999969mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + + + + + + + + + inkscape:pagecheckerboard="0" + inkscape:snap-intersection-paths="true" + inkscape:bbox-paths="false" + inkscape:lockguides="true"> + originx="-47.499986" + originy="-2.4999965" /> - + id="metadata5"> image/svg+xml - - + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-47.49996,-2.4999995)"> + + + + in2 + inkscape:export-ydpi="1012" + inkscape:export-xdpi="1012" + xml:space="preserve" + style="font-size:9.8778px;line-height:1.25;font-family:sans-serif;stroke-width:0.529166;stroke-linecap:round;stroke-linejoin:round" + x="98.310982" + y="22.764622" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-3-6-3">in2 out1 + inkscape:export-ydpi="1012" + inkscape:export-xdpi="1012" + xml:space="preserve" + style="font-size:9.8778px;line-height:1.25;font-family:sans-serif;stroke-width:0.529166;stroke-linecap:round;stroke-linejoin:round" + x="58.285896" + y="42.764622" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-3-6-3-3">in1 - in1 - + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 94.999959,11.999998 V 34.499996" + id="path984-0-9-9-9-7-6-60" /> + + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 56.999959,49.999998 H 79.999953" + id="path984-0-9-9-9-7-6-8" /> + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 52.999959,45.999998 4,4 -4,4 z" + id="path4652-12-9-60-5-4-2" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + out1 + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 109.99999,49.999998 h 22.99996" + id="path984-0-9-9-9-7-6-8-6" /> + sodipodi:nodetypes="cccc" /> diff --git a/docs/api/_images/CombustionChamber_darkmode.svg b/docs/api/_images/CombustionChamber_darkmode.svg new file mode 100644 index 000000000..1ff71f737 --- /dev/null +++ b/docs/api/_images/CombustionChamber_darkmode.svg @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + in2 + in1 + + + + + out1 + + + + diff --git a/docs/api/_images/CombustionEngine.svg b/docs/api/_images/CombustionEngine.svg index 237edf947..519952211 100644 --- a/docs/api/_images/CombustionEngine.svg +++ b/docs/api/_images/CombustionEngine.svg @@ -1,235 +1,358 @@ + viewBox="0 0 93.499991 64.762918" + height="64.762917mm" + width="93.499985mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + + + + + + + + + inkscape:pagecheckerboard="0" + inkscape:snap-intersection-paths="true" + inkscape:bbox-paths="false" + inkscape:lockguides="true"> + originx="-67.750004" + originy="-32.607178" /> - + id="metadata5"> image/svg+xml - + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-67.749985,-32.607182)"> in4 + inkscape:export-ydpi="1012" + inkscape:export-xdpi="1012" + xml:space="preserve" + style="font-size:4.9389px;line-height:1.25;font-family:sans-serif;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round" + x="96.642952" + y="91.382317" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5">in1 out3 + inkscape:export-ydpi="1012" + inkscape:export-xdpi="1012" + xml:space="preserve" + style="font-size:4.9389px;line-height:1.25;font-family:sans-serif;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round" + x="104.94641" + y="91.240036" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-5">out1 in3 - + inkscape:export-ydpi="1012" + inkscape:export-xdpi="1012" + xml:space="preserve" + style="font-size:4.9389px;line-height:1.25;font-family:sans-serif;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round" + x="116.65549" + y="91.382317" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-9">in2 + in3 + in4 + out2 + out3 + sodipodi:nodetypes="ccccc" + style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 99.999984,84.000005 v -19 l 4.999996,5 5,-5 v 19" + id="path984-0-9-9-9-7-6-8-3" /> + sodipodi:nodetypes="ccccc" + style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 119.99998,84.000005 v -19 l 5,5 5,-5 v 19" + id="path984-0-9-9-9-7-6-8-3-6" /> + + + + + + + + + + + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> - - - out2 - out1 - in2 - in1 - + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 89.999984,39.999993 V 75.000002 H 139.99998 V 39.999993 Z" + id="path1057-2-7-1-9" + sodipodi:nodetypes="ccccc" /> diff --git a/docs/api/_images/CombustionEngine_darkmode.svg b/docs/api/_images/CombustionEngine_darkmode.svg new file mode 100644 index 000000000..a8e1b2f0a --- /dev/null +++ b/docs/api/_images/CombustionEngine_darkmode.svg @@ -0,0 +1,358 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + in1 + out1 + in2 + in3 + in4 + out2 + out3 + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/api/_images/Compressor.svg b/docs/api/_images/Compressor.svg index 106db365a..328c86ad2 100644 --- a/docs/api/_images/Compressor.svg +++ b/docs/api/_images/Compressor.svg @@ -1,100 +1,189 @@ + viewBox="0 0 104.99999 42.941693" + height="42.941692mm" + width="104.99998mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + + + + + + + + - + inkscape:window-y="27" + inkscape:window-x="72" + inkscape:window-height="1136" + inkscape:window-width="1848" + inkscape:snap-to-guides="false" + inkscape:guide-bbox="true" + showguides="true" + inkscape:bbox-nodes="false" + inkscape:snap-grids="true" + inkscape:snap-bbox="true" + inkscape:snap-nodes="true" + inkscape:object-paths="true" + inkscape:snap-center="true" + showgrid="true" + inkscape:document-rotation="0" + inkscape:current-layer="layer1" + inkscape:document-units="mm" + inkscape:cy="218.5" + inkscape:cx="150" + inkscape:zoom="1" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + fit-margin-top="5" + fit-margin-left="5" + fit-margin-right="5" + fit-margin-bottom="5" + inkscape:pagecheckerboard="0" + inkscape:snap-intersection-paths="true" + inkscape:bbox-paths="false" + inkscape:lockguides="true"> + + + id="metadata5"> image/svg+xml - - + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-44.999995,-23.52916)"> + + + + in1 + inkscape:export-ydpi="1012" + inkscape:export-xdpi="1012" + xml:space="preserve" + style="font-size:9.8778px;line-height:1.25;font-family:sans-serif;stroke-width:0.529166;stroke-linecap:round;stroke-linejoin:round" + x="55.785919" + y="37.764626" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5">in1 out1 - + inkscape:export-ydpi="1012" + inkscape:export-xdpi="1012" + xml:space="preserve" + style="font-size:9.8778px;line-height:1.25;font-family:sans-serif;stroke-width:0.529166;stroke-linecap:round;stroke-linejoin:round" + x="122.39284" + y="37.480064" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-6">out1 + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 54.49999,45.000004 H 82.499984" + id="path984-0-9-9-9-7-6-8" /> + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 140.5,40.999992 4,4 -4,4 z" + id="path4652-12-9-60-5-4-2" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 50.499994,40.999992 4,4 -4,4 z" + id="path4652-12-9-60-5-4-2-3" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> diff --git a/docs/api/_images/Compressor_darkmode.svg b/docs/api/_images/Compressor_darkmode.svg new file mode 100644 index 000000000..6a52860bc --- /dev/null +++ b/docs/api/_images/Compressor_darkmode.svg @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + in1 + out1 + + + + + diff --git a/docs/api/_images/Condenser.svg b/docs/api/_images/Condenser.svg index 4b98a8454..f5e4981f1 100644 --- a/docs/api/_images/Condenser.svg +++ b/docs/api/_images/Condenser.svg @@ -1,138 +1,236 @@ + viewBox="0 0 78.49998 95.46657" + height="95.466568mm" + width="78.499977mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + + + + + + + + + inkscape:window-y="27" + inkscape:window-x="72" + inkscape:window-height="1136" + inkscape:window-width="1848" + inkscape:snap-to-guides="false" + inkscape:guide-bbox="true" + showguides="true" + inkscape:bbox-nodes="true" + inkscape:snap-grids="true" + inkscape:snap-bbox="true" + inkscape:snap-nodes="true" + inkscape:object-paths="true" + inkscape:snap-center="true" + showgrid="true" + inkscape:document-rotation="0" + inkscape:current-layer="layer1" + inkscape:document-units="mm" + inkscape:cy="166.25" + inkscape:cx="163.5" + inkscape:zoom="2" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + fit-margin-top="5" + fit-margin-left="5" + fit-margin-right="5" + fit-margin-bottom="5" + inkscape:pagecheckerboard="0" + inkscape:snap-intersection-paths="true" + inkscape:bbox-paths="false" + inkscape:snap-others="true"> + originx="-139.87502" + originy="-37.150059" /> - + id="metadata5"> image/svg+xml - - out2 + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-139.875,-37.150058)"> + + + + + - - + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 160.875,47.116657 V 65.116655" + id="path984-0-9-9-9-7-6-6" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 160.875,123.11665 V 104.6501" + id="path984-0-9-9-9-7-6-9" /> in1 - out1 - + inkscape:export-ydpi="1012" + inkscape:export-xdpi="1012" + xml:space="preserve" + style="font-size:9.8778px;line-height:1.25;font-family:sans-serif;stroke-width:0.529166;stroke-linecap:round;stroke-linejoin:round" + x="144.1609" + y="57.881287" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-3">in1 in2 + inkscape:export-ydpi="1012" + inkscape:export-xdpi="1012" + xml:space="preserve" + style="font-size:9.8778px;line-height:1.25;font-family:sans-serif;stroke-width:0.529166;stroke-linecap:round;stroke-linejoin:round" + x="170.76784" + y="117.59671" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-3-3">out1 + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 212.87498,84.650055 -4,4 4,4 z" + id="path4652-12-9-60-5-4-2-0" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 156.87498,42.650057 4,4 4,-4 z" + id="path4652-12-9-60-5-4-2-0-5" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + + + in2 + out2 diff --git a/docs/api/_images/Condenser_darkmode.svg b/docs/api/_images/Condenser_darkmode.svg new file mode 100644 index 000000000..a82df3413 --- /dev/null +++ b/docs/api/_images/Condenser_darkmode.svg @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + in1 + out1 + + + + + in2 + out2 + + diff --git a/docs/api/_images/DropletSeparator.svg b/docs/api/_images/DropletSeparator.svg index a94c9fbae..b41a4eceb 100644 --- a/docs/api/_images/DropletSeparator.svg +++ b/docs/api/_images/DropletSeparator.svg @@ -1,136 +1,213 @@ + viewBox="0 0 69.223438 95.000002" + height="95mm" + width="69.223434mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + + + + + + + + + inkscape:pagecheckerboard="0" + inkscape:snap-intersection-paths="true" + inkscape:bbox-paths="false"> + originx="-196.83243" + originy="-62.500002" /> - + id="metadata5"> image/svg+xml - - - in1 - out1 + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-196.83239,-62.500007)"> + + + + + + sodipodi:nodetypes="ccc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 224.55586,116.00001 18.99988,12.00002 13.0001,-2e-5" + id="path984-0-9-9-9-7-6-0-1" /> + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 218.55586,94.529191 V 72.000005" + id="path984-0-9-9-9-7-0-1-5-0-8-4-7-7-8" /> out2 + inkscape:export-ydpi="1012" + inkscape:export-xdpi="1012" + xml:space="preserve" + style="font-size:9.8778px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke-width:0.529166;stroke-linecap:round;stroke-linejoin:round" + x="227.50845" + y="83.53054" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-3-4-9-5">out1 + out2 + in1 + + sodipodi:nodetypes="cccc" /> + sodipodi:nodetypes="cccc" /> diff --git a/docs/api/_images/DropletSeparator_darkmode.svg b/docs/api/_images/DropletSeparator_darkmode.svg new file mode 100644 index 000000000..151e49f47 --- /dev/null +++ b/docs/api/_images/DropletSeparator_darkmode.svg @@ -0,0 +1,214 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + out1 + out2 + in1 + + + + + diff --git a/docs/api/_images/Drum.svg b/docs/api/_images/Drum.svg index 3ab3959d2..d395db3a4 100644 --- a/docs/api/_images/Drum.svg +++ b/docs/api/_images/Drum.svg @@ -1,151 +1,240 @@ + viewBox="0 0 92.037091 94.999971" + height="94.999969mm" + width="92.037086mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + + + + + + + + + inkscape:pagecheckerboard="0" + inkscape:snap-intersection-paths="true" + inkscape:bbox-paths="false"> + originx="-184.7222" + originy="-62.500004" /> - + id="metadata5"> image/svg+xml - - - in1 - out2 + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-184.72217,-62.500008)"> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 219.25922,148.00002 v -22.5292" + id="path984-0-9-9-9-7-6-9" /> + + + + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 203.78832,110.00002 234.73014,110" + id="path984-0-9-9-9-7-0-1-5-0-8-4-7-7-5-6-6" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 225.25924,104.00002 18.99988,-12.000016 23.0001,2e-5" + id="path984-0-9-9-9-7-6-0" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 225.25924,116.00002 18.99988,12.00002 23.0001,-2e-5" + id="path984-0-9-9-9-7-6-0-1" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 219.25924,94.529204 V 72.000018" + id="path984-0-9-9-9-7-0-1-5-0-8-4-7-7-8" /> + out1 + in2 out1 + style="font-size:9.8778px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke-width:0.529166;stroke-linecap:round;stroke-linejoin:round" + x="201.60489" + y="143.75243" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-3-4-9-8-56">in1 in2 + style="font-size:9.8778px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke-width:0.529166;stroke-linecap:round;stroke-linejoin:round" + x="189.17715" + y="82.48008" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-3-4-9-58">out2 + + + + diff --git a/docs/api/_images/Drum_darkmode.svg b/docs/api/_images/Drum_darkmode.svg new file mode 100644 index 000000000..b1399c532 --- /dev/null +++ b/docs/api/_images/Drum_darkmode.svg @@ -0,0 +1,241 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + out1 + in2 + in1 + out2 + + + + + + diff --git a/docs/api/_images/FuelCell.svg b/docs/api/_images/FuelCell.svg new file mode 100644 index 000000000..12b2d6dcd --- /dev/null +++ b/docs/api/_images/FuelCell.svg @@ -0,0 +1,315 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + out2 + out1 + H2 + in1 + in2 + O2 + H2O + in3 + + + + + + + + + + + + + diff --git a/docs/api/_images/FuelCell_darkmode.svg b/docs/api/_images/FuelCell_darkmode.svg new file mode 100644 index 000000000..53394fb33 --- /dev/null +++ b/docs/api/_images/FuelCell_darkmode.svg @@ -0,0 +1,315 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + out2 + out1 + H2 + in1 + in2 + O2 + H2O + in3 + + + + + + + + + + + + + diff --git a/docs/api/_images/HeatExchanger.svg b/docs/api/_images/HeatExchanger.svg index 0d4a7b439..1d3ec7e5a 100644 --- a/docs/api/_images/HeatExchanger.svg +++ b/docs/api/_images/HeatExchanger.svg @@ -1,146 +1,241 @@ + viewBox="0 0 115.00002 94.999971" + height="94.999969mm" + width="115.00002mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + + + + + + + + + fit-margin-bottom="5" + inkscape:pagecheckerboard="0" + inkscape:snap-intersection-paths="true" + inkscape:bbox-paths="false"> + originx="-167.5" + originy="-32.500003" /> - + id="metadata5"> image/svg+xml - - in2 - out2 + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-167.49997,-32.500008)"> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 225.00001,42.000019 -2e-5,23.000152" + id="path984-0-9-9-9-7-6" /> + + + - + inkscape:connector-curvature="0" + style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 210.00003,65.000005 v 30.00002 h 30.00004 v -30.00002 z" + id="path1057-2-7-1-9" + sodipodi:nodetypes="ccccc" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 240.00007,80.000019 h 32.9999" + id="path984-0-9-9-9-7-6-4" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 224.99999,118.00002 V 95.000025" + id="path984-0-9-9-9-7-0-1-5-0-8-4-7-7-8" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 210.00003,80.000019 H 176.99997" + id="path984-0-9-9-9-7-6-4-1" /> + in1 + out1 in1 + style="font-size:9.8778px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke-width:0.529166;stroke-linecap:round;stroke-linejoin:round" + x="233.95258" + y="113.53056" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-3-4-7-3-7">out2 out1 + style="font-size:9.8778px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke-width:0.529166;stroke-linecap:round;stroke-linejoin:round" + x="227.38422" + y="53.75243" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-3-4-7-3-7-3">in2 + + + + diff --git a/docs/api/_images/HeatExchanger_darkmode.svg b/docs/api/_images/HeatExchanger_darkmode.svg new file mode 100644 index 000000000..8a8a56a12 --- /dev/null +++ b/docs/api/_images/HeatExchanger_darkmode.svg @@ -0,0 +1,241 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + in1 + out1 + out2 + in2 + + + + + + diff --git a/docs/api/_images/Merge.svg b/docs/api/_images/Merge.svg index f88a7258c..e75c56302 100644 --- a/docs/api/_images/Merge.svg +++ b/docs/api/_images/Merge.svg @@ -1,198 +1,310 @@ - - - + viewBox="0 0 51.161181 48.620084" + height="48.620083mm" + width="51.161179mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + id="defs2"> + transform="scale(-0.4)" + style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt" + d="M 5.77,0 -2.88,5 V -5 Z" + id="path9033" /> + + + + transform="matrix(0.8,0,0,0.8,10,0)" + style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt" + d="M 0,0 5,-5 -12.5,0 5,5 Z" + id="path8897" /> + + + + + + + + + + id="metadata5"> image/svg+xml - + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-153.74997,7.3700866)"> + + in2 + style="font-size:4.9389px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round" + x="159.9464" + y="16.240038" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-3-4-0">out1 in1 - - - - - + style="font-size:4.9389px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round" + x="171.64293" + y="1.3823198" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-3-4-0-3">in1 out1 + style="font-size:4.9389px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round" + x="186.65547" + y="6.3823199" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-3-4-0-3-2">in2 inn - + style="font-size:4.9389px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round" + x="193.62334" + y="21.359591" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-3-4-0-3-2-6">in3 in3 + style="font-size:4.9389px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round" + x="166.63509" + y="31.38232" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-3-4-0-3-2-2">inn + + + + + + + + + - diff --git a/docs/api/_images/Merge_darkmode.svg b/docs/api/_images/Merge_darkmode.svg new file mode 100644 index 000000000..deb785f7c --- /dev/null +++ b/docs/api/_images/Merge_darkmode.svg @@ -0,0 +1,310 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + out1 + in1 + in2 + in3 + inn + + + + + + + + + + + diff --git a/docs/api/_images/NH3_sankey.html b/docs/api/_images/NH3_sankey.html deleted file mode 100644 index 88c2f26f3..000000000 --- a/docs/api/_images/NH3_sankey.html +++ /dev/null @@ -1,67 +0,0 @@ - - - -
-
- - \ No newline at end of file diff --git a/docs/api/_images/Node.svg b/docs/api/_images/Node.svg deleted file mode 100644 index 7c51228a5..000000000 --- a/docs/api/_images/Node.svg +++ /dev/null @@ -1,293 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - in2 - in1 - - - - - outn - inn - in3 - - - - out2 - out1 - - out3 - - - - - diff --git a/docs/api/_images/ParabolicTrough.svg b/docs/api/_images/ParabolicTrough.svg index 7ca971585..7750d68a5 100644 --- a/docs/api/_images/ParabolicTrough.svg +++ b/docs/api/_images/ParabolicTrough.svg @@ -1,921 +1,193 @@ - - + viewBox="0 0 87.499987 31.987609" + height="31.987608mm" + width="87.499985mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + id="defs2"> + + + + + + + fit-margin-bottom="5" + inkscape:pagecheckerboard="0" + inkscape:snap-intersection-paths="true" + inkscape:bbox-paths="false" + inkscape:snap-object-midpoints="true"> + originx="-93.750002" + originy="-59.500001" /> + id="metadata5"> image/svg+xml - + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-93.749987,-59.500006)"> + sodipodi:nodetypes="cccc" /> + sodipodi:nodetypes="cccc" /> in1 + style="stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round" + y="71.382317" + x="101.64295" + id="tspan1023-6-9-1-6-2-8-3-2-0-7-6" + sodipodi:role="line">in1 out1 + style="stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round" + y="71.240028" + x="164.94641" + id="tspan1023-6-9-1-6-2-8-3-2-0-7-6-5" + sodipodi:role="line">out1 + + + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> diff --git a/docs/api/_images/ParabolicTrough_darkmode.svg b/docs/api/_images/ParabolicTrough_darkmode.svg new file mode 100644 index 000000000..363e96515 --- /dev/null +++ b/docs/api/_images/ParabolicTrough_darkmode.svg @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + in1 + out1 + + + + + + + + + diff --git a/docs/api/_images/Pipe.svg b/docs/api/_images/Pipe.svg index 16e9bbfdc..f0db97821 100644 --- a/docs/api/_images/Pipe.svg +++ b/docs/api/_images/Pipe.svg @@ -1,106 +1,175 @@ + viewBox="0 0 72.499994 20.370091" + height="20.37009mm" + width="72.499992mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + + + + + + + + + inkscape:pagecheckerboard="0" + inkscape:snap-intersection-paths="true" + inkscape:bbox-paths="false" + inkscape:snap-object-midpoints="true"> + originx="-93.75" + originy="-87.629906" /> - + id="metadata5"> image/svg+xml - + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-93.74998,-87.62991)"> + + + inin1 + id="tspan2432">1 outout1 + id="tspan2432-5">1 + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 158.99998,98.000007 2,2.000003 -2,2 z" + id="path4652-12-9-60-5-4-2-2" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> - + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 98.999979,98.000007 2.000001,2.000003 -2.000001,2 z" + id="path4652-12-9-60-5-4-2-2-3" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> diff --git a/docs/api/_images/Pipe_darkmode.svg b/docs/api/_images/Pipe_darkmode.svg new file mode 100644 index 000000000..de9aba628 --- /dev/null +++ b/docs/api/_images/Pipe_darkmode.svg @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + in1 + out1 + + + + diff --git a/docs/api/_images/Pump.svg b/docs/api/_images/Pump.svg index e35ce3e5d..4aa38c567 100644 --- a/docs/api/_images/Pump.svg +++ b/docs/api/_images/Pump.svg @@ -1,100 +1,182 @@ + viewBox="0 0 94.999982 37.738267" + height="37.738266mm" + width="94.999977mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + + + + + + + + - + inkscape:window-y="27" + inkscape:window-x="72" + inkscape:window-height="1136" + inkscape:window-width="1848" + inkscape:snap-to-guides="false" + inkscape:guide-bbox="true" + showguides="true" + inkscape:bbox-nodes="false" + inkscape:snap-grids="true" + inkscape:snap-bbox="true" + inkscape:snap-nodes="true" + inkscape:object-paths="true" + inkscape:snap-center="true" + showgrid="true" + inkscape:document-rotation="0" + inkscape:current-layer="layer1" + inkscape:document-units="mm" + inkscape:cy="78.135299" + inkscape:cx="77.781746" + inkscape:zoom="1.4142136" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + fit-margin-top="5" + fit-margin-left="5" + fit-margin-right="5" + fit-margin-bottom="5" + inkscape:pagecheckerboard="0" + inkscape:snap-intersection-paths="true" + inkscape:bbox-paths="false"> + + + id="metadata5"> image/svg+xml - - + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-97.499981,-0.69534715)"> + + style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 145.00012,32.435493 12,-11.99998 -12,-11.9999998" + id="path4585-2-7-1" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" /> - in1 - out1 + style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 102.99998,24.435533 4,-4 -4,-4 z" + id="path4652-12-9-60-5-4-2-3" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 182.99998,24.435533 4,-4 -4,-4 z" + id="path4652-12-9-60-5-4-2-3-5" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 182.99998,20.435533 H 156.99812" + id="path984-0-9-9-9-7-0-1-5-0-8-4-7-7-8-8" /> + + in1 + out1 diff --git a/docs/api/_images/Pump_darkmode.svg b/docs/api/_images/Pump_darkmode.svg new file mode 100644 index 000000000..bacf3d1a6 --- /dev/null +++ b/docs/api/_images/Pump_darkmode.svg @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + in1 + out1 + + diff --git a/docs/api/_images/SEGS_sankey.png b/docs/api/_images/SEGS_sankey.png deleted file mode 100644 index 0b219dbd6..000000000 Binary files a/docs/api/_images/SEGS_sankey.png and /dev/null differ diff --git a/docs/api/_images/SolarCollector.svg b/docs/api/_images/SolarCollector.svg index abf6d8d2b..3c6c8a22a 100644 --- a/docs/api/_images/SolarCollector.svg +++ b/docs/api/_images/SolarCollector.svg @@ -1,974 +1,183 @@ - - + viewBox="0 0 70.499965 52.499989" + height="52.499989mm" + width="70.499962mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + fit-margin-bottom="5" + inkscape:pagecheckerboard="0" + inkscape:snap-intersection-paths="true" + inkscape:bbox-paths="false"> + originx="-119.75004" + originy="-43.750011" /> + id="metadata5"> image/svg+xml - - - - - - - - + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-119.75,-43.750016)"> in1 + inkscape:export-ydpi="1012" + inkscape:export-xdpi="1012" + xml:space="preserve" + style="font-size:4.9389px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round" + x="131.64293" + y="86.382317" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-7-3-1">in1 out1 + inkscape:export-ydpi="1012" + inkscape:export-xdpi="1012" + xml:space="preserve" + style="font-size:4.9389px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round" + x="164.9464" + y="56.240036" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-7-3-1-9">out1 - + + sodipodi:nodetypes="cccc" /> + sodipodi:nodetypes="cccc" /> - - - - - + sodipodi:nodetypes="cccccccccccccccc" + style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 129.99996,89.000005 v -10 h 32 l 3,-3 h -32 l 3,-3 h 32 l 3,-3 h -32 l 3,-3 h 32 l 3,-3 h -32 l 3,-3 h 32 v -10" + id="path984-0-9-9-9-7-2" /> diff --git a/docs/api/_images/SolarCollector_darkmode.svg b/docs/api/_images/SolarCollector_darkmode.svg new file mode 100644 index 000000000..50259e5cc --- /dev/null +++ b/docs/api/_images/SolarCollector_darkmode.svg @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + in1 + out1 + + + + + + diff --git a/docs/api/_images/Sp.svg b/docs/api/_images/Sp.svg new file mode 100644 index 000000000..af97dfcef --- /dev/null +++ b/docs/api/_images/Sp.svg @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + in1 + out1 + out2 + out3 + outn + + + + + + + + + + + diff --git a/docs/api/_images/Splitter.svg b/docs/api/_images/Splitter.svg index 63978612d..a1fecb9bb 100644 --- a/docs/api/_images/Splitter.svg +++ b/docs/api/_images/Splitter.svg @@ -1,198 +1,309 @@ - - - + viewBox="0 0 56.082793 49.455621" + height="49.45562mm" + width="56.08279mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + id="defs2"> + transform="scale(-0.4)" + style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt" + d="M 5.77,0 -2.88,5 V -5 Z" + id="path9033" /> + + + + transform="matrix(0.8,0,0,0.8,10,0)" + style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt" + d="M 0,0 5,-5 -12.5,0 5,5 Z" + id="path8897" /> + + + + + + + + + + id="metadata5"> image/svg+xml - + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-153.74997,7.2278038)"> + + inin1 + id="tspan2879">1 outout1 - - - - - - + id="tspan4210">1 outout2 + id="tspan4210-1">2 outout3 + id="tspan4210-1-6">3 outoutn + id="tspan4210-1-0">n + + + + + + + + + - diff --git a/docs/api/_images/Splitter_darkmode.svg b/docs/api/_images/Splitter_darkmode.svg new file mode 100644 index 000000000..478f16bd6 --- /dev/null +++ b/docs/api/_images/Splitter_darkmode.svg @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + in1 + out1 + out2 + out3 + outn + + + + + + + + + + + diff --git a/docs/api/_images/SubsystemInterface.svg b/docs/api/_images/SubsystemInterface.svg index ebd755145..bba4241b6 100644 --- a/docs/api/_images/SubsystemInterface.svg +++ b/docs/api/_images/SubsystemInterface.svg @@ -1,51 +1,52 @@ - - - + viewBox="0 0 67.688335 47.63987" + height="47.63987mm" + width="67.688332mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + id="defs2"> + + + + + + - - - + + + + id="metadata5"> image/svg+xml - + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-122.10837,-52.610142)"> system border + in1 + style="font-size:4.9389px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round" + x="174.9464" + y="71.240036" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-7">out1 out1 - + style="font-size:4.9389px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round" + x="174.9464" + y="76.240036" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-7-3">out2 + in1 inn + style="font-size:4.9389px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round" + x="126.64294" + y="76.382324" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-7-3-1-9">in2 outn + style="font-size:4.9389px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round" + x="126.64294" + y="91.382324" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-7-3-1-2">inn + outn + style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 138.99999,67.999991 2,2 -2,2 z" + id="path4652-12-9-60-5-4-2-4-3" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 169.99999,67.999991 2,2 -2,2 z" + id="path4652-12-9-60-5-4-2-4-6" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 169.99997,70.000011 h -29" + id="path984-0-9-9-9-7" /> - system border + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:0.5, 2;stroke-dashoffset:0;stroke-opacity:1" + d="m 154.99997,95.000011 v -30" + id="path984-0-9-9-9-7-9" /> + + + + + + diff --git a/docs/api/_images/SubsystemInterface_darkmode.svg b/docs/api/_images/SubsystemInterface_darkmode.svg new file mode 100644 index 000000000..8faa3ee23 --- /dev/null +++ b/docs/api/_images/SubsystemInterface_darkmode.svg @@ -0,0 +1,290 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + system border + out1 + out2 + in1 + in2 + inn + outn + + + + + + + + + + + + diff --git a/docs/api/_images/Turbine.svg b/docs/api/_images/Turbine.svg index 2c18e2c72..1e5c355aa 100644 --- a/docs/api/_images/Turbine.svg +++ b/docs/api/_images/Turbine.svg @@ -1,114 +1,175 @@ - - + viewBox="0 0 104.99999 69.999902" + height="69.999901mm" + width="104.99998mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + id="defs2"> + + + + + + +
+ inkscape:pagecheckerboard="0" + inkscape:snap-intersection-paths="true" + inkscape:bbox-paths="false" + inkscape:lockguides="true"> + originx="-120.00004" + originy="-47.750066" /> + id="metadata5"> image/svg+xml - + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-120,-47.750067)"> + in1 + id="tspan1295-2-3-0-3-5-7-3-5-0-5-24-7-1-0-9" + x="130.78593" + y="70.014618" + style="fill:#000000;fill-opacity:1;stroke-width:0.529166;stroke-linecap:round;stroke-linejoin:round">in1 out1 + id="tspan1295-2-3-0-3-5-7-3-5-0-5-24-7-1-0-9-3" + x="197.39284" + y="69.730057" + style="fill:#000000;fill-opacity:1;stroke-width:0.529166;stroke-linecap:round;stroke-linejoin:round">out1 + + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 187.50004,71.750011 -6e-5,-14.500018 H 215.5" + id="path984-0-9-9-9-7-6-8-4" /> + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 125.5,53.249995 4,4 -4,4 z" + id="path4652-12-9-60-5-4-2-9" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 215.5,53.249995 4,4 -4,4 z" + id="path4652-12-9-60-5-4-2-9-3" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> diff --git a/docs/api/_images/Turbine_darkmode.svg b/docs/api/_images/Turbine_darkmode.svg new file mode 100644 index 000000000..0aa7d4154 --- /dev/null +++ b/docs/api/_images/Turbine_darkmode.svg @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + in1 + out1 + + + + + + diff --git a/docs/api/_images/Valve.svg b/docs/api/_images/Valve.svg index b20049bcd..5154c2561 100644 --- a/docs/api/_images/Valve.svg +++ b/docs/api/_images/Valve.svg @@ -1,89 +1,175 @@ + viewBox="0 0 94.999957 30.74012" + height="30.74012mm" + width="94.999954mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + + + + + + + + - + inkscape:window-y="27" + inkscape:window-x="72" + inkscape:window-height="1136" + inkscape:window-width="1848" + inkscape:snap-to-guides="false" + inkscape:guide-bbox="true" + showguides="true" + inkscape:bbox-nodes="false" + inkscape:snap-grids="true" + inkscape:snap-bbox="true" + inkscape:snap-nodes="true" + inkscape:object-paths="true" + inkscape:snap-center="true" + showgrid="true" + inkscape:document-rotation="0" + inkscape:current-layer="layer1" + inkscape:document-units="mm" + inkscape:cy="121" + inkscape:cx="256" + inkscape:zoom="0.5" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + fit-margin-top="5" + fit-margin-left="5" + fit-margin-right="5" + fit-margin-bottom="5" + inkscape:pagecheckerboard="0" + inkscape:snap-intersection-paths="true" + inkscape:bbox-paths="false" + inkscape:snap-object-midpoints="true"> + + + id="metadata5"> image/svg+xml - + id="layer1" + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-112.5,-82.444879)"> + + + in1 + inkscape:export-ydpi="1012" + inkscape:export-xdpi="1012" + xml:space="preserve" + style="font-size:9.8778px;line-height:1.25;font-family:sans-serif;stroke-width:0.529166;stroke-linecap:round;stroke-linejoin:round" + x="179.89284" + y="94.665131" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-03">out1 out1 - + inkscape:export-ydpi="1012" + inkscape:export-xdpi="1012" + xml:space="preserve" + style="font-size:9.8778px;line-height:1.25;font-family:sans-serif;stroke-width:0.529166;stroke-linecap:round;stroke-linejoin:round" + x="123.28594" + y="94.949692" + id="text1297-0-9-8-6-9-4-7-6-7-8-6-9-5-5">in1 + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 118,98.185072 4,4.000008 -4,4 z" + id="path4652-12-9-60-5-4-2-2" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 197.99998,98.185064 4,4.000016 -4,4 z" + id="path4652-12-9-60-5-4-2-2-3" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> diff --git a/docs/api/_images/Valve_darkmode.svg b/docs/api/_images/Valve_darkmode.svg new file mode 100644 index 000000000..b5687ac84 --- /dev/null +++ b/docs/api/_images/Valve_darkmode.svg @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + out1 + in1 + + + + diff --git a/docs/api/_images/WaterElectrolyzer.svg b/docs/api/_images/WaterElectrolyzer.svg index e7e4f68a2..d321ebb45 100644 --- a/docs/api/_images/WaterElectrolyzer.svg +++ b/docs/api/_images/WaterElectrolyzer.svg @@ -1,93 +1,99 @@ - - + version="1.1" + viewBox="0 0 72.499994 67.499994" + height="67.499992mm" + width="72.499992mm" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + id="linearGradient2073" + inkscape:collect="always"> + style="stop-color:#000000;stop-opacity:1;" /> - - - + style="stop-color:#000000;stop-opacity:0;" /> + - - - + gradientTransform="translate(0.29243162,-2.3779876)" + gradientUnits="userSpaceOnUse" + y2="204.98201" + x2="223.36507" + y1="204.98201" + x1="221.6942" + id="linearGradient2075" + xlink:href="#linearGradient2073" + inkscape:collect="always" /> + inkscape:snap-nodes="true" + inkscape:object-paths="true" + inkscape:snap-center="true" + showgrid="true" + inkscape:document-rotation="0" + inkscape:current-layer="layer1" + inkscape:document-units="mm" + inkscape:cy="148.84598" + inkscape:cx="91.923882" + inkscape:zoom="1.4142136" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + fit-margin-top="5" + fit-margin-left="5" + fit-margin-right="5" + fit-margin-bottom="5" + inkscape:pagecheckerboard="0" + inkscape:snap-intersection-paths="true" + inkscape:bbox-paths="false" + inkscape:snap-object-midpoints="true"> + originx="-88.75" + originy="-33.750006" /> @@ -97,200 +103,213 @@ image/svg+xml - - - out2 - - in1 - out1 - in2 - out3 - - - - - - - - - - - - - - H2 - O2 - H2O - - + inkscape:groupmode="layer" + inkscape:label="Ebene 1" + transform="translate(-88.749981,-33.750012)"> + + + + + + in2 + out1 + H2 + in1 + out2 + O2 + H2O + out3 + + + + + + + + + + + diff --git a/docs/api/_images/WaterElectrolyzer_darkmode.svg b/docs/api/_images/WaterElectrolyzer_darkmode.svg new file mode 100644 index 000000000..c83c5bb4e --- /dev/null +++ b/docs/api/_images/WaterElectrolyzer_darkmode.svg @@ -0,0 +1,315 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + in2 + out1 + H2 + in1 + out2 + O2 + H2O + out3 + + + + + + + + + + + + + diff --git a/docs/api/_images/basic.svg b/docs/api/_images/basic.svg deleted file mode 100644 index d0e2192c2..000000000 --- a/docs/api/_images/basic.svg +++ /dev/null @@ -1,916 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - G - - - - - - - - - - - - - - diff --git a/docs/api/_images/basic_efficiency.svg b/docs/api/_images/basic_efficiency.svg deleted file mode 100644 index 081cd4e24..000000000 --- a/docs/api/_images/basic_efficiency.svg +++ /dev/null @@ -1,1043 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/api/_images/cc_bp.svg b/docs/api/_images/cc_bp.svg deleted file mode 100644 index 4e2047d09..000000000 --- a/docs/api/_images/cc_bp.svg +++ /dev/null @@ -1,1218 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - G - - - - - - - - - - - - - - - - - - - - - G - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/api/_images/chp.svg b/docs/api/_images/chp.svg deleted file mode 100644 index a8c397868..000000000 --- a/docs/api/_images/chp.svg +++ /dev/null @@ -1,1089 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - G - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/api/_images/chp_PQ.svg b/docs/api/_images/chp_PQ.svg deleted file mode 100644 index 1107b49ad..000000000 --- a/docs/api/_images/chp_PQ.svg +++ /dev/null @@ -1,1579 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/api/_images/diagram_E_D.svg b/docs/api/_images/diagram_E_D.svg deleted file mode 100644 index 377ff6679..000000000 --- a/docs/api/_images/diagram_E_D.svg +++ /dev/null @@ -1,2167 +0,0 @@ - - - - - - - - - 2021-08-23T12:31:42.026353 - image/svg+xml - - - Matplotlib v3.3.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/api/_images/diagram_cop_eps_Tgeo_Q.svg b/docs/api/_images/diagram_cop_eps_Tgeo_Q.svg deleted file mode 100644 index 77e0a00e6..000000000 --- a/docs/api/_images/diagram_cop_eps_Tgeo_Q.svg +++ /dev/null @@ -1,1826 +0,0 @@ - - - - - - - - - 2021-08-09T11:06:48.809804 - image/svg+xml - - - Matplotlib v3.3.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/api/_images/diagram_cop_eps_Tgeo_Ths.svg b/docs/api/_images/diagram_cop_eps_Tgeo_Ths.svg deleted file mode 100644 index 891e51078..000000000 --- a/docs/api/_images/diagram_cop_eps_Tgeo_Ths.svg +++ /dev/null @@ -1,1945 +0,0 @@ - - - - - - - - - 2021-08-09T11:06:47.618579 - image/svg+xml - - - Matplotlib v3.3.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/api/_images/diagram_eps_Tamb_Tgeo.svg b/docs/api/_images/diagram_eps_Tamb_Tgeo.svg deleted file mode 100644 index dd4bd1594..000000000 --- a/docs/api/_images/diagram_eps_Tamb_Tgeo.svg +++ /dev/null @@ -1,1822 +0,0 @@ - - - - - - - - - 2021-08-09T11:06:46.095693 - image/svg+xml - - - Matplotlib v3.3.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/api/_images/flowsheet.svg b/docs/api/_images/flowsheet.svg new file mode 100644 index 000000000..a0e96ceb9 --- /dev/null +++ b/docs/api/_images/flowsheet.svg @@ -0,0 +1,873 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + compressor 1 + condenser + evaporator + expansion valve + 1 + 6 + + + + + + + + consumer + 20 + 21 + 22 + + + 23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 2 + 3 + 4 + 5 + 7 + 8 + 9 + 11 + 12 + 14 + 15 + 16 + 17 + 13 + 18 + 19 + superheater + compressor 2 + + + + + diff --git a/docs/api/_images/heat_pump.svg b/docs/api/_images/heat_pump.svg deleted file mode 100644 index 0d35bd4e5..000000000 --- a/docs/api/_images/heat_pump.svg +++ /dev/null @@ -1,611 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - source intercool - sink intercool - consumerback flow - consumerfeed flow - sink ambient - source ambient - - - - - coolant in - coolant out - condenser - expansion valve - drum withevaporator - superheater - compressor train - - diff --git a/docs/api/_images/heat_pump_COP_air.svg b/docs/api/_images/heat_pump_COP_air.svg deleted file mode 100644 index f279064bc..000000000 --- a/docs/api/_images/heat_pump_COP_air.svg +++ /dev/null @@ -1,1234 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/api/_images/heat_pump_COP_water.svg b/docs/api/_images/heat_pump_COP_water.svg deleted file mode 100644 index 3e0444580..000000000 --- a/docs/api/_images/heat_pump_COP_water.svg +++ /dev/null @@ -1,1226 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/api/_images/heat_pump_example.svg b/docs/api/_images/heat_pump_example.svg deleted file mode 100644 index 52b3f8160..000000000 --- a/docs/api/_images/heat_pump_example.svg +++ /dev/null @@ -1,641 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - sink ambient - consumerback flow - consumerfeed flow - sink ambient - sourceambient - - - - - coolant in - coolant out - condenser - expansion valve - drum withevaporator - superheater - compressor train - - - - - - fan/pump - - - diff --git a/docs/api/_images/heat_pump_exergy_flowsheet.svg b/docs/api/_images/heat_pump_exergy_flowsheet.svg deleted file mode 100644 index f4a7899c1..000000000 --- a/docs/api/_images/heat_pump_exergy_flowsheet.svg +++ /dev/null @@ -1,504 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - ground heatfeed flow - - condenser - expansion valve - evaporator - cycle closer - - compressor - ground heat return flow - heating systemfeed flow - heating systemreturn flow - - - - - - - - - - - - - heating system - - - - - geothermal heat collector - - - - diff --git a/docs/api/_images/intro_connections.svg b/docs/api/_images/intro_connections.svg deleted file mode 100644 index 46ec2c102..000000000 --- a/docs/api/_images/intro_connections.svg +++ /dev/null @@ -1,326 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - waste steam - flue gas - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/api/_images/intro_district_heating_scheme.svg b/docs/api/_images/intro_district_heating_scheme.svg deleted file mode 100644 index 420f5a4f7..000000000 --- a/docs/api/_images/intro_district_heating_scheme.svg +++ /dev/null @@ -1,286 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - source - sink - - - pipe feed - pipe back - - - - - heat exchanger - - - central heating plant - consumer - - Q - - - valve - - - - - - diff --git a/docs/api/_images/power_plant_two_extractions.svg b/docs/api/_images/power_plant_two_extractions.svg deleted file mode 100644 index 19039462d..000000000 --- a/docs/api/_images/power_plant_two_extractions.svg +++ /dev/null @@ -1,1372 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - G - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/api/_images/scatterplot_efficiency_optimization.svg b/docs/api/_images/scatterplot_efficiency_optimization.svg deleted file mode 100644 index 8f81d8085..000000000 --- a/docs/api/_images/scatterplot_efficiency_optimization.svg +++ /dev/null @@ -1,1837 +0,0 @@ - - - - - - - - - 2021-02-11T10:41:05.717444 - image/svg+xml - - - Matplotlib v3.3.3, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/api/_images/subsystem_waste_heat_generator.svg b/docs/api/_images/subsystem_waste_heat_generator.svg deleted file mode 100644 index 5c103a5db..000000000 --- a/docs/api/_images/subsystem_waste_heat_generator.svg +++ /dev/null @@ -1,1057 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - superheater - evaporator - economizer - drum - - diff --git a/docs/api/_images/tutorial_heat_pump.svg b/docs/api/_images/tutorial_heat_pump.svg deleted file mode 100644 index cff5f1431..000000000 --- a/docs/api/_images/tutorial_heat_pump.svg +++ /dev/null @@ -1,589 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - source intercool - sink intercool - sink ambient - source ambient - - - - condenser - expansion valve - drum withevaporator - superheater - compressor train - coolant cycle closer(coolant in) - - consumer cycle closer - - - diff --git a/docs/api/tespy.components.rst b/docs/api/components.rst similarity index 96% rename from docs/api/tespy.components.rst rename to docs/api/components.rst index b938cfe2a..c05f296f3 100644 --- a/docs/api/tespy.components.rst +++ b/docs/api/components.rst @@ -200,6 +200,15 @@ tespy.components.piping.valve module :show-inheritance: +tespy.components.reactors.fuel_cell module +--------------------------------------------------- + +.. automodule:: tespy.components.reactors.fuel_cell + :members: + :undoc-members: + :show-inheritance: + + tespy.components.reactors.water_electrolyzer module --------------------------------------------------- diff --git a/docs/api/tespy.connections.rst b/docs/api/connections.rst similarity index 95% rename from docs/api/tespy.connections.rst rename to docs/api/connections.rst index 9f7be091a..0cea7a70e 100644 --- a/docs/api/tespy.connections.rst +++ b/docs/api/connections.rst @@ -1,23 +1,23 @@ -tespy.connections module -======================== - -.. automodule:: tespy.connections - :members: - :undoc-members: - :show-inheritance: - -tespy.connections.bus module ----------------------------- - -.. automodule:: tespy.connections.bus - :members: - :undoc-members: - :show-inheritance: - -tespy.connections.connection module ------------------------------------ - -.. automodule:: tespy.connections.connection - :members: - :undoc-members: - :show-inheritance: +tespy.connections module +======================== + +.. automodule:: tespy.connections + :members: + :undoc-members: + :show-inheritance: + +tespy.connections.bus module +---------------------------- + +.. automodule:: tespy.connections.bus + :members: + :undoc-members: + :show-inheritance: + +tespy.connections.connection module +----------------------------------- + +.. automodule:: tespy.connections.connection + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/api/tespy.data.rst b/docs/api/data.rst similarity index 95% rename from docs/api/tespy.data.rst rename to docs/api/data.rst index bbc3e8884..bb28de9cf 100644 --- a/docs/api/tespy.data.rst +++ b/docs/api/data.rst @@ -1,167 +1,161 @@ -tespy.data module -================= - -Module contents ---------------- - -.. automodule:: tespy.data - :members: - :undoc-members: - :show-inheritance: - -Default characteristics ------------------------ - -Characteristic lines -^^^^^^^^^^^^^^^^^^^^ -**turbine** - -.. figure:: _images/turbine_eta_s_char_DEFAULT.svg - :alt: Characteristic line "DEFAULT" for parameter "eta_s_char". - :align: center - - Reference: Generic data. - -.. figure:: _images/turbine_eta_s_char_TRAUPEL.svg - :alt: Characteristic line "TRAUPEL" for parameter "eta_s_char". - :align: center - - Reference: :cite:`Traupel2001`. - -**compressor** - -.. figure:: _images/compressor_eta_s_char_DEFAULT.svg - :alt: Characteristic line "DEFAULT" for parameter "eta_s_char". - :align: center - - Reference: Generic data. - -**pump** - -.. figure:: _images/pump_eta_s_char_DEFAULT.svg - :alt: Characteristic line "DEFAULT" for parameter "eta_s_char". - :align: center - - Reference: Generic data. - -**combustion engine** - -.. figure:: _images/combustion_engine_tiP_char_DEFAULT.svg - :alt: Characteristic line "DEFAULT" for parameter "tiP_char". - :align: center - - Reference: Generic data. - -.. figure:: _images/combustion_engine_Q1_char_DEFAULT.svg - :alt: Characteristic line "DEFAULT" for parameter "Q1_char". - :align: center - - Reference: Generic data. - -.. figure:: _images/combustion_engine_Q2_char_DEFAULT.svg - :alt: Characteristic line "DEFAULT" for parameter "Q2_char". - :align: center - - Reference: Generic data. - -.. figure:: _images/combustion_engine_Qloss_char_DEFAULT.svg - :alt: Characteristic line "DEFAULT" for parameter "Qloss_char". - :align: center - - Reference: Generic data. - -**heat exchanger** - -.. figure:: _images/heat_exchanger_kA_char1_DEFAULT.svg - :alt: Characteristic line "DEFAULT" for parameter "kA_char1". - :align: center - - Reference: Generic data. - -.. figure:: _images/heat_exchanger_kA_char1_CONDENSING_FLUID.svg - :alt: Characteristic line "CONDENSING FLUID" for parameter "kA_char1". - :align: center - - Reference: Generic data. - -.. figure:: _images/heat_exchanger_kA_char2_DEFAULT.svg - :alt: Characteristic line "DEFAULT" for parameter "kA_char2". - :align: center - - Reference: Generic data. - -.. figure:: _images/heat_exchanger_kA_char2_EVAPORATING_FLUID.svg - :alt: Characteristic line "EVAPORATING FLUID" for parameter "kA_char2". - :align: center - - Reference: Generic data. - -**condenser** - -.. figure:: _images/condenser_kA_char1_DEFAULT.svg - :alt: Characteristic line "DEFAULT" for parameter "kA_char1". - :align: center - - Reference: Generic data. - -.. figure:: _images/condenser_kA_char2_DEFAULT.svg - :alt: Characteristic line "DEFAULT" for parameter "kA_char2". - :align: center - - Reference: Generic data. - -**desuperheater** - -.. figure:: _images/desuperheater_kA_char1_DEFAULT.svg - :alt: Characteristic line "DEFAULT" for parameter "kA_char1". - :align: center - - Reference: Generic data. - -.. figure:: _images/desuperheater_kA_char2_DEFAULT.svg - :alt: Characteristic line "DEFAULT" for parameter "kA_char2". - :align: center - - Reference: Generic data. - -**heat exchanger simple** - -.. figure:: _images/heat_exchanger_simple_kA_char_DEFAULT.svg - :alt: Characteristic line "DEFAULT" for parameter "kA_char". - :align: center - - Reference: Generic data. - -**pipe** - -.. figure:: _images/pipe_kA_char_DEFAULT.svg - :alt: Characteristic line "DEFAULT" for parameter "kA_char". - :align: center - - Reference: Generic data. - -**water electrolyzer** - -.. figure:: _images/water_electrolyzer_eta_char_DEFAULT.svg - :alt: Characteristic line "DEFAULT" for parameter "eta_char". - :align: center - - Reference: Generic data. - -Characteristic maps -^^^^^^^^^^^^^^^^^^^ - -**compressor** - -.. figure:: _images/compressor_char_map_pr_DEFAULT.svg - :alt: Characteristic map "DEFAULT" for parameter "char_map_pr". - :align: center - - Reference: :cite:`Plis2016`. - -.. figure:: _images/compressor_char_map_eta_s_DEFAULT.svg - :alt: Characteristic map "DEFAULT" for parameter "char_map_eta_s". - :align: center - - Reference: :cite:`Plis2016`. - +.. _tespy_data_label: + +tespy.data module +================= + +Default characteristics +----------------------- + +Characteristic lines +^^^^^^^^^^^^^^^^^^^^ +**turbine** + +.. figure:: _images/turbine_eta_s_char_DEFAULT.svg + :alt: Characteristic line "DEFAULT" for parameter "eta_s_char". + :align: center + + Reference: Generic data. + +.. figure:: _images/turbine_eta_s_char_TRAUPEL.svg + :alt: Characteristic line "TRAUPEL" for parameter "eta_s_char". + :align: center + + Reference: :cite:`Traupel2001`. + +**compressor** + +.. figure:: _images/compressor_eta_s_char_DEFAULT.svg + :alt: Characteristic line "DEFAULT" for parameter "eta_s_char". + :align: center + + Reference: Generic data. + +**pump** + +.. figure:: _images/pump_eta_s_char_DEFAULT.svg + :alt: Characteristic line "DEFAULT" for parameter "eta_s_char". + :align: center + + Reference: Generic data. + +**combustion engine** + +.. figure:: _images/combustion_engine_tiP_char_DEFAULT.svg + :alt: Characteristic line "DEFAULT" for parameter "tiP_char". + :align: center + + Reference: Generic data. + +.. figure:: _images/combustion_engine_Q1_char_DEFAULT.svg + :alt: Characteristic line "DEFAULT" for parameter "Q1_char". + :align: center + + Reference: Generic data. + +.. figure:: _images/combustion_engine_Q2_char_DEFAULT.svg + :alt: Characteristic line "DEFAULT" for parameter "Q2_char". + :align: center + + Reference: Generic data. + +.. figure:: _images/combustion_engine_Qloss_char_DEFAULT.svg + :alt: Characteristic line "DEFAULT" for parameter "Qloss_char". + :align: center + + Reference: Generic data. + +**heat exchanger** + +.. figure:: _images/heat_exchanger_kA_char1_DEFAULT.svg + :alt: Characteristic line "DEFAULT" for parameter "kA_char1". + :align: center + + Reference: Generic data. + +.. figure:: _images/heat_exchanger_kA_char1_CONDENSING_FLUID.svg + :alt: Characteristic line "CONDENSING FLUID" for parameter "kA_char1". + :align: center + + Reference: Generic data. + +.. figure:: _images/heat_exchanger_kA_char2_DEFAULT.svg + :alt: Characteristic line "DEFAULT" for parameter "kA_char2". + :align: center + + Reference: Generic data. + +.. figure:: _images/heat_exchanger_kA_char2_EVAPORATING_FLUID.svg + :alt: Characteristic line "EVAPORATING FLUID" for parameter "kA_char2". + :align: center + + Reference: Generic data. + +**condenser** + +.. figure:: _images/condenser_kA_char1_DEFAULT.svg + :alt: Characteristic line "DEFAULT" for parameter "kA_char1". + :align: center + + Reference: Generic data. + +.. figure:: _images/condenser_kA_char2_DEFAULT.svg + :alt: Characteristic line "DEFAULT" for parameter "kA_char2". + :align: center + + Reference: Generic data. + +**desuperheater** + +.. figure:: _images/desuperheater_kA_char1_DEFAULT.svg + :alt: Characteristic line "DEFAULT" for parameter "kA_char1". + :align: center + + Reference: Generic data. + +.. figure:: _images/desuperheater_kA_char2_DEFAULT.svg + :alt: Characteristic line "DEFAULT" for parameter "kA_char2". + :align: center + + Reference: Generic data. + +**heat exchanger simple** + +.. figure:: _images/heat_exchanger_simple_kA_char_DEFAULT.svg + :alt: Characteristic line "DEFAULT" for parameter "kA_char". + :align: center + + Reference: Generic data. + +**pipe** + +.. figure:: _images/pipe_kA_char_DEFAULT.svg + :alt: Characteristic line "DEFAULT" for parameter "kA_char". + :align: center + + Reference: Generic data. + +**water electrolyzer** + +.. figure:: _images/water_electrolyzer_eta_char_DEFAULT.svg + :alt: Characteristic line "DEFAULT" for parameter "eta_char". + :align: center + + Reference: Generic data. + +Characteristic maps +^^^^^^^^^^^^^^^^^^^ + +**compressor** + +.. figure:: _images/compressor_char_map_pr_DEFAULT.svg + :alt: Characteristic map "DEFAULT" for parameter "char_map_pr". + :align: center + + Reference: :cite:`Plis2016`. + +.. figure:: _images/compressor_char_map_eta_s_DEFAULT.svg + :alt: Characteristic map "DEFAULT" for parameter "char_map_eta_s". + :align: center + + Reference: :cite:`Plis2016`. + diff --git a/docs/api/tespy.networks.rst b/docs/api/networks.rst similarity index 95% rename from docs/api/tespy.networks.rst rename to docs/api/networks.rst index 2592e2903..5f9217788 100644 --- a/docs/api/tespy.networks.rst +++ b/docs/api/networks.rst @@ -1,23 +1,23 @@ -tespy.networks module -===================== - -.. automodule:: tespy.networks - :members: - :undoc-members: - :show-inheritance: - -tespy.networks.network module ------------------------------ - -.. automodule:: tespy.networks.network - :members: - :undoc-members: - :show-inheritance: - -tespy.networks.network_reader module ------------------------------------- - -.. automodule:: tespy.networks.network_reader - :members: - :undoc-members: - :show-inheritance: +tespy.networks module +===================== + +.. automodule:: tespy.networks + :members: + :undoc-members: + :show-inheritance: + +tespy.networks.network module +----------------------------- + +.. automodule:: tespy.networks.network + :members: + :undoc-members: + :show-inheritance: + +tespy.networks.network_reader module +------------------------------------ + +.. automodule:: tespy.networks.network_reader + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/api/tespy.tools.rst b/docs/api/tools.rst similarity index 88% rename from docs/api/tespy.tools.rst rename to docs/api/tools.rst index 17543b064..f76f92c95 100644 --- a/docs/api/tespy.tools.rst +++ b/docs/api/tools.rst @@ -61,3 +61,11 @@ tespy.tools.logger module :members: :undoc-members: :show-inheritance: + +tespy.tools.optimization module +------------------------------- + +.. automodule:: tespy.tools.optimization + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/basics.rst b/docs/basics.rst new file mode 100644 index 000000000..ccc9354d2 --- /dev/null +++ b/docs/basics.rst @@ -0,0 +1,81 @@ +.. _tespy_basics_label: + +Modeling Basic Systems +~~~~~~~~~~~~~~~~~~~~~~ + +In this section we will introduce how to create your first simple TESPy models. +In the intro part you learn about the modeling concept of TESPy. The other +subsections are step by step walkthroughs for well-known thermodynamic +applications. + +If you want to learn more about the details of the different parts of the +software, you should also have a look at the +:ref:`Documentation section ` after the first steps. If +you have any questions please reach out to the +:ref:`TESPy community `. There are regular online +meetings as well as a discussion forum on GitHub. + +.. toctree:: + :maxdepth: 1 + :hidden: + + basics/intro.rst + basics/heat_pump.rst + basics/rankine_cycle.rst + basics/gas_turbine.rst + basics/district_heating.rst + + +.. card:: Introduction: Learn the basic modeling concept of TESPy + :link: tespy_basics_intro_label + :link-type: ref + + .. figure:: /_static/images/basics/modeling_concept.svg + :align: center + :alt: TESPy's modeling concept + +.. grid:: 2 + :gutter: 1 + + .. grid-item-card:: Heat Pump + :link: tespy_basics_heat_pump_label + :link-type: ref + + .. image:: /_static/images/basics/heat_pump.svg + :class: only-light + + .. image:: /_static/images/basics/heat_pump_darkmode.svg + :class: only-dark + + .. grid-item-card:: Clausius Rankine Cycle + :link: tespy_basics_rankine_cycle_label + :link-type: ref + + .. image:: /_static/images/basics/rankine_cycle.svg + :class: only-light + + .. image:: /_static/images/basics/rankine_cycle_darkmode.svg + :class: only-dark + +.. grid:: 2 + :gutter: 1 + + .. grid-item-card:: Gas Turbine + :link: tespy_basics_gas_turbine_label + :link-type: ref + + .. image:: /_static/images/basics/gas_turbine.svg + :class: only-light + + .. image:: /_static/images/basics/gas_turbine_darkmode.svg + :class: only-dark + + .. grid-item-card:: District Heating System + :link: tespy_basics_district_heating_label + :link-type: ref + + .. image:: /_static/images/basics/district_heating.svg + :class: only-light + + .. image:: /_static/images/basics/district_heating_darkmode.svg + :class: only-dark diff --git a/docs/basics/district_heating.rst b/docs/basics/district_heating.rst new file mode 100644 index 000000000..7732f8f23 --- /dev/null +++ b/docs/basics/district_heating.rst @@ -0,0 +1,135 @@ +.. _tespy_basics_district_heating_label: + +District Heating Network +======================== + +.. figure:: /_static/images/basics/district_heating.svg + :align: center + :alt: Topology of the district heating network + :figclass: only-light + + Figure: Topology of the district heating network + +.. figure:: /_static/images/basics/district_heating_darkmode.svg + :align: center + :alt: Topology of the district heating network + :figclass: only-dark + + Figure: Topology of the district heating network + +The model used in this example is shown the figure. It consists of a central +heating plant and a consumer, represented by a heat exchanger with a control +valve. A much more complex district heating system is included in the +advanced tutorials section. + +Download the full script here: +:download:`district_heating.py ` + +Setting up the System +^^^^^^^^^^^^^^^^^^^^^ +For this model we have to import the :code:`Network` and :code:`Connection` +classes as well as the respective components. After setting up the network we +can create the components, connect them to the network (as shown in the other) +examples. + +.. dropdown:: Click to expand to code section + + .. literalinclude:: /../tutorial/basics/district_heating.py + :language: python + :start-after: [sec_1] + :end-before: [sec_2] + +In the first step, we assume we have a specific heat demand of the consumer +and constant pressure and thermal losses in the pipes. Furthermore, the pump +produces a constant pressure at the feed part of the system. With the control +valve in place the pressure of the return part of the system is then decoupled +from that value. Therefore, we need to impose a pressure value at the sink as +well, which should be equal to the pressure at the pump's inlet. The pressure +drop in the valve will then be the residual pressure drop between the feed and +the return part of the system. Lastly, we fix the feed flow and the return +flow (at connection 4) temperature values. + +.. literalinclude:: /../tutorial/basics/district_heating.py + :language: python + :start-after: [sec_2] + :end-before: [sec_3] + +Design Pipe Dimensions +^^^^^^^^^^^^^^^^^^^^^^ +In the second step we will design the pipe's dimensions. There are two tasks +for this: + +- Calculate the necessary pipe diameter given a target pressure loss as well + as length and pipe roughness. +- Calculate the necessary insulation of the pipe based on assumptions + regarding the heat loss at a given ambient temperature value. + +For the first step, we impose lengths and roughness of the pipe and set the +diameter to :code:`"var"`, indicating the diameter of the pipe should be a +variable value in the calculation. + +.. literalinclude:: /../tutorial/basics/district_heating.py + :language: python + :start-after: [sec_3] + :end-before: [sec_4] + +In the second step we can fix the diameter to its resulting value and +therefore unset the desired pressure loss first. Then, we impose the ambient +temperature of the pipes (we assume the temperature of the ambient is not +affected by the heat loss of the pipe). With the given heat loss, the +:code:`kA` value can be calculated. It is the area independent heat transfer +coefficient. + +.. literalinclude:: /../tutorial/basics/district_heating.py + :language: python + :start-after: [sec_4] + :end-before: [sec_5] + +.. note:: + + In the results you can see, that the pipes' pressure losses are still at + the desired value after remove the pressure ration specification and using + the calculated value of the diameter instead. + +Changing Operation Conditions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Next, we want to investigate what happens, in case the + +- ambient temperature changes. +- heat load varies. +- overall temperature level in the heating system is reduced. + +To do that, we will use similar setups as show in the rankine cycle +introduction. The :code:`KA` value of both pipes is assumed to be fixed, the +efficiency of the pump and pressure losses in consumer and heat source are +constant as well. + +.. dropdown:: Click to expand to code section + + .. literalinclude:: /../tutorial/basics/district_heating.py + :language: python + :start-after: [sec_5] + :end-before: [sec_6] + +.. figure:: /_static/images/basics/district_heating_partload.svg + :align: center + :alt: Performance of the district heating system at changing operating conditions + :figclass: only-light + + Figure: Performance of the district heating system at changing operating conditions. + +.. figure:: /_static/images/basics/district_heating_partload_darkmode.svg + :align: center + :alt: Performance of the district heating system at changing operating conditions + :figclass: only-dark + + Figure: Performance of the district heating system at changing operating conditions. + +.. note:: + + The efficiency value is defined as ratio of the heat delivered to the + consumer to the heat production in the central heating plant. + + .. math:: + + \eta = \frac{\dot{Q}_\text{consumer}}{\dot{Q}_\text{production}} diff --git a/docs/basics/gas_turbine.rst b/docs/basics/gas_turbine.rst new file mode 100644 index 000000000..e271c6874 --- /dev/null +++ b/docs/basics/gas_turbine.rst @@ -0,0 +1,265 @@ +.. _tespy_basics_gas_turbine_label: + +Gas Turbine +=========== + +.. figure:: /_static/images/basics/gas_turbine.svg + :align: center + :alt: Topology of the gas turbine + :figclass: only-light + + Figure: Topology of the gas turbine + +.. figure:: /_static/images/basics/gas_turbine_darkmode.svg + :align: center + :alt: Topology of the gas turbine + :figclass: only-dark + + Figure: Topology of the gas turbine + +This tutorial introduces a new component, the combustion chamber. You will +learn how to use the component and set up a simple open cycle gas turbine: It +compresses air and burns fuel in the combustion chamber. The hot and +pressurized flue gas expands in the turbine, which drives the compressor and +the generator. You will also learn, how to use the fluid compositon as a +variable in your simulation. + +Download the full script here: +:download:`gas_turbine.py ` + +Setting up the Combustion Chamber +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +We are setting up our system step by step. Especially for larger systems, it +is recommended you follow this approach, since TESPy highly relies on a set of +good starting values for good convergence. You can learn more about it in the +:ref:`advanced tutorial ` section of the online +documentation. + +.. note:: + + There are two different types of combustion chambers available: + + - :py:class:`tespy.components.combustion.base.CombustionChamber` and + - :py:class:`tespy.components.combustion.diabatic.DiabaticCombustionChamber`. + + Both can handle varying fluid compositions for the air and the fuel and + calculate the fluid composition of the flue gas. Thus, it is possible to + e.g. specify the oxygen mass fraction in the flue gas in a calculation. + The difference between the components lies in the fact, that the + :code:`CombustionChamber` does **not consider heat or pressure losses**, + while :code:`DiabaticCombustionChamber` does so. + +In this tutorial, we will use the +:py:class:`tespy.components.combustion.diabatic.DiabaticCombustionChamber`. +First, we set up a network and the components. The network's fluid list must +contain all fluid components used for the combustion chamber. **These are at** +**least the fuel, oxygen, carbon-dioxide and water**. For this example we +add Nitrogen, since it is the most important fresh air component. + +.. literalinclude:: /../tutorial/basics/gas_turbine.py + :language: python + :start-after: [sec_1] + :end-before: [sec_2] + +In the first step, we do not connect the inlet of the combustion chamber with +the compressor but with the air source instead. Similarly, the outlet of the +combustion chamber is directly connected to the flue gas sink. + +.. literalinclude:: /../tutorial/basics/gas_turbine.py + :language: python + :start-after: [sec_2] + :end-before: [sec_3] + +There are many different specifications possible. For the combustion chamber +we will specify its air to stoichiometric air ratio lamb and the thermal input +(:math:`LHV \cdot \dot{m}_{f}`). + +Furthermore, we specify the efficiency :code:`eta` of the component, which +determines the heat loss as ratio of the thermal input. :code:`eta=1` means, +no heat losses, thus adiabatic behavior. + +The pressure ratio :code:`pr` describes the ratio of the pressure at the +outlet to the pressure at **the inlet 1**. The pressure value at the inlet 2 +is detached from the other pressure values, it must be a result of a different +parameter specification. In this example, we set it directly. Initially, we +assume adiabatic behavior :code:`eta=1` and no pressure losses :code:`pr=1`. + +The ambient conditions as well as the fuel gas inlet temperature are defined +in the next step. The full vector for the air and the fuel gas composition +have to be defined. The component can not handle "Air" as input fluid. We can +run the code after the specifications. + +.. literalinclude:: /../tutorial/basics/gas_turbine.py + :language: python + :start-after: [sec_3] + :end-before: [sec_4] + +Of course, you can change the parametrization in any desired way. For example +instead of stating the thermal input, you could choose any of the mass flows: + +.. literalinclude:: /../tutorial/basics/gas_turbine.py + :language: python + :start-after: [sec_4] + :end-before: [sec_5] + +or instead of the air to stoichiometric air ratio you could specify the flue +gas temperature. + +.. literalinclude:: /../tutorial/basics/gas_turbine.py + :language: python + :start-after: [sec_5] + :end-before: [sec_6] + +It is also possible to make modifications on the fluid composition, for +example, we can add hydrogen to the fuel mixture. + +.. literalinclude:: /../tutorial/basics/gas_turbine.py + :language: python + :start-after: [sec_6] + :end-before: [sec_7] + +The most convenient way to access the fluid composition is to access the +results dataframe for the connections. + +.. literalinclude:: /../tutorial/basics/gas_turbine.py + :language: python + :start-after: [sec_7] + :end-before: [sec_8] + +.. note:: + + All component and connection results are available in the :code:`results` + dict of the :code:`Network` instance. The keys of the dictionary are the + respective class names. + +Setting up the Full System +^^^^^^^^^^^^^^^^^^^^^^^^^^ +After learning more about the component, we are going to add the remaining +components: The turbine, the compressor and the generator. To do that, remove +the existing connections from the network, create the new connections and +add them to the network again. We also add a :code:`Bus` representing the +generator, assuming 98 % mechanical-electrical efficiency. + +.. literalinclude:: /../tutorial/basics/gas_turbine.py + :language: python + :start-after: [sec_8] + :end-before: [sec_9] + +Since we deleted the connection 2 and 3, all specifications for those +connections have to be added again. The air fluid composition is specified on +connection 1 with ambient pressure and temperature. The compressor pressure +ratio is set to 15 bar, the turbine inlet temperature to 1200 °C. Finally, set +the gas turbine outlet pressure to ambient pressure as well as the +compressor's and turbine's efficiency. + +.. literalinclude:: /../tutorial/basics/gas_turbine.py + :language: python + :start-after: [sec_9] + :end-before: [sec_10] + +Note, that the pressure of the fuel is lower than the pressure of the air at +the combustion chamber as we did not change the pressure of connection 5. A +respective warning is printed after the calculation. We can fix it like so: + +.. literalinclude:: /../tutorial/basics/gas_turbine.py + :language: python + :start-after: [sec_10] + :end-before: [sec_11] + +We can investigate, how the turbine inlet temperature and the compressor +pressure ratio affect thermal efficiency and power generation. Also, we +assume 2 % heat losses and 3 % pressure losses in the combustion chamber. + +.. dropdown:: Click to expand to code section + + .. literalinclude:: /../tutorial/basics/gas_turbine.py + :language: python + :start-after: [sec_11] + :end-before: [sec_12] + +.. figure:: /_static/images/basics/gas_turbine_parametric.svg + :align: center + :alt: Gas turbine performance at different compressor pressure ratios and turbine inlet temperatures + :figclass: only-light + + Figure: Gas turbine performance at different compressor pressure ratios + and turbine inlet temperatures + +.. figure:: /_static/images/basics/gas_turbine_parametric_darkmode.svg + :align: center + :alt: Gas turbine performance at different compressor pressure ratios and turbine inlet temperatures + :figclass: only-dark + + Figure: Gas turbine performance at different compressor pressure ratios + and turbine inlet temperatures + +Fluid Composition Specifications +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In this section you will learn how the fluid composition can be used as a +variable in such systems. To begin, we can impose the oxygen mass fraction on +the flue gas instead of the turbine inlet pressure, since it determines the +share of oxygen that is not required in the combustion. We can see, how the +turbine inlet temperature correlates with the oxygen mass fraction. + +.. dropdown:: Click to expand to code section + + .. literalinclude:: /../tutorial/basics/gas_turbine.py + :language: python + :start-after: [sec_12] + :end-before: [sec_13] + +.. figure:: /_static/images/basics/gas_turbine_oxygen.svg + :align: center + :alt: Turbine inlet temperature at different levels of oxygen in the flue gas + :figclass: only-light + + Figure: Turbine inlet temperature at different levels of oxygen in the + flue gas + +.. figure:: /_static/images/basics/gas_turbine_oxygen_darkmode.svg + :align: center + :alt: Turbine inlet temperature at different levels of oxygen in the flue gas + :figclass: only-dark + + Figure: Turbine inlet temperature at different levels of oxygen in the + flue gas + +Let us now assume, we do have an unknown shares of hydrogen and methane within +our fuel mixture. With the known mass flow of the fuel and an overall thermal +input, we can calculate both fractions by removing their respective values +from the input parameters and using the :code:`fluid_balance` keyword instead, +which automatically calculates the sum of all fluid mass fractions to be 1. + +Investigate how changing the thermal input requires a different mixture of +hydrogen and methane. + +.. attention:: + + With this setup, a thermal input below the lower heating value of methane + or above the lower heating value of hydrogen (each multiplied with the + mass flow of 1 kg/s) does not make sense as input specification. This is + individual of every fluid you use as fuel and you cannot easily abstract + the values to any other combination. + +.. dropdown:: Click to expand to code section + + .. literalinclude:: /../tutorial/basics/gas_turbine.py + :language: python + :start-after: [sec_13] + :end-before: [sec_14] + +.. figure:: /_static/images/basics/gas_turbine_fuel_composition.svg + :align: center + :alt: Mass fractions of H2 and CH4 in fuel mixture at different thermal input + :figclass: only-light + + Figure: Mass fractions of H2 and CH4 in fuel mixture at varying thermal + input and constant fuel mass flow + +.. figure:: /_static/images/basics/gas_turbine_fuel_composition_darkmode.svg + :align: center + :alt: Mass fractions of H2 and CH4 in fuel mixture at different thermal input + :figclass: only-dark + + Figure: Mass fractions of H2 and CH4 in fuel mixture at varying thermal + input and constant fuel mass flow diff --git a/docs/basics/heat_pump.rst b/docs/basics/heat_pump.rst new file mode 100644 index 000000000..8be8a888a --- /dev/null +++ b/docs/basics/heat_pump.rst @@ -0,0 +1,171 @@ +.. _tespy_basics_heat_pump_label: + +Heat Pump +========= + +.. figure:: /_static/images/basics/heat_pump.svg + :align: center + :alt: Topology of the heat pump + :figclass: only-light + + Figure: Topology of the heat pump + +.. figure:: /_static/images/basics/heat_pump_darkmode.svg + :align: center + :alt: Topology of the heat pump + :figclass: only-dark + + Figure: Topology of the heat pump + +This tutorial is the continuation of the tutorial in the +:ref:`introduction `. First, we have a look at +specification options and modeling flexibility in TESPy as well as some +typical errors, that might occur when using the software. Then we will make a +simple analysis of the COP of the heat pump based on several input parameters. + +Download the full script here: +:download:`heat_pump.py ` + +Flexibility in Modeling +^^^^^^^^^^^^^^^^^^^^^^^ +In TESPy the specifications for components and/or connections are +interchangable in every possible way, provided that the system of equations +representing the plant is well defined. + +For example, instead of the heat provided by the condenser we could specify +the mass flow :code:`m` of the refrigerant. To unset a parameter you need to +set it to :code:`None`. To replace the specification, set the mass flow of +connection c1 to 5 kg/s: + +.. literalinclude:: /../tutorial/basics/heat_pump.py + :language: python + :start-after: [sec_7] + :end-before: [sec_8] + +You can observe, that the heat transferred by the condenser now is a result of +the mass flow imposed. We could do similar things, for example with the heat +sink temperature. We imposed it in our initial set up. Now we want to insert +a compressor with a fixed output to input pressure ratio. In that case, we +cannot choose the condensation temperature but it will be a result of that +specification: + +.. literalinclude:: /../tutorial/basics/heat_pump.py + :language: python + :start-after: [sec_8] + :end-before: [sec_9] + +Or, we have a plant running with data observation running. It tells us the +compressor outlet temperature and we want to know what the efficiency of the +compressor would be, in case we measure :code:`T=97.3` at connection 3. + +.. literalinclude:: /../tutorial/basics/heat_pump.py + :language: python + :start-after: [sec_9] + :end-before: [sec_10] + +Typical Errors +^^^^^^^^^^^^^^ +If you over- or underdetermine the system by specifying too few or too many +parameters, you will get an error message. We could set the heat demand and the +mass flow at the same time. + +.. attention:: + + The two code examples in this section are not included in the downloadable + script! + +.. code-block:: python + + co.set_attr(Q=-1e6) + c1.set_attr(m=5) + + my_plant.solve('design') + +.. error:: + + .. code-block:: bash + + ERROR:root:You have provided too many parameters: 20 required, 21 supplied. Aborting calculation! + Traceback (most recent call last): + File ".\tutorial\basics\heat_pump.py", line 59, in + my_plant.solve('design') + File "c:\users\user\documents\github\tespy\src\tespy\networks\network.py", line 1623, in solve + self.solve_determination() + File "c:\users\user\documents\github\tespy\src\tespy\networks\network.py", line 1749, in solve_determination + raise hlp.TESPyNetworkError(msg) + tespy.tools.helpers.TESPyNetworkError: You have provided too many parameters: 20 required, 21 supplied. Aborting calculation! + +If you make a specification that leads to the correct amount of parameters but +causes a linear dependency in the system of equations, the error message cannot +be that clear to you. To make an easy example, we can set mass flow on the +connections 1 and 2 with the heat demand and the evaporation temperature unset. +In this case the number of equations will be correct, but the specification +obviously does not make any sense. + +.. code-block:: python + + co.set_attr(Q=None) + c1.set_attr(m=5) + c2.set_attr(m=5, T=None) + + my_plant.solve('design') + +.. error:: + + .. code-block:: bash + + ERROR:root:Singularity in jacobian matrix, calculation aborted! Make sure your network does not have any linear dependencies in the parametrisation. Other reasons might be + -> given temperature with given pressure in two phase region, try setting enthalpy instead or provide accurate starting value for pressure. + -> given logarithmic temperature differences or kA-values for heat exchangers, + -> support better starting values. + -> bad starting value for fuel mass flow of combustion chamber, provide small (near to zero, but not zero) starting value. + +.. seealso:: + + For more detailed information about the number of variables involved and + ways of parameter specifications, please go to the + :ref:`TESPy modules section ` inside the Documentation + chapter. + + Another frequent reason for such errors are bad starting values. We have a + tutorial specifically dedicated to this topic + :ref:`here `. + +Parametric Analysis of COP +^^^^^^^^^^^^^^^^^^^^^^^^^^ +For a constant amount of heat production, we will investigate the influence of + +* the source temperature level +* the sink temperature level and +* the isentropic efficiency of the compressor. + +To do this, we import the numpy and matplotlib package and define the ranges +and then iterate over a loop and restart the simulation for every input +parameter. After each loop, we set the respective parameter back to its +original value. We collect the results in lists and can finally make a scatter +plot using matplotlib. + +.. dropdown:: Click to expand to code section + + .. literalinclude:: /../tutorial/basics/heat_pump.py + :language: python + :start-after: [sec_10] + :end-before: [sec_11] + +.. figure:: /_static/images/basics/heat_pump_parametric.svg + :align: center + :alt: Parametric analysis of the heat pump's COP + :figclass: only-light + + Figure: Parametric analysis of the heat pump's COP + +.. figure:: /_static/images/basics/heat_pump_parametric_darkmode.svg + :align: center + :alt: Parametric analysis of the heat pump's COP + :figclass: only-dark + + Figure: Parametric analysis of the heat pump's COP + +The figure shows the results of the COP analysis. The base case is at an +evaporation temperature of 20 °C, the condensation temperature at 80 °C and the +isentropic effficiency of the compressor at 85 %. diff --git a/docs/basics/intro.rst b/docs/basics/intro.rst new file mode 100644 index 000000000..4de5f6234 --- /dev/null +++ b/docs/basics/intro.rst @@ -0,0 +1,181 @@ +.. _tespy_basics_intro_label: + +Introduction +============ + +In this section we provide you with the basics of the TESPy's modeling concept. +TESPy builds up on **components** that are connected using **connections** to +form a topological **network**. The figure below highlights these three core +components of the software at the example of a small heat pump. + +.. figure:: /_static/images/basics/modeling_concept.svg + :align: center + :alt: TESPy's modeling concept + + Figure: TESPy's modeling concept. + +Set up a plant +-------------- + +In order to simulate a plant we start by creating the network +(:py:class:`tespy.networks.network.Network`). The network is the main container +for the model. You need to specify a list of the fluids you require for the +calculation in your plant. For more information on the fluid properties go to +the :ref:`corresponding section ` in the +documentation. + +.. literalinclude:: /../tutorial/basics/heat_pump.py + :language: python + :start-after: [sec_1] + :end-before: [sec_2] + +On top of that, it is possible to specify a unit system and value ranges for +the network's variables. If you do not specify these, TESPy will use SI-units. +We will thus only specify the unit systems, in this case. + +.. literalinclude:: /../tutorial/basics/heat_pump.py + :language: python + :start-after: [sec_2] + :end-before: [sec_3] + +Now you can start to create the components of the network. + +Set up components +----------------- + +The list of components available can be found +:ref:`here `. If you set up a component you +have to specify a (within one network) unique label. Moreover, it is possible +to specify parameters for the component, for example power :math:`P` for a pump +or upper terminal temperature difference :math:`ttd_\mathrm{u}` of a heat +exchanger. The full list of parameters for a specific component is stated in +the respective class documentation. This example uses a compressor, a control +valve two (simple) heat exchangers and a so called cycle closer. + +.. note:: + + Parameters for components are generally optional. Only the component's + label is mandatory. If an optional parameter is not specified by the user, + it will be a result of the plant's simulation. This way, the set of + equations a component returns is determined by which parameters you + specify. You can find all equations in each component's documentation as + well. + +.. literalinclude:: /../tutorial/basics/heat_pump.py + :language: python + :start-after: [sec_3] + :end-before: [sec_4] + + +After creating the components the next step is to connect them in order to form +your topological network. + +Establish connections +--------------------- + +Connections are used to link two components (outlet of component 1 to inlet of +component 2: source to target). If two components are connected with each other +the fluid properties at the source will be equal to the properties at the +target. It is possible to set the properties on each connection in a similar +way as parameters are set for components. The basic specification options are: + +* mass flow (m) +* volumetric flow (v) +* pressure (p) +* enthalpy (h) +* temperature (T) +* a fluid vector (fluid) + +.. seealso:: + + There are more specification options available. Please refer to + the :ref:`connections section ` in the + TESPy modules documentation for detailed information. The specification + options are stated in the connection class documentation, too: + :py:class:`tespy.connections.connection.Connection`. + +After creating the connections, we need to add them to the network. As the +connections hold the information, which components are connected in which way, +we do not need to pass the components to the network. + +.. literalinclude:: /../tutorial/basics/heat_pump.py + :language: python + :start-after: [sec_4] + :end-before: [sec_5] + +.. note:: + + The :code:`CycleCloser` is a necessary component when working with closed + cycles, because a system would always be overdetermined, if, for example, + a mass flow is specified at some point within the cycle. It would propagate + through all of the components, since they have an equality constraint for + the mass flow at their inlet and their outlet. With the example here, that + would mean: **Without the cycle closer** specification of massflow at an + connection would lead to the following set of equations for massflow, which + is an overdetermination: + + .. math:: + + \begin{split} + \dot{m}_1 = &\;\text{5 kg/s}\\ + \dot{m}_1 = &\;\dot{m}_2\\ + \dot{m}_2 = &\;\dot{m}_3\\ + \dot{m}_3 = &\;\dot{m}_4\\ + \dot{m}_4 = &\;\dot{m}_1\\ + \end{split} + + Similarly, this applies to the fluid composition. + + The cycle closer will prompt a warning, if the mass flow and fluid + composition are not equal at its inlet and outlet. + +We can set the component and connection parameters. In this example, we specify +the pressure losses (by outlet to inlet pressure ratio :code:`pr`) in the +condenser and the evaporator as well as the efficiency :code:`eta_s` of the +compressor. On top of that, the heat production of the heat pump can be set +with :code:`Q` for the condenser. Since we are working in **subcritical** +regime in this tutorial, we set the state of the fluid at the evaporator's +outlet to fully saturated steam (:code:`x=1`) and at the condenser's outlet to +fully saturated liqud (:code:`x=0`). On top of that, we want to impose the +condensation and the evaporation temperature levels. Last, we have to specify +the fluid vector at one point in our network. + +.. literalinclude:: /../tutorial/basics/heat_pump.py + :language: python + :start-after: [sec_5] + :end-before: [sec_6] + +.. note:: + + The sign convention for energy transfer by components is always from the + perspective of the component. Energy entering the component means positive + sign, energy leaving the component's system boundary means negative sign. + +Start your calculation +---------------------- + +After building your network, the components and the connections, add the +following line at the end of your script and run it. You can calculate the COP +with the respective component parameters. + +.. literalinclude:: /../tutorial/basics/heat_pump.py + :language: python + :start-after: [sec_6] + :end-before: [sec_7] + +Next steps +---------- + +We highly recommend to check our other basic model examples on how to set up +different standard thermodynamic cycles in TESPy. The heat pump cycle in that +section builds on this heat pump. We will introduce couple of different inputs +and show, how to change the working fluid. The other tutorials show the usage +of more components, for example the combustion chamber and the turbine or a +condenser including the cooling water side of the system. + +In the more advanced tutorials, you will learn, how to set up more complex +plants ste by step, make a design calculation of the plant as well as calculate +offdesign/partload performance. + +In order to get a good overview of the TESPy functionalities, the sections on +the :ref:`TESPy modules ` will guide you in detail. diff --git a/docs/basics/rankine_cycle.rst b/docs/basics/rankine_cycle.rst new file mode 100644 index 000000000..d412e6aa4 --- /dev/null +++ b/docs/basics/rankine_cycle.rst @@ -0,0 +1,252 @@ +.. _tespy_basics_rankine_cycle_label: + +Rankine Cycle +============= + +.. figure:: /_static/images/basics/rankine_cycle.svg + :align: center + :alt: Topology of the rankine cycle + :figclass: only-light + + Figure: Topology of the rankine cycle + +.. figure:: /_static/images/basics/rankine_cycle_darkmode.svg + :align: center + :alt: Topology of the rankine cycle + :figclass: only-dark + + Figure: Topology of the rankine cycle + +Download the full script here: +:download:`rankine.py ` + +Setting up the Cycle +^^^^^^^^^^^^^^^^^^^^ +We will model the cycle including the cooling water of the condenser. For this +start with the :code:`Network` set up we already know. + +.. literalinclude:: /../tutorial/basics/rankine.py + :language: python + :start-after: [sec_1] + :end-before: [sec_2] + +Following, we create the components and connect them. The :code:`Condenser` has +a hot side inlet and outlet as well as a cold side inlet and outlet. The hot +side is indicated by using the index 1 for the inlet and outlet :code:`in1` and +:code:`out1`, the cold side uses the index 2 (:code:`in2` and :code:`out2`). + +Again, for the closed thermodynamic cycle we have to insert a cycle closer. The +cooling water inlet and the cooling water outlet of the condenser are directly +connected to a :code:`Source` and a :code:`Sink` respectively. + +.. literalinclude:: /../tutorial/basics/rankine.py + :language: python + :start-after: [sec_2] + :end-before: [sec_3] + +For the parameters, we predefine the pressure losses in the heat exchangers. +For the condenser, the hot side pressure losses are neglected :code:`pr1=1`, +for the cooling water side we assume pressure loss of 2 % :code:`pr2=0.98`. The +steam generator inflicts a pressure loss of 10 %. + +The turbine and feed pump will have the isentropic efficiency specified. For +the connection parameters, the fluid has to be defined in both the main cycle +and the cooling water system. Furthermore, the live steam temperature, pressure +and mass flow are set. Lastly, we set the condensation pressure level and the +feed and return flow temperature of the cooling water as well as its feed +pressure. + +.. literalinclude:: /../tutorial/basics/rankine.py + :language: python + :start-after: [sec_3] + :end-before: [sec_4] + +After running the simulation, for example, we can observe the temperature +differences at the condenser. Instead of directly setting a pressure value for +condensation, we could also set the upper terminal temperature difference +:code:`ttd_u` instead. It is defined as the condensation temperature to cooling +water return flow temperature. + +.. tip:: + + You will find the documentation of each equation of the components in the + respective seciton of the API documentation. For example, the condenser + :py:class:`tespy.components.heat_exchangers.condenser.Condenser`. + +.. literalinclude:: /../tutorial/basics/rankine.py + :language: python + :start-after: [sec_4] + :end-before: [sec_5] + +After rerunning, we will see that the condensation temperature and pressure +are both automatically calculated by the specified terminal temperature value. + +Assess Electrical Power +^^^^^^^^^^^^^^^^^^^^^^^ +To assess the electrical power output we want to consider the power generated +by the turbine as well as the power required to drive the feed pump. It is +possible to include both of the component's power values in a single electrical +:code:`Bus`. We can do this by importing the +:py:class:`tespy.connections.bus.Bus` class, creating an instance and adding +both components to the bus. + +.. literalinclude:: /../tutorial/basics/rankine.py + :language: python + :start-after: [sec_5] + :end-before: [sec_6] + +.. note:: + + The :code:`Bus` can take components which either produce or consume energy. + Specifying :code:`'base': 'bus'` means, that the efficiency value is + referenced to the electrical power + + .. math:: + + \dot{W} = \dot{W}_\text{el} \cdot \eta + + while specifying :code:`'base': 'component'` (default) takes the component's + power as base value. + + .. math:: + + \dot{W}_\text{el} = \dot{W} \cdot \eta + +The results for the bus are printed separately. Observe, that the steam +turbine's electrical power production (:code:`bus value`) is lower than the +:code:`component value`, while it is inverted for the feed pump. + +You can also set the total desired power production of the system, for example +replacing the mass flow specification at connection 1: + +.. literalinclude:: /../tutorial/basics/rankine.py + :language: python + :start-after: [sec_6] + :end-before: [sec_7] + +Analyze Efficiency and Powergeneration +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In this section, we will analyze the power production and the efficiency +of the cycle, given constant steam mass flow and with varying values for the + +- live steam pressure, +- live steam temperature and +- cooling water temperature level. + +To do that, we are using a very similar setup as has been used in the +:ref:`heat pump tutorial `. For the feed water +temperature level we want to set the change in temperature at the condenser +to a constant value. Also, we have to unset the power generation specification +again and use a constant mass flow instead. With :code:`iterinfo=False` we +can disable the printout of the convergence history. + +.. dropdown:: Click to expand to code section + + .. literalinclude:: /../tutorial/basics/rankine.py + :language: python + :start-after: [sec_7] + :end-before: [sec_8] + +.. figure:: /_static/images/basics/rankine_parametric.svg + :align: center + :alt: Parametric analysis of the efficiency and power output + :figclass: only-light + + Figure: Parametric analysis of the efficiency and power output + +.. figure:: /_static/images/basics/rankine_parametric_darkmode.svg + :align: center + :alt: Parametric analysis of the efficiency and power output + :figclass: only-dark + + Figure: Parametric analysis of the efficiency and power output + +Partload Simulation +^^^^^^^^^^^^^^^^^^^ +In the partload simulation part, we are starting with a specific design of the +plant and calculate the partload perfomance with some assumptions on the +component's individual behavior. The table below summarizes the assumptions, +which we will keep as simple as possible in this moment. For more insights +have a look at the step by step +:ref:`heat pump tutorial ` or at the +:ref:`Network documentation `. + ++-----------+---------------------------+-------------------------------+ +| Component | Assumptions | Settings | ++===========+===========================+===============================+ +| Turbine | cone law applies | unset inlet pressure and | +| | | apply cone law | ++-----------+---------------------------+-------------------------------+ +| Condenser | constant heat transfer | unset terminal temperature | +| | coefficient | difference and set heat | +| | | transfer coefficient | ++-----------+---------------------------+-------------------------------+ +| Cooling | constant volumetric flow | unset return temperature | +| water | | value and set volumetric flow | ++-----------+---------------------------+-------------------------------+ + +With these specifications, the following physics are applied to the model: + +- Due to the constant volumetric flow of water, the temperature of the cooling + water returning from the condenser will react to the total heat transferred + in the condensation: Increased heat transfer means incresing temperature, + decreased heat transfer means decreased temperature. +- The constant heat transfer coefficient of the condenser will calculate the + condensation temperature (and therefore pressure) based on the temperature + regime in the cooling water side: + + - Increase in temperature for the cooling water leads to increased + condensation temperature (at constant heat transfer). + - Increase in heat transfer means increase in necessary temperature + difference at the condenser (at constant cooling water inlet temperature). + +- The cone law is a mathematical model to predict the pressure at the turbine's + inlet based on the deviation from the design conditions. Generally, + increased mass flow leads to higher inlet pressure (at constant inlet + temperature and constant outlet pressure). However, this equation is more + complex, since a lot more parameters are involved compared to the other + equations applied. + +In order to apply these specifications, we can use the :code:`design` and +:code:`offdesign` keywords. The keyword :code:`design` unsets the specified +data in the list in an offdesign calculation. The keyword :code:`offdesign` +automatically sets the respective parameter for the offdesign calculation. In +case the specification refers to a value, the value is taken from the design +mode calculation. In the example, the main condenser's kA value is calculated +in the design simulation and its value will be kept constant through the +offdesign simulations. + +.. literalinclude:: /../tutorial/basics/rankine.py + :language: python + :start-after: [sec_8] + :end-before: [sec_9] + +We have to save the design state of the network and run the :code:`solve` +method with the :code:`design_path` specified. + +.. literalinclude:: /../tutorial/basics/rankine.py + :language: python + :start-after: [sec_9] + :end-before: [sec_10] + +Finally, we can alter the mass flow from its design value of 20 kg/s to only +50 % of its value. In this example, we calculate the efficiency and plot it. + +.. literalinclude:: /../tutorial/basics/rankine.py + :language: python + :start-after: [sec_10] + :end-before: [sec_11] + +.. figure:: /_static/images/basics/rankine_partload.svg + :align: center + :alt: Partload electric efficiency of the rankine cycle + :figclass: only-light + + Figure: Partload electric efficiency of the rankine cycle + +.. figure:: /_static/images/basics/rankine_partload_darkmode.svg + :align: center + :alt: Partload electric efficiency of the rankine cycle + :figclass: only-dark + + Figure: Partload electric efficiency of the rankine cycle diff --git a/docs/benchmarks.rst b/docs/benchmarks.rst new file mode 100644 index 000000000..3d3f13852 --- /dev/null +++ b/docs/benchmarks.rst @@ -0,0 +1,54 @@ +Benchmarks +========== +To ensure credibility as well as reproducibility for the software, several +measures are taken. The most important information is listed below: + +Model Validation +---------------- +TESPy has been used to model several different research and engineering +applications. In the paper on integration of generic exergy analysis in TESPy +:cite:`Witte2022` three models have been built from literature sources: A +solar thermal power plant, a supercritical CO2 brayton cycle as well as a +refrigeration machine using air as working fluid. + +For the solar thermal power plant we have created a full model of the plant +using a standard industry software in parallel. **The comparison showed** +**identical results**. For the other two applications we have compared the +results of the TESPy model with the data published in the respective research +paper and found very well matching results. Differences can be explained by +different implementations of the fluid property back-end. + +Finally, in the extension of the exergy analysis to chemical exergy +:cite:`Hofmann2022` we have also compared results of the CGAM process +:cite:`Valero1994` modeled in TESPy with a full model using industry software +and with the data provided from literature as well :cite:`Bejan1996`. + +The code for the full models is accessible open source on GitHub: + +- `So called "Solar Energy Generating System" `__ +- `Supercritical CO2 power cycle `__ +- `Air refrigeration machine `__ +- `CGAM process `__ + + +Unit testing +------------ +On top of the full model validation, the software includes full unit testing. +Here, single features of the software are tested by comparing the result the +software provides with the result we would expect when manually modeling that +feature. For example, we set up a turbine and check, whether the isentropic +efficiency specification in the TESPy component matches the results that is +expected doing the same process manually. This is done for all modules of the +software. + +Continuous Integration +---------------------- +TESPy has a +`Continuous Integration `__ +pipeline. The unit tests and the full model tests are automatically run +whenever changes to the source code of the software are made. By this we can +ensure, that changes in the code do not break with existing features or +invalidate results of the existing models. + +For more information on how to run the tests please see the +:ref:`how to develop ` section. diff --git a/docs/conf.py b/docs/conf.py index 0c81e8ae7..b3643c520 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,20 +1,7 @@ # -*- coding: utf-8 -*- -# -# oemof documentation build configuration file, created by -# sphinx-quickstart on Thu Dec 18 16:57:35 2014. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. import os import sys -import sphinx_rtd_theme import tespy @@ -25,125 +12,80 @@ # -- General configuration ------------------------------------------------ -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.autosummary', - 'sphinx.ext.imgmath', + 'sphinx.ext.coverage', + 'sphinx.ext.doctest', + 'sphinx.ext.extlinks', + 'sphinx.ext.ifconfig', 'sphinx.ext.napoleon', + 'sphinx.ext.todo', 'sphinx.ext.viewcode', - 'sphinxcontrib.bibtex' + 'sphinx_copybutton', + 'sphinx_design', + 'sphinxcontrib.bibtex', ] -bibtex_bibfiles = ['references.bib'] - -numpydoc_show_class_members = False - -# -autoclass_content = 'both' - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'tespy' -copyright = u'2018-2020, Francesco Witte' -author = u'Francesco Witte' +# landing page +# master_doc = 'contents' +# names, years, etc +project = 'TESPy' +year = '2022' +author = 'Francesco Witte' +copyright = '{0}, {1}'.format(year, author) -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# # The short X.Y version. version = tespy.__version__.split(' ')[0] # The full version, including alpha/beta/rc tags. release = tespy.__version__ -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# The suffix of source filenames. +source_suffix = '.rst' +# folder for templates +templates_path = ['_templates'] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build', 'whatsnew/*'] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False +exclude_patterns = ['_build'] # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' +pygments_style = 'trac' -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# show all class members +# numpydoc_show_class_members = False -# If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +# place for bibtex references +bibtex_bibfiles = ['references.bib'] +# links to github +github_repo_url = "https://github.com/oemof/tespy/" +extlinks = { + "issue": (f"{github_repo_url}/issues/%s", "#%s"), # noqa: WPS323 + "pr": (f"{github_repo_url}/pull/%s", "PR #%s"), # noqa: WPS323 + "commit": (f"{github_repo_url}/commit/%s", "%s"), # noqa: WPS323 +} # -- Options for HTML output ---------------------------------------------- -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -#html_theme = 'bizstyle' - -html_theme = "sphinx_rtd_theme" - -html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = { -# "sidebarwidth": "25em", -# "documentwidth":"50em", -# "pagewidth": "75em", -# } - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# The theme to use for HTML and HTML Help pages. +html_theme = 'furo' # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None + # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +html_short_title = '%s-%s' % (project, version) -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None -html_logo = './api/_images/logo_tespy_mid.svg' +# Some more stuff +html_use_smartypants = True +html_last_updated_fmt = '%b %d, %Y' +html_split_index = False # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 @@ -153,55 +95,38 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['./_build/_static'] - -html_css_files = ['css/custom.css', ] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -#html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +html_static_path = ['_static'] +html_css_files = [ + 'css/custom.css', +] +# html_additional_pages = { +# "index": "index.html" +# } + +html_sidebars = { + '**': [ + 'sidebar/brand.html', + 'sidebar/search.html', + 'sidebar/scroll-start.html', + 'sidebar/navigation.html', + 'sidebar/ethical-ads.html', + 'sidebar/scroll-end.html', + 'sidebar/variant-selector.html', + ], +} -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +html_theme_options = { + "light_logo": "./images/logo_tespy_mid.svg", + "dark_logo": "./images/logo_tespy_mid_darkmode.svg", +} -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' +napoleon_use_ivar = True +napoleon_use_rtype = False +napoleon_use_param = False -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# copybutton configuration +copybutton_prompt_text = r'>>> |\.\.\. ' +copybutton_prompt_is_regexp = True # Output file base name for HTML help builder. htmlhelp_basename = 'tespy_doc' @@ -354,3 +279,9 @@ # If false, no index is generated. #epub_use_index = True + +# -- Options for linkcheck ---------------------------------------------- + +linkcheck_ignore = [ + r'https://doi.org/10.2172/95571', +] diff --git a/docs/developing_tespy.rst b/docs/development/how.rst similarity index 66% rename from docs/developing_tespy.rst rename to docs/development/how.rst index ed7fb1990..1d0647d3e 100644 --- a/docs/developing_tespy.rst +++ b/docs/development/how.rst @@ -1,42 +1,11 @@ -.. _developing_tespy_label: +.. _tespy_development_how_label: -Developing TESPy -================ - -TESPy has been developed mainly by Francesco Witte at the University of Applied -Sciences Flensburg. We hope that many people can make use of this project and -that it will be a community driven project in the future, as users might demand -special components or flexible implementations of characteristics, custom -equations, basically what ever you can think of. - -We want to invite you to join the developing process and share your ideas. Your -solutions may help other users as well. Contributing to the development of -TESPy may help other people and it improves the quality of your code as it will -be reviewed by other developers. - -The easiest way of joining the developing process is by improving the -documentation. If you spot mistakes or think, the documentation could be more -precise or clear in some sections, feel free to fix it and create a pull -request on the github repository. - -Another simple first step is to program your own custom subsystems and share -them in the community. For a good start just look into our tutorial -:ref:`How do I create custom subsystems `. - -A third, highly appreciated way for you to contribute is the provision of new -and/or improved equations, maybe even whole characteristics for single -components, such as compressor maps, characteristics for turbine efficiency or -heat transfer coefficients etc.. +How can I contribute? +===================== You will find the most important information concerning the development process in the following sections. If you have any further questions feel free to -contact us, we are looking forward to hearing -from you! - -.. contents:: - :depth: 1 - :local: - :backlinks: top +contact us, we are looking forward to hearing from you! Install the developer version ----------------------------- @@ -48,7 +17,7 @@ repository and install development requirements with pip. .. code:: bash - git clone https://github.com/YOUR_GITHUB_USERNAME/tespy.git + git clone https://github.com/YOUR_GITHUB_USERNAME/tespy.git cd tespy pip install -e .[dev] @@ -60,55 +29,15 @@ the example below). .. code:: bash - git remote add upstream https://github.com/oemof/tespy.git - git fetch upstream - git pull upstream dev --rebase + git remote add upstream https://github.com/oemof/tespy.git + git fetch upstream + git pull upstream dev --rebase Use the :code:`--rebase` comand to avoid merge commits fo every upstream pull. If you want to make changes to tespy, checkout a new branch from your local dev branch. Make your changes, commit them and create a PR on the oemof/tespy dev branch. -Your contribution ------------------ - -There are different ways you can contribute - -Contribute to the documentation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If you come across typos or grammatical mistakes or want to improve -comprehensibility of the documentation, make your adjustments or suggestions -and create a pull request for the dev branch. We appreciate your contribution! - -Improve or add new equations -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The components equations represent the behavior of each component. Are we -missing any equations? Or do you see possibilities to improve the formulation? -Add them to your code and create a pull request on the dev branch. - -Share your subsystems -^^^^^^^^^^^^^^^^^^^^^ - -You have encountered component groups that are frequently required? Create a -subsystem to simplify your own work and share your subsystem by adding it to -the tespy.components.subsystems file. - -For both, **the equations and the subsystems**, please provide the docstring -and maybe inline comments, if you want to make the code more comprehensible. In -general, your code should fit to the :ref:`style_guidlines_label`, a complete -documentation is only required, if the code will be added to TESPy permanently. - -Add component characteristics -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The component characteristics represent large added value for your calculation. -If you have detailed information on components offdesign behavior - even for -specific cases - it will improve the results. Every user can benefit from this -knowlegde and thus we are very happy to discuss about the implementation of new -characteristics. - Collaboration with pull requests -------------------------------- @@ -207,8 +136,8 @@ Docstrings ^^^^^^^^^^ We decided to use the style of the numpydoc docstrings. See the following -link for an -`example `_. +link for more information +`numpy docstrings `_. Code commenting diff --git a/docs/development/what.rst b/docs/development/what.rst new file mode 100644 index 000000000..1e60844cb --- /dev/null +++ b/docs/development/what.rst @@ -0,0 +1,56 @@ +.. _tespy_development_what_label: + +What can I contribute? +====================== +TESPy has been developed mainly by Francesco Witte at the University of Applied +Sciences Flensburg - and a lot of free time. We hope that many people can make +use of this project and that it will be a community driven project in the +future, as users might demand special components or flexible implementations of +characteristics, custom equations, basically what ever you can think of. + +Therefore we would like to invite you to contribute in this process, share your +ideas and experience and maybe start developing the software. Your solutions +may help other users as well. Contributing to the development of TESPy is easy +and will help the development team and all other users of the software. If you +start to develop features it may also improve the quality of your code as it +will be reviewed by other developers. + +There are a variety of different ways you can contribute to the development, +amongst others, these may be: + +Contribute to the documentation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The easiest way of joining the developing process is by improving the +documentation. If you spot mistakes or think, the documentation could be more +precise or clear in some sections, feel free to fix it and create a pull +request on the github repository. + +If you come across typos or grammatical mistakes or want to improve +comprehensibility of the documentation, make your adjustments or suggestions +and create a pull request for the dev branch. We appreciate your contribution! + +Share your projects +^^^^^^^^^^^^^^^^^^^ +You have used the software in your research paper or project, maybe even in a +real world application? We would love to feature your project on our +:ref:`Example Applications ` page. Please reach out to +us by opening a new issue on our github page. + +Add new component equations +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The components equations represent the behavior of each component. Do you miss +equations? Open a discussion on the github discussions page or add them to your +fork of TESPy and create a pull request on the dev branch. + +Add component characteristics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Another highly appreciated way for you to contribute is the provision of new +and/or improved characteristics for single components, such as compressor +efficiency maps, characteristics for turbine efficiency or heat transfer +coefficients etc.. + +The component characteristics represent large added value for your calculation. +If you have detailed information on components offdesign behavior - even for +specific cases - it will improve the results. Every user can benefit from this +knowledge and thus we are very happy to discuss about the implementation of new +characteristics. diff --git a/docs/examples.rst b/docs/examples.rst new file mode 100644 index 000000000..2fecda194 --- /dev/null +++ b/docs/examples.rst @@ -0,0 +1,47 @@ +.. _tespy_examples_label: + +~~~~~~~~~~~~~~~~~~~~ +Example Applications +~~~~~~~~~~~~~~~~~~~~ + +On this page we collect example applications of TESPy. If you want to add your +example here, please open an issue on GitHub and let us know. The source code +of the application should be accessible freely so other users can learn from +your project. + +.. card:: + :link: https://github.com/fwitte/chp_orc + + **Combined Heat and Power Organic Rankine Cycle** + ^^^ + + .. grid:: 2 + + .. grid-item:: + + Starting from well production information for a geothermal energy + reservoir over a lifetime of 40 years, the development of the + electrical power output of an ORC is monitored within different + designs of the plant. The geothermal heat source is exploted to + provide heat to a district heating system and the residual heat is + used to operate the orc cycle. + + .. grid-item:: + + .. image:: /_static/images/examples/GRC_electrical_power_output.svg + :align: center + :alt: Development of the Electrical Power Output of the ORC for a District with 2 MW Peak Heat Load + :class: only-light + + .. image:: /_static/images/examples/GRC_electrical_power_output_darkmode.svg + :align: center + :alt: Development of the Electrical Power Output of the ORC for a District with 2 MW Peak Heat Load + :class: only-dark + + +++ + Title: Computational Modeling of Organic Rankine Cycle Combined Heat and + Power for Sedimentary Geothermal Exploitation + + Authors: Nicholas Fry, Jessica Eagle-Bluestone, Francesco Witte + + Reference: diff --git a/docs/first_steps.rst b/docs/first_steps.rst deleted file mode 100644 index 119f546a9..000000000 --- a/docs/first_steps.rst +++ /dev/null @@ -1,183 +0,0 @@ -First steps -=========== - -In this section we provide you with a very simple example as firsts steps in -using TESPy. The model used in this introduction is shown the figure. It -consists of a central heating plant and a consumer, represented by a heat -exchanger with a control valve. - -.. figure:: /api/_images/intro_district_heating_scheme.svg - :align: center - - Figure: Topology of the simplest district heating system. - -Set up a plant --------------- - -In order to simulate a plant we start by creating a network -(:py:class:`tespy.networks.network.Network`). The network is the main container -for the model. You need to specify a list of the fluids you require for the -calculation in your plant. For more information on the fluid properties go to -the :ref:`corresponding section ` in TESPy -modules. - -.. code-block:: python - - from tespy.networks import Network - - # create a network object with water as fluid - fluid_list = ['water'] - my_plant = Network(fluids=fluid_list) - -On top of that, it is possible to specify a unit system and value ranges for -the network's variables. If you do not specify these, TESPy will use SI-units. -The specification of the **value range** is used to **improve convergence** -**stability**, in case you are dealing with **fluid mixtures**, e.g. using -combustion. We will thus only specify the unit systems, in this case. - -.. code-block:: python - - # set the unitsystem for temperatures to °C and for pressure to bar - my_plant.set_attr(T_unit='C', p_unit='bar', h_unit='kJ / kg') - -Now you can start to create the components of the network. - -Set up components ------------------ - -The list of components available can be found -:ref:`here `. If you set up a component you have -to specify a (within one network) unique label. Moreover, it is possible to -specify parameters for the component, for example power :math:`P` for a turbine -or upper terminal temperature difference :math:`ttd_\mathrm{u}` of a heat -exchanger. The full list of parameters for a specific component is stated in -the respective class documentation. The example uses pipes, a control valve and -a heat exchanger. The definition of the parameters available can be found here: - -- :py:class:`tespy.components.piping.pipe.Pipe` -- :py:class:`tespy.components.piping.valve.Valve` -- :py:class:`tespy.components.heat_exchangers.simple.HeatExchangerSimple` - -.. note:: - - Parameters for components are generally optional. Only the component's - label is mandatory. If an optional parameter is not specified by the user, - it will be a result of the plant's simulation. This way, the set of - equations a component returns is determined by which parameters you - specify. You can find all equations in the components documentation as - well. - -.. code-block:: python - - from tespy.components import ( - Sink, Source, Pipe, Valve, HeatExchangerSimple) - - # sources & sinks (central heating plant) - so = Source('heat source output') - si = Sink('heat source input') - - # consumer - cons = HeatExchangerSimple('consumer') - cons.set_attr(Q=-10000, pr=0.98) # Q in W - val = Valve('valve') - val.set_attr(pr=1) # pr - pressure ratio (output/input pressure) - - # pipes - pipe_feed = Pipe('pipe_feed') - pipe_back = Pipe('pipe_back') - - pipe_feed.set_attr(ks=0.0005, # pipe's roughness in meters - L=100, # length in m - D=0.06, # diameter in m - kA=10, # area independent heat transfer coefficient kA in W/K - Tamb=10) # ambient temperature of the pipe environment (ground temperature) - pipe_back.set_attr(ks=0.0005, - L=100, - D=0.06, - kA=10, - Tamb=10) - -After creating the components the next step is to connect them in order to form -your topological network. - -Establish connections ---------------------- - -Connections are used to link two components (outlet of component 1 to inlet of -component 2: source to target). If two components are connected with each other -the fluid properties at the source will be equal to the properties at the -target. It is possible to set the properties on each connection in a similar -way as parameters are set for components. The basic specification options are: - - * mass flow (m) - * volumetric flow (v) - * pressure (p) - * enthalpy (h) - * temperature (T) - * a fluid vector (fluid) - -.. note:: - - There are more specification options available. Please refer to - the :ref:`connections section ` in the TESPy - modules chapter for detailed information. The specification options are - stated in the - connection class documentation, too: - :py:class:`tespy.connections.connection.Connection`. - -After creating the connections, we need to add them to the network. As the -connections hold the information, which components are connected in which way, -we do not need to pass the components to the network. - -The connection parameters specified in the example case, are inlet and outlet -temperature of the system as well as the inlet pressure. The pressure losses in -the pipes, the consumer and the control valve determine the pressure at all -other points of the network. The enthalpy is calculated from given temperature -and heat losses in the pipes. Additionally we have to specify the fluid vector -at one point in our network. - -.. code-block:: python - - from tespy.connections import Connection - - # connections of the disctrict heating system - so_pif = Connection(so, 'out1', pipe_feed, 'in1') - - pif_cons = Connection(pipe_feed, 'out1', cons, 'in1') - cons_val = Connection(cons, 'out1', val, 'in1') - - val_pib = Connection(val, 'out1', pipe_back, 'in1') - pib_si = Connection(pipe_back, 'out1', si, 'in1') - - # this line is crutial: you have to add all connections to your network - my_plant.add_conns(so_pif, pif_cons, cons_val, val_pib, pib_si) - - so_pif.set_attr(T=90, p=15, fluid={'water': 1}) - cons_val.set_attr(T=60) - -Start your calculation ----------------------- - -After building your network, the components and the connections, add the -following line at the end of your script and run it: - -.. code-block:: python - - my_plant.solve(mode='design') - my_plant.print_results() - -We highly recommend to check our step-by-step -:ref:`tutorial ` on how to set up a heat pump (see -figure below) in TESPy. You will learn, how to set up and design a plant as -well as calculate offdesign/partload performance. - -.. figure:: /api/_images/tutorial_heat_pump.svg - :align: center - - Figure: Topology of a heat pump - -Additional examples are provided in the -:ref:`examples section `. - -In order to get a good overview of the TESPy functionalities, the sections on -the :ref:`TESPy modules ` will guide you in detail. diff --git a/docs/index.rst b/docs/index.rst index 68c46cc0a..3bd4a5b96 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -2,28 +2,45 @@ .. include:: introduction.rst +.. toctree:: + :maxdepth: 2 + :hidden: -Contents -======== + introduction .. toctree:: :maxdepth: 2 + :caption: User Guide + :hidden: - introduction installation - first_steps + basics + tutorials + examples regular_meeting - tutorials_examples - tespy_modules - tespy_analyses - developing_tespy + +.. toctree:: + :maxdepth: 2 + :caption: Documentation + :hidden: + + modules + benchmarks + api whats_new zliterature - api -Indices and tables -================== +.. toctree:: + :maxdepth: 2 + :caption: Advanced Features + :hidden: + + advanced/exergy + +.. toctree:: + :maxdepth: 2 + :caption: Contribute to TESPy + :hidden: -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` + development/what + development/how diff --git a/docs/installation.rst b/docs/installation.rst index b7e2976fa..ad8cecd3c 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -4,109 +4,68 @@ Installation and setup ###################### -.. contents:: - :depth: 1 - :local: - :backlinks: top +Following you find guidelines for the installation process for linux and +windows. TESPy is a Python package, thus it requires you to have Python 3 +installed. +.. tab-set:: -Following you find guidelines for the installation process for different -operation systems. + .. tab-item:: Linux -Linux -===== + **Installing Python 3** -Installing Python 3 -------------------- + Most Linux distributions will have Python 3 in their repository. Use the + specific software management to install it, if it is not yet installed. If + you are using Ubuntu/Debian try executing the following code in your + terminal: -TESPy is a Python package, thus it requires you to have Python 3 installed. -Most Linux distributions will have Python 3 in their repository. Use the -specific software management to install it. If you are using Ubuntu/Debian try -executing the following code in your terminal: + .. code:: console -.. code:: console + sudo apt-get install python3 - sudo apt-get install python3 + You can also download different versions of Python via + https://www.python.org/downloads/. -You can also download different versions of Python via -https://www.python.org/downloads/. + **Having Python 3 installed** -Having Python 3 installed -------------------------- + We recommend installting TESPy within a virtual Python enviroment an not + into the base, system wide Python installation. On Linux you can use + virtualenv to do so. -.. code:: console + 1. Install virtualenv using the package management of your Linux distribution, + pip install or install it from source + (`see virtualenv documentation `_) + 2. Open terminal to create and activate a virtual environment by typing: - pip install tespy + .. code-block:: console -To use pip you have to install the pypi package. Normally pypi is part of your -virtual environment. + virtualenv -p /usr/bin/python3 your_env_name + source your_env_name/bin/activate -.. _virtualenv_label: + 3. In terminal type: :code:`pip install tespy` -Using virtualenv instead of system wide Python ----------------------------------------------- + Warning: If you have an older version of virtualenv you should update pip + :code:`pip install --upgrade pip`. -Instead of installing TESPy with pip to your system Python, you can instead -install TESPy to a virtual Python environment. + **Using Conda** - 1. Install virtualenv using the package management of your Linux distribution, - pip install or install it from source - (`see virtualenv documentation `_) - 2. Open terminal to create and activate a virtual environment by typing: + Alternatively you can use conda for enviroment and package management. You + can follow the installation instructions for windows users. - .. code-block:: console + .. tab-item:: Windows - virtualenv -p /usr/bin/python3 your_env_name - source your_env_name/bin/activate + For windows we recommend using conda as package manager. You can download a + light weight open source variant of conda: "miniforge3". - 3. In terminal type: :code:`pip install tespy` + 1. Download latest `miniforge3 `__ + for Python 3.x (64 or 32 bit). + 2. Install miniforge3 + 3. Open "miniforge prompt" to manage your virtual environments. You can + create a new environment and acivate it by -Warning: If you have an older version of virtualenv you should update pip -:code:`pip install --upgrade pip`. + .. code-block:: console -.. _tespy_installation_windows_label: + conda create -n tespy-env python=3.9 + activate tespy-env -Windows -======= - -Having Python 3 installed -------------------------- - -If you already have a working Python 3 environment you can install TESPy by -using pip. We recommend you installing the package in a virtual environment. -You can use virtualenv (:ref:`see here for instructions `) -or a virtual environment e.g. in :ref:`Anaconda `. - -.. code:: console - - pip install tespy - -If you encounter any errors within the installation of the package, please let -us know by opening an issue on our GitHub repository. Also, if pip is not part -of your python environment, you have to install the pypi package. - -.. _anaconda_label: - -Using Anaconda --------------- - - 1. Download latest `Anaconda `_ - for Python 3.x (64 or 32 bit). - 2. Install Anaconda - 3. Open 'Anaconda Prompt' to create and activate a virtual environment by - typing: - - .. code-block:: console - - conda create -n yourenvname python=3.x - activate yourenvname - - 4. In the active Anaconda Prompt type: :code:`pip install tespy` - - -Mac OSX -======= - -Installation instructions for Mac OSX are not available, yet. If you want to -share your knowledge on the installation and fill this gap, feel free to -contact us. + 4. In the active prompt type: :code:`pip install tespy` diff --git a/docs/introduction.rst b/docs/introduction.rst index 40d9ddfc7..dbe0d6379 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -8,8 +8,14 @@ plants, district heating systems or heat pumps. It is an external extension module within the `Open Energy Modeling Framework `_ and can be used as a standalone package. -.. figure:: /api/_images/logo_tespy_big.svg - :align: center +.. image:: /_static/images/logo_tespy_big.svg + :align: center + :class: only-light + + +.. image:: /_static/images/logo_tespy_big_darkmode.svg + :align: center + :class: only-dark With the TESPy package you are able to calculate stationary operation in order to design the process of your plant. From that point it is possible to @@ -36,11 +42,6 @@ Key Features component groups * **Postprocessing** features like exergy analysis and fluid property plotting -.. contents:: - :depth: 1 - :local: - :backlinks: top - Quick installation ================== @@ -55,19 +56,17 @@ We provide more detailed :ref:`installation instructions `, too. If you want to use the latest features, you might want to install the -**developer version**. See section -:ref:`Developing TESPy ` for more information. +**developer version**. See +:ref:`this section ` for more information. Getting into TESPy ================== For a good start on how TESPy works and how you can use it, we provide some -examples at the :ref:`examples section `. On top of that, -there is a step-by-step :ref:`tutorial ` on how to -model a heat pump in TESPy. - -The :ref:`TESPy modules section ` provides you -with all important information on the different modules of TESPy. +:ref:`basic ` and :ref:`advanced ` +tutorials in the User Guide section. The +:ref:`modules ` section provides you with in depth +information on the different modules of TESPy. Citation ======== @@ -79,7 +78,9 @@ As TESPy is a free software, we kindly ask that you add a reference to TESPy if you use the software for your scientific work. Please cite the article with the BibTeX citation below. -BibTeX citation:: +BibTeX citation + +.. code:: @article{Witte2020, doi = {10.21105/joss.02178}, @@ -100,22 +101,4 @@ zenodo. Find your version here: https://doi.org/10.5281/zenodo.2555866. License ======= -Copyright (c) 2017-2021 oemof developer group - -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. +.. include:: ../LICENSE diff --git a/docs/modules.rst b/docs/modules.rst new file mode 100644 index 000000000..bd96435e5 --- /dev/null +++ b/docs/modules.rst @@ -0,0 +1,88 @@ +.. _tespy_modules_label: + +~~~~~~~~~~~~~ +TESPy modules +~~~~~~~~~~~~~ + +The following sections give a detailed overview on the modules of TESPy. This +includes all important settings of networks, components and connections as well +as the underlying functionalities of the software. + +.. toctree:: + :maxdepth: 1 + :glob: + :hidden: + + modules/networks.rst + modules/components.rst + modules/connections.rst + modules/characteristics.rst + modules/fluid_properties.rst + modules/ude.rst + + +.. grid:: 2 + :gutter: 1 + + .. grid-item-card:: Network + :link: tespy_modules_networks_label + :link-type: ref + + .. image:: /_static/images/basics/modeling_concept.svg + + .. grid-item-card:: Components and Component Groups + :link: tespy_modules_components_label + :link-type: ref + + .. image:: /_static/images/modules/subsystem_waste_heat_generator.svg + :class: only-light + + .. image:: /_static/images/modules/subsystem_waste_heat_generator_darkmode.svg + :class: only-dark + +.. grid:: 2 + :gutter: 1 + + .. grid-item-card:: Connections + :link: tespy_modules_connections_label + :link-type: ref + + .. image:: /_static/images/modules/connections.svg + :class: only-light + + .. image:: /_static/images/modules/connections_darkmode.svg + :class: only-dark + + .. grid-item-card:: Characteristics + :link: tespy_modules_characteristics_label + :link-type: ref + + .. image:: /_static/images/modules/characteristics.svg + :class: only-light + + .. image:: /_static/images/modules/characteristics_darkmode.svg + :class: only-dark + + +.. grid:: 2 + :gutter: 1 + + .. grid-item-card:: Fluid Properties + :link: tespy_fluid_properties_label + :link-type: ref + + .. image:: /_static/images/modules/fluid_properties.svg + :class: only-light + + .. image:: /_static/images/modules/fluid_properties_darkmode.svg + :class: only-dark + + .. grid-item-card:: User Defined Equations + :link: tespy_ude_label + :link-type: ref + + .. image:: /_static/images/modules/ude.svg + :class: only-light + + .. image:: /_static/images/modules/ude_darkmode.svg + :class: only-dark diff --git a/docs/tespy_modules/characteristics.rst b/docs/modules/characteristics.rst similarity index 98% rename from docs/tespy_modules/characteristics.rst rename to docs/modules/characteristics.rst index fbb68e2b4..22130803b 100644 --- a/docs/tespy_modules/characteristics.rst +++ b/docs/modules/characteristics.rst @@ -1,3 +1,5 @@ +.. _tespy_modules_characteristics_label: + Characteristics =============== @@ -6,7 +8,7 @@ implementation. There two different types of characteristics available in TESPy: lines (:py:class:`CharLine `) and maps (:py:class:`CharMap `). The default characteristics available are to be found in the -:py:mod:`tespy.data` module documentation. +:ref:`tespy_data_label` documentation. Characteristic lines -------------------- @@ -94,7 +96,7 @@ Your custom definitions of characteristic lines go into the The :code:`char_lines.json` should have names for identification of the characteristic lines on the first level. On the second level the x and y data are assigned to the name of the characteristic line. The x and y data must be -stated as list. +stated as lists. .. code-block:: json diff --git a/docs/tespy_modules/components.rst b/docs/modules/components.rst similarity index 63% rename from docs/tespy_modules/components.rst rename to docs/modules/components.rst index d46c0caf8..385eaa959 100644 --- a/docs/tespy_modules/components.rst +++ b/docs/modules/components.rst @@ -1,9 +1,11 @@ +.. _tespy_modules_components_label: + Components ========== -In this section we will introduce you into the details of component +In this section we will introduce you to the details of component parametrisation and component characteristics. At the end of the section we -show you, how to create custom components. +show you how to create custom components. List of components ------------------ @@ -13,50 +15,51 @@ well as the equations. - Basics - * :py:class:`Cycle closer` - * :py:class:`Sink ` - * :py:class:`Source ` - * :py:class:`Subsystem interface ` + * :py:class:`Cycle closer` + * :py:class:`Sink ` + * :py:class:`Source ` + * :py:class:`Subsystem interface ` - Combustion - * :py:class:`Combustion chamber ` - * :py:class:`Diabatic combustion chamber ` - (Advanced version of combustion chamber, featuring heat losses and - pressure drop) - * :py:class:`Combustion engine ` + * :py:class:`Combustion chamber ` + * :py:class:`Diabatic combustion chamber ` + (Advanced version of combustion chamber, featuring heat losses and pressure + drop) + * :py:class:`Combustion engine ` - Heat exchangers - * :py:class:`Simplified heat exchanger ` - * :py:class:`Solar collector ` - * :py:class:`Parabolic trough ` - * :py:class:`Heat exchanger ` - * :py:class:`Condenser ` - * :py:class:`Desuperheater ` + * :py:class:`Simplified heat exchanger ` + * :py:class:`Solar collector ` + * :py:class:`Parabolic trough ` + * :py:class:`Heat exchanger ` + * :py:class:`Condenser ` + * :py:class:`Desuperheater ` - Nodes - * :py:class:`Droplet separator ` - * :py:class:`Drum ` - * :py:class:`Merge ` - * :py:class:`Separator ` - * :py:class:`Splitter ` + * :py:class:`Droplet separator ` + * :py:class:`Drum ` + * :py:class:`Merge ` + * :py:class:`Separator ` + * :py:class:`Splitter ` - Piping - * :py:class:`Pipe ` - * :py:class:`Valve ` + * :py:class:`Pipe ` + * :py:class:`Valve ` - Reactors - * :py:class:`Water electrolyzer ` + * :py:class:`Fuel cell ` + * :py:class:`Water electrolyzer ` - Turbomachinery - * :py:class:`Compressor ` - * :py:class:`Pump ` - * :py:class:`Turbine ` + * :py:class:`Compressor ` + * :py:class:`Pump ` + * :py:class:`Turbine ` List of custom components ------------------------- @@ -64,15 +67,15 @@ Here we list the components integrated in the customs module. - :py:class:`Evaporator for two-phase geothermal organic rankine cycle ` -.. _using_tespy_components_parametrisation_label: +.. _tespy_modules_components_parametrisation_label: Component parametrisation ------------------------- All parameters of components are objects of a :code:`DataContainer` class. The -data container for component parameters it is called +data container for component parameters is called :code:`ComponentProperties`, :code:`ComponentCharacteristics` for component -characteristics and :code:`ComponentCharacteristicMaps` for characteristic +characteristics, and :code:`ComponentCharacteristicMaps` for characteristic maps. The main purpose of having a data container for the parameters (instead of pure numbers), is added flexibility for the user. There are different ways for you to specify and access component parameters. @@ -130,21 +133,28 @@ not be implemented by the solver. There are several components using parameter groups: - heat_exchanger_simple and pipe - * :code:`hydro_group` (:code:`D`, :code:`L`, :code:`ks`) - * :code:`kA_group` (:code:`kA`, :code:`Tamb`) - * :code:`kA_char_group` (:code:`kA_char`, :code:`Tamb`) + + * :code:`hydro_group` (:code:`D`, :code:`L`, :code:`ks`) + * :code:`kA_group` (:code:`kA`, :code:`Tamb`) + * :code:`kA_char_group` (:code:`kA_char`, :code:`Tamb`) + - solar_collector - * :code:`hydro_group` (:code:`D`, :code:`L`, :code:`ks`) - * :code:`energy_group` (:code:`E`, :code:`eta_opt`, :code:`lkf_lin`, - :code:`lkf_quad`, :code:`A`, :code:`Tamb`) + + * :code:`hydro_group` (:code:`D`, :code:`L`, :code:`ks`) + * :code:`energy_group` (:code:`E`, :code:`eta_opt`, :code:`lkf_lin`, + :code:`lkf_quad`, :code:`A`, :code:`Tamb`) + - parabolic_trough - * :code:`hydro_group` (:code:`D`, :code:`L`, :code:`ks`) - * :code:`energy_group` (:code:`E`, :code:`eta_opt`, :code:`aoi`, - :code:`doc`, :code:`c_1`, :code:`c_2`, :code:`iam_1`, :code:`iam_2`, - :code:`A`, :code:`Tamb`) + + * :code:`hydro_group` (:code:`D`, :code:`L`, :code:`ks`) + * :code:`energy_group` (:code:`E`, :code:`eta_opt`, :code:`aoi`, + :code:`doc`, :code:`c_1`, :code:`c_2`, :code:`iam_1`, :code:`iam_2`, + :code:`A`, :code:`Tamb`) + - compressor - * :code:`char_map_eta_s_group` (:code:`char_map_eta_s`, :code:`igva`) - * :code:`char_map_pr_group` (:code:`char_map_pr`, :code:`igva`) + + * :code:`char_map_eta_s_group` (:code:`char_map_eta_s`, :code:`igva`) + * :code:`char_map_pr_group` (:code:`char_map_pr`, :code:`igva`) Custom variables ^^^^^^^^^^^^^^^^ @@ -194,7 +204,7 @@ Component characteristics Several components integrate parameters using a characteristic function. These parameters come with default characteristics. The default characteristics -available can be found in the :py:mod:`` module. Of course, it is +available can be found in the :ref:`tespy_data_label`. Of course, it is possible to specify your own characteristic functions. .. note:: @@ -230,26 +240,27 @@ For example, :code:`kA_char` specification for heat exchangers: he = HeatExchanger('evaporator') # the characteristic function requires the design value of the property, - # therefore the design value of kA must be set and additonally we set + # therefore the design value of kA must be set and additionally we set # the kA_char method. This is performed automatically, if you specify the # kA_char as offdesign parameter (usual case). he.set_attr(kA={'design': 1e5}, kA_char={'is_set': True}) # use a characteristic line from the defaults: specify the component, the - # parameter and the name of the characteristic function. Also, specify, what - # type of characteristic function you want to use. + # parameter and the name of the characteristic function. Also, specify, + # what type of characteristic function you want to use. kA_char1 = ldc('heat exchanger', 'kA_char1', 'DEFAULT', CharLine) kA_char2 = ldc('heat exchanger', 'kA_char2', 'EVAPORATING FLUID', CharLine) he.set_attr(kA_char2=kA_char2) # specification of a data container yields the same result. It is - # aditionally possible to specify the characteristics parameter, e.g. mass flow - # for kA_char1 and volumetric flow for kA_char2 + # additionally possible to specify the characteristics parameter, e.g. mass + # flow for kA_char1 and volumetric flow for kA_char2 he.set_attr( kA_char1={'char_func': kA_char1, 'param': 'm'}, kA_char2={'char_func': kA_char2, 'param': 'v'}) - # or use custom values for the characteristic line e.g. kA vs volumetric flow + # or use custom values for the characteristic line e.g. kA vs volumetric + # flow x = np.array([0, 0.5, 1, 2]) y = np.array([0, 0.8, 1, 1.2]) kA_char1 = CharLine(x, y) @@ -308,7 +319,7 @@ Instead of writing your custom characteristic line information directly into your Python script, TESPy provides a second method of implementation: It is possible to store your data in the :code:`HOME/.tespy/data` folder and import from there. For additional information on formatting and usage, look into -:ref:`this part `. +:ref:`this part `. .. code-block:: python @@ -337,44 +348,44 @@ Characteristics are available for the following components and parameters: - combustion engine - * :py:meth:`tiP_char `: thermal input vs. power ratio. - * :py:meth:`Q1_char `: heat output 1 vs. power ratio. - * :py:meth:`Q2_char `: heat output 2 vs. power ratio. - * :py:meth:`Qloss_char `: heat loss vs. power ratio. + * :py:meth:`tiP_char `: thermal input vs. power ratio. + * :py:meth:`Q1_char `: heat output 1 vs. power ratio. + * :py:meth:`Q2_char `: heat output 2 vs. power ratio. + * :py:meth:`Qloss_char `: heat loss vs. power ratio. - compressor - * :py:meth:`char_map `: pressure ratio vs. non-dimensional mass flow. - * :py:meth:`char_map `: isentropic efficiency vs. non-dimensional mass flow. - * :py:meth:`eta_s_char `: isentropic efficiency. + * :py:meth:`char_map `: pressure ratio vs. non-dimensional mass flow. + * :py:meth:`char_map `: isentropic efficiency vs. non-dimensional mass flow. + * :py:meth:`eta_s_char `: isentropic efficiency. - heat exchangers: - * :py:meth:`kA1_char, kA2_char `: heat transfer coefficient. + * :py:meth:`kA1_char, kA2_char `: heat transfer coefficient. - pump - * :py:meth:`eta_s_char `: isentropic efficiency. - * :py:meth:`flow_char `: absolute pressure change. + * :py:meth:`eta_s_char `: isentropic efficiency. + * :py:meth:`flow_char `: absolute pressure change. - simple heat exchangers - * :py:meth:`kA_char `: heat transfer coefficient. + * :py:meth:`kA_char `: heat transfer coefficient. - turbine - * :py:meth:`eta_s_char `: isentropic efficiency. + * :py:meth:`eta_s_char `: isentropic efficiency. - valve - * :py:meth:`dp_char `: absolute pressure change. + * :py:meth:`dp_char `: absolute pressure change. - water electrolyzer - * :py:meth:`eta_char `: efficiency vs. load ratio. + * :py:meth:`eta_char `: efficiency vs. load ratio. For more information on how the characteristic functions work -:ref:`click here `. +:ref:`click here `. Extend components with new equations ------------------------------------ @@ -521,7 +532,7 @@ characteristic lines or characteristic maps are loaded automatically by the component initialisation method of class :py:class:`tespy.components.component.Component`. For more information on the default characteristics consider this -:ref:`chapter `. +:ref:`chapter `. The structure is very similar to the mandatory constraints, using DataContainers instead of dictionaries, e.g. for the Valve: @@ -687,3 +698,191 @@ methods needs the label as parameter. Need assistance? ^^^^^^^^^^^^^^^^ You are very welcome to submit an issue on our GitHub! + +.. _tespy_subsystems_label: + +Component Groups: Subystems +=========================== + +Subsystems are an easy way to add frequently used component groups such as a +drum with evaporator or a preheater with desuperheater to your system. In this +section you will learn how to create a subsystem and implement it in your work. +The subsystems are highly customizable and thus a very powerful tool, if you +require to use specific component groups frequently. We provide an example, of +how to create a simple subsystem and use it in a simulation. + +Custom subsystems +----------------- + +Create a :code:`.py` file in your working-directory. This file contains the +class definition of your subsystem and at minimum two methods: + +- :code:`create_comps`: Method to create the components of your subsystem and + save them in the :code:`Subsystem.comps` attribute (dictionary). +- :code:`create_conns`: Method to create the connections of your subsystem and + save them in the :code:`Subsystem.conns` attribute (dictionary). + +All other functionalities are inherited by the parent class of the +:py:class:`subsystem ` object. + +Example +------- + +Create the subsystem +^^^^^^^^^^^^^^^^^^^^ + +We create a subsystem for the usage of a waste heat steam generator. The +subsystem is built up of a superheater, an evaporator, a drum and an economizer +as seen in the figure below. + +.. figure:: /_static/images/modules/subsystem_waste_heat_generator.svg + :align: center + :alt: Topology of the waste heat steam generator + :figclass: only-light + + Figure: Topology of the waste heat steam generator + +.. figure:: /_static/images/modules/subsystem_waste_heat_generator_darkmode.svg + :align: center + :alt: Topology of the waste heat steam generator + :figclass: only-dark + + Figure: Topology of the waste heat steam generator + +Create a file, e.g. :code:`mysubsystems.py` and add the following lines: + +- Imports of the necessary classes from tespy. +- Class definition of the subsystem (inheriting from subsystem class). +- Methods for component and connection creation. Both, components and + connections, are stored in a dictionary for easy access by their respective + label. + +.. code-block:: python + + from tespy.components import Subsystem, HeatExchanger, Drum + from tespy.connections import Connection + + + class WasteHeatSteamGenerator(Subsystem): + """Class documentation""" + + def create_comps(self): + """Create the subsystem's components.""" + self.comps['eco'] = HeatExchanger('economizer') + self.comps['eva'] = HeatExchanger('evaporator') + self.comps['sup'] = HeatExchanger('superheater') + self.comps['drum'] = Drum('drum') + + def create_conns(self): + """Define the subsystem's connections.""" + self.conns['eco_dr'] = Connection( + self.comps['eco'], 'out2', self.comps['drum'], 'in1') + self.conns['dr_eva'] = Connection( + self.comps['drum'], 'out1', self.comps['eva'], 'in2') + self.conns['eva_dr'] = Connection( + self.comps['eva'], 'out2', self.comps['drum'], 'in2') + self.conns['dr_sup'] = Connection( + self.comps['drum'], 'out2', self.comps['sup'], 'in2') + self.conns['sup_eva'] = Connection( + self.comps['sup'], 'out1', self.comps['eva'], 'in1') + self.conns['eva_eco'] = Connection( + self.comps['eva'], 'out1', self.comps['eco'], 'in1') + +Import your subsystem +^^^^^^^^^^^^^^^^^^^^^ + +In a different script, we create a network and import the subsystem we just +created along with the different tespy classes required. The location of the +:code:`mysubsystems.py` file must be known by your python installation or lie +within the same folder as your script. + +.. code-block:: python + + from tespy.networks import Network + from tespy.components import Source, Sink + from tespy.connections import Connection + import numpy as np + + from mysubsystems import WasteHeatSteamGenerator as WHSG + + # %% network definition + + fluid_list = ['air', 'water'] + nw = Network(fluid_list, p_unit='bar', T_unit='C') + + # %% component definition + + feed_water = Source('feed water inlet') + steam = Sink('live steam outlet') + + waste_heat = Source('waste heat inlet') + chimney = Sink('waste heat chimney') + + sg = WHSG('waste heat steam generator') + + # %% connection definition + + fw_sg = Connection(feed_water, 'out1', sg.comps['eco'], 'in2') + sg_ls = Connection(sg.comps['sup'], 'out2', steam, 'in1') + fg_sg = Connection(waste_heat, 'out1', sg.comps['sup'], 'in1') + sg_ch = Connection(sg.comps['eco'], 'out1', chimney, 'in1') + + nw.add_conns(fw_sg, sg_ls, fg_sg, sg_ch) + nw.add_subsys(sg) + + # %% connection parameters + + fw_sg.set_attr(fluid={'air': 0, 'water': 1}, T=25) + fg_sg.set_attr(fluid={'air': 1, 'water': 0}, T=650, m=100) + + sg_ls.set_attr(p=130) + sg_ch.set_attr(p=1) + + sg.conns['eva_dr'].set_attr(x=0.6) + + # %% component parameters + + sg.comps['eco'].set_attr(pr1=0.999, pr2=0.97, + design=['pr1', 'pr2', 'ttd_u'], + offdesign=['zeta1', 'zeta2', 'kA_char']) + + sg.comps['eva'].set_attr(pr1=0.999, ttd_l=20, design=['pr1', 'ttd_l'], + offdesign=['zeta1', 'kA_char']) + + sg.comps['sup'].set_attr(pr1=0.999, pr2=0.99, ttd_u=50, + design=['pr1', 'pr2', 'ttd_u'], + offdesign=['zeta1', 'zeta2', 'kA_char']) + + sg.conns['eco_dr'].set_attr(Td_bp=-5, design=['Td_bp']) + + # %% solve + + # solve design case + nw.solve('design') + nw.print_results() + nw.save('tmp') + + # offdesign test + nw.solve('offdesign', design_path='tmp') + + +Add more flexibility +-------------------- + +If you want to add even more flexibility, you might need to manipulate the +:code:`__init__` method of your custom subsystem class. Usually, you do not +need to override this method. However, if you need additional parameters, e.g. +in order to alter the subsystem's topology or specify additional information, +take a look at the :py:class:`tespy.components.subsystem.Subsystem` class and +add your code between the label declaration and the components and connection +creation in the :code:`__init__` method. + +For example, if you want a variable number of inlets and outlets because you +have a variable number of components groups within your subsystem, you may +introduce an attribute which is set on initialisation and lets you create and +parameterize components and connections generically. This might be very +interesting for district heating systems, turbines with several sections of +equal topology, etc.. For a good start, you can have a look at the +:code:`sub_consumer.py` of the district heating network in the +`oemof_examples `_ +repository. diff --git a/docs/tespy_modules/connections.rst b/docs/modules/connections.rst similarity index 90% rename from docs/tespy_modules/connections.rst rename to docs/modules/connections.rst index 566570ce3..ef9ceeb08 100644 --- a/docs/tespy_modules/connections.rst +++ b/docs/modules/connections.rst @@ -1,348 +1,356 @@ -Connections -=========== - -This section provides an overview of the parametrisation of connections, the -usage of references and busses (connections for energy flow). - -Parametrisation ---------------- - -As mentioned in the introduction, for each connection you can specify the -following parameters: - - * mass flow* (m), - * volumetric flow (v), - * pressure* (p), - * enthalpy* (h), - * temperature* (T), - * vapor mass fraction for pure fluids (x), - * a fluid vector (fluid) and - * a balance closer for the fluid vector (fluid_balance). - -It is possible to specify values, starting values, references and data -containers. The data containers for connections are dc_prop for fluid -properties (mass flow, pressure, enthalpy, temperature and vapor mass -fraction) and dc_flu for fluid composition. If you want to specify -data_containers, you need to import them from the :py:mod:`tespy.tools` module. - -In order to create the connections we create the components to connect first. - -.. code-block:: python - - from tespy.tools import FluidProperties as dc_prop - from tespy.connections import Connection, Ref - from tespy.components import Sink, Source - - # create components - source1 = Source('source 1') - source2 = Source('source 2') - sink1 = Sink('sink 1') - sink2 = Sink('sink 2') - - # create connections - myconn = Connection(source1, 'out1', sink1, 'in1') - myotherconn = Connection(source2, 'out1', sink2, 'in1') - - # set pressure and vapor mass fraction by value, temperature and enthalpy - # analogously - myconn.set_attr(p=7, x=0.5) - - # set starting values for mass flow, pressure and enthalpy (has no effect - # on temperature and vapor mass fraction!) - myconn.set_attr(m0=10, p0=15, h0=100) - - # do the same with a data container - myconn.set_attr(p=dc_prop(val=7, val_set=True), - x=dc_prop(val=0.5, val_set=True)) - myconn.set_attr(m=dc_prop(val0=10), p=dc_prop(val0=15), - h=dc_prop(val0=100)) - - # specify a referenced value: pressure of myconn is 1.2 times pressure at - # myotherconn minus 5 (unit is the network's corresponding unit) - myconn.set_attr(p=Ref(myotherconn, 1.2, -5)) - - # specify value and reference at the same time - myconn.set_attr(p=dc_prop(val=7, val_set=True, - ref=Ref(myotherconn, 1.2, -5), ref_set=True)) - - # possibilities to unset values - myconn.set_attr(p=np.nan) - myconn.set_attr(p=None) - myconn.p.set_attr(val_set=False, ref_set=False) - -If you want to specify the fluid vector you can do it in the following way. - -.. note:: - - If you specify a fluid, use the fluid's name and do not include the fluid - property back end. - -.. code-block:: python - - from tespy.tools import FluidComposition as dc_flu - - # set both elements of the fluid vector - myconn.set_attr(fluid={'water': 1, 'air': 0}) - # same thing, but using data container - myconn.set_attr(fluid=dc_flu(val={'water': 1, 'air': 0}, - val_set={'water': True, 'air': True})) - - # set starting values - myconn.set_attr(fluid0={'water': 1, 'air': 0}) - # same thing, but using data container - myconn.set_attr(fluid=dc_flu(val0={'water': 1, 'air': 0})) - - # unset full fluid vector - myconn.set_attr(fluid={}) - # unset part of fluid vector - myconn.fluid.set_attr(val_set={'water': False}) - -.. note:: - - References can not be used for fluid composition at the moment! - -You may want to access the network's connections other than using the variable -names, for example in an imported network or connections from a subsystem. It -is possible to access these using the connection's label. By default, the label -is generated by this logic: - -:code:`source:source_id_target:target_id`, where - -- :code:`source` and :code:`target` are the labels of the components that are - connected. -- :code:`source_id` and :code:`target_id` are e.g. :code:`out1` and - :code:`in2` respectively. - -.. code-block:: python - - myconn = Connection(source1, 'out1', sink1, 'in1', label='myconnlabel') - mynetwork.add_conns(myconn) - mynetwork.get_conn('myconnlabel').set_attr(p=1e5) - -.. note:: - - The label can only be specified on creation of the connection. Changing the - label after might break this access method. - -.. _tespy_busses_label: - -Busses ------- - -Busses are energy flow connectors. You can sum the energy flow of different -components and create relations between components regarding mass independent -energy transport. - -Different use-cases for busses could be: - -- post-processing -- introduce motor or generator efficiencies -- create relations of different components - -The handling of busses is very similar to connections and components. You need -to add components to your busses as a dictionary containing at least the -instance of your component. Additionally you may provide a characteristic line, -linking the ratio of actual value to a referenced value (design case value) to -an efficiency factor the component value of the bus is multiplied with. For -instance, you can provide a characteristic line of an electrical generator or -motor for a variable conversion efficiency. The referenced value is retrieved -by the design point of your system. Offdesign calculations use the referenced -value from your system's design point for the characteristic line. In design -case, the ratio will always be 1. - -After a simulation, it is possible to output the efficiency of a component on -a bus and to output the bus value of the component using - -- :code:`mycomponent.calc_bus_efficiency(mybus)` -- :code:`mycomponent.calc_bus_value(mybus)` - -These data are also available in the network's results dictionary and contain - -- the bus value, -- the component value, -- the efficiency value and -- the design value of the bus. - -.. code-block:: python - - bus_results = mynetwork.results['power output'] - -.. note:: - - The available keywords for the dictionary are: - - - 'comp' for the component instance. - - 'param' for the parameter (e.g. the combustion engine has various - parameters, have a look at the - :ref:`combustion engine example `) - - 'char' for the characteristic line - - 'base' the base for efficiency definition - - 'P_ref' for the reference value of the component - - There are different specification possibilities: - - - If you specify the component only, the parameter will be default and the - efficiency factor of the characteristic line will be 1 independent of - the load. - - If you specify a numeric value for char, the efficiency factor will be - equal to that value independent of the load. - - If you want to specify a characteristic line, provide - a :py:class:`CharLine ` - object. - - Specify :code:`'base': 'bus'` if you want to change from the default base - to the bus as base. This means, that the definition of the efficiency - factor will change according to your specification. - - .. math :: - - \eta = \begin{cases} - \frac{\dot{E}_\mathrm{component}}{\dot{E}_\mathrm{bus}} & - \text{'base': 'bus'}\\ - \frac{\dot{E}_\mathrm{bus}}{\dot{E}_\mathrm{component}} & - \text{'base': 'component'} - \end{cases} - - This applies to the calculation of the bus value analogously. - - .. math:: - - \dot{E}_\mathrm{bus} = \begin{cases} - \frac{\dot{E}_\mathrm{component}}{f\left( - \frac{\dot{E}_\mathrm{bus}}{\dot{E}_\mathrm{bus,design}}\right)} & - \text{'base': 'bus'}\\ - \dot{E}_\mathrm{component} \cdot f\left( - \frac{\dot{E}_\mathrm{component}} - {\dot{E}_\mathrm{component,design}}\right) & - \text{'base': 'component'} - \end{cases} - -The examples below show the implementation of busses in your TESPy simulation. - -Create a pump that is powered by a turbine. The turbine's :code:`turbine_fwp` -power output must therefore be equal to the pump's :code:`fwp` power -consumption. - -.. code-block:: python - - from tespy.networks import Network - from tespy.components import Pump, Turbine, CombustionEngine - from tespy.connections import Bus - - # the total power on this bus must be zero - # this way we can make sure the power of the turbine has the same value as - # the pump's power but with negative sign - fwp_bus = Bus('feed water pump bus', P=0) - fwp_bus.add_comps({'comp': turbine_fwp}, {'comp': fwp}) - my_network.add_busses(fwp_bus) - -Create two turbines :code:`turbine1` and :code:`turbine2` which have the same -power output. - -.. code:: python - - # the total power on this bus must be zero, too - # we make sure the two turbines yield the same power output by adding the char - # parameter for the second turbine and using -1 as char - turbine_bus = Bus('turbines', P=0) - turbine_bus.add_comps({'comp': turbine_1}, {'comp': turbine_2, 'char': -1}) - my_network.add_busses(turbine_bus) - -Create a bus for post-processing purpose only. Include a characteristic line -for a generator and add two turbines :code:`turbine_hp` and :code:`turbine_lp` -to the bus. - -.. code:: python - - # bus for postprocessing, no power (or heat flow) specified but with variable - # conversion efficiency - power_bus = Bus('power output') - x = np.array([0.2, 0.4, 0.6, 0.8, 1.0, 1.1]) - y = np.array([0.85, 0.93, 0.95, 0.96, 0.97, 0.96]) - # create a characteristic line for a generator - gen = CharLine(x=x, y=y) - power.add_comps( - {'comp': turbine_hp, 'char': gen1}, - {'comp': turbine_lp, 'char': gen2}) - my_network.add_busses(power_bus) - -Create a bus for the electrical power output of a combustion engine -:code:`comb_engine`. Use a generator for power conversion and specify the total -power output. - -.. code:: python - - # bus for combustion engine power - el_power_bus = Bus('combustion engine power', P=-10e6) - el_power_bus.add_comps({'comp': comb_engine, 'param': 'P', 'char': gen}) - -Create a bus for the electrical power input of a pump :code:`pu` with -:code:`'bus'` and with :code:`'component'` as base. In both cases, the value of -the component power will be identical. Due to the different efficiency -definitions the value of the bus power will differ in part load. - -.. code:: python - - import numpy as np - from tespy.components import Pump, Sink, Source - from tespy.connections import Bus, Connection - from tespy.networks import Network - from tespy.tools.characteristics import CharLine - - nw = Network(fluids=['H2O'], p_unit='bar', T_unit='C') - - si = Sink('sink') - so = Source('source') - pu = Pump('pump') - - so_pu = Connection(so, 'out1', pu, 'in1') - pu_si = Connection(pu, 'out1', si, 'in1') - - nw.add_conns(so_pu, pu_si) - - # bus for combustion engine power - x = np.array([0.2, 0.4, 0.6, 0.8, 1.0, 1.1]) - y = np.array([0.85, 0.93, 0.95, 0.96, 0.97, 0.96]) - # create a characteristic line for a generator - mot_bus_based = CharLine(x=x, y=y) - mot_comp_based = CharLine(x=x, y=1 / y) - bus1 = Bus('pump power bus based') - bus1.add_comps({'comp': pu, 'char': mot_bus_based, 'base': 'bus'}) - # the keyword 'base': 'component' is the default value, therefore it does - # not need to be passed - bus2 = Bus('pump power component based') - bus2.add_comps({'comp': pu, 'char': mot_comp_based}) - - nw.add_busses(bus1, bus2) - - so_pu.set_attr(fluid={'H2O': 1}, m=10, p=5, T=20) - pu_si.set_attr(p=10) - - pu.set_attr(eta_s=0.75) - - nw.solve('design') - nw.save('tmp') - print('Bus based efficiency:', pu.calc_bus_efficiency(bus1)) - print('Component based efficiency:', 1 / pu.calc_bus_efficiency(bus2)) - print('Bus based bus power:', pu.calc_bus_value(bus1)) - print('Component based bus power:', pu.calc_bus_value(bus2)) - - so_pu.set_attr(m=9) - nw.solve('offdesign', design_path='tmp') - print('Bus based efficiency:', pu.calc_bus_efficiency(bus1)) - print('Component based efficiency:', 1 / pu.calc_bus_efficiency(bus2)) - print('Bus based bus power:', pu.calc_bus_value(bus1)) - print('Component based bus power:', pu.calc_bus_value(bus2)) - - # get DataFrame with the bus results - bus_results = nw.results['pump power bus based'] - -.. note:: - - The x-values of the characteristic line represent the relative load of the - component: actual value of the bus divided by the reference/design point - value. In design-calculations the x-value used in the function evaluation - will always be at 1. - -As mentioned in the component section: It is also possible to import your -custom characteristics from the :code:`HOME/.tespy/data` folder. Read more -about this :ref:`here `. +.. _tespy_modules_connections_label: + +Connections +=========== + +This section provides an overview of the parametrisation of connections, the +usage of references and busses (connections for energy flow). + +Parametrisation +--------------- + +As mentioned in the introduction, for each connection you can specify the +following parameters: + +* mass flow* (m), +* volumetric flow (v), +* pressure* (p), +* enthalpy* (h), +* temperature* (T), +* vapor mass fraction for pure fluids (x), +* a fluid vector (fluid) and +* a balance closer for the fluid vector (fluid_balance). + +It is possible to specify values, starting values, references and data +containers. The data containers for connections are dc_prop for fluid +properties (mass flow, pressure, enthalpy, temperature and vapor mass +fraction) and dc_flu for fluid composition. If you want to specify +data_containers, you need to import them from the :py:mod:`tespy.tools` module. + +In order to create the connections we create the components to connect first. + +.. code-block:: python + + from tespy.tools import FluidProperties as dc_prop + from tespy.connections import Connection, Ref + from tespy.components import Sink, Source + + # create components + source1 = Source('source 1') + source2 = Source('source 2') + sink1 = Sink('sink 1') + sink2 = Sink('sink 2') + + # create connections + myconn = Connection(source1, 'out1', sink1, 'in1') + myotherconn = Connection(source2, 'out1', sink2, 'in1') + + # set pressure and vapor mass fraction by value, temperature and enthalpy + # analogously + myconn.set_attr(p=7, x=0.5) + + # set starting values for mass flow, pressure and enthalpy (has no effect + # on temperature and vapor mass fraction!) + myconn.set_attr(m0=10, p0=15, h0=100) + + # do the same with a data container + myconn.set_attr( + p=dc_prop(val=7, val_set=True), + x=dc_prop(val=0.5, val_set=True) + ) + myconn.set_attr( + m=dc_prop(val0=10), p=dc_prop(val0=15), h=dc_prop(val0=100) + ) + + # specify a referenced value: pressure of myconn is 1.2 times pressure at + # myotherconn minus 5 (unit is the network's corresponding unit) + myconn.set_attr(p=Ref(myotherconn, 1.2, -5)) + + # specify value and reference at the same time + myconn.set_attr( + p=dc_prop( + val=7, val_set=True, ref=Ref(myotherconn, 1.2, -5), ref_set=True + ) + ) + + # possibilities to unset values + myconn.set_attr(p=np.nan) + myconn.set_attr(p=None) + myconn.p.set_attr(val_set=False, ref_set=False) + +If you want to specify the fluid vector you can do it in the following way. + +.. note:: + + If you specify a fluid, use the fluid's name and do not include the fluid + property back end. + +.. code-block:: python + + from tespy.tools import FluidComposition as dc_flu + + # set both elements of the fluid vector + myconn.set_attr(fluid={'water': 1, 'air': 0}) + # same thing, but using data container + myconn.set_attr(fluid=dc_flu(val={'water': 1, 'air': 0}, + val_set={'water': True, 'air': True})) + + # set starting values + myconn.set_attr(fluid0={'water': 1, 'air': 0}) + # same thing, but using data container + myconn.set_attr(fluid=dc_flu(val0={'water': 1, 'air': 0})) + + # unset full fluid vector + myconn.set_attr(fluid={}) + # unset part of fluid vector + myconn.fluid.set_attr(val_set={'water': False}) + +.. note:: + + References can not be used for fluid composition at the moment! + +You may want to access the network's connections other than using the variable +names, for example in an imported network or connections from a subsystem. It +is possible to access these using the connection's label. By default, the label +is generated by this logic: + +:code:`source:source_id_target:target_id`, where + +- :code:`source` and :code:`target` are the labels of the components that are + connected. +- :code:`source_id` and :code:`target_id` are e.g. :code:`out1` and + :code:`in2` respectively. + +.. code-block:: python + + myconn = Connection(source1, 'out1', sink1, 'in1', label='myconnlabel') + mynetwork.add_conns(myconn) + mynetwork.get_conn('myconnlabel').set_attr(p=1e5) + +.. note:: + + The label can only be specified on creation of the connection. Changing the + label after might break this access method. + +.. _tespy_busses_label: + +Busses +------ + +Busses are energy flow connectors. You can sum the energy flow of different +components and create relations between components regarding mass independent +energy transport. + +Different use-cases for busses could be: + +- post-processing +- introduce motor or generator efficiencies +- create relations of different components + +The handling of busses is very similar to connections and components. You need +to add components to your busses as a dictionary containing at least the +instance of your component. Additionally you may provide a characteristic line, +linking the ratio of actual value to a referenced value (design case value) to +an efficiency factor the component value of the bus is multiplied with. For +instance, you can provide a characteristic line of an electrical generator or +motor for a variable conversion efficiency. The referenced value is retrieved +by the design point of your system. Offdesign calculations use the referenced +value from your system's design point for the characteristic line. In design +case, the ratio will always be 1. + +After a simulation, it is possible to output the efficiency of a component on +a bus and to output the bus value of the component using + +- :code:`mycomponent.calc_bus_efficiency(mybus)` +- :code:`mycomponent.calc_bus_value(mybus)` + +These data are also available in the network's results dictionary and contain + +- the bus value, +- the component value, +- the efficiency value and +- the design value of the bus. + +.. code-block:: python + + bus_results = mynetwork.results['power output'] + +.. note:: + + The available keywords for the dictionary are: + + - 'comp' for the component instance. + - 'param' for the parameter (e.g. the combustion engine has various + parameters) + - 'char' for the characteristic line + - 'base' the base for efficiency definition + - 'P_ref' for the reference value of the component + + There are different specification possibilities: + + - If you specify the component only, the parameter will be default and the + efficiency factor of the characteristic line will be 1 independent of + the load. + - If you specify a numeric value for char, the efficiency factor will be + equal to that value independent of the load. + - If you want to specify a characteristic line, provide + a :py:class:`CharLine ` + object. + - Specify :code:`'base': 'bus'` if you want to change from the default base + to the bus as base. This means, that the definition of the efficiency + factor will change according to your specification. + + .. math :: + + \eta = \begin{cases} + \frac{\dot{E}_\mathrm{component}}{\dot{E}_\mathrm{bus}} & + \text{'base': 'bus'}\\ + \frac{\dot{E}_\mathrm{bus}}{\dot{E}_\mathrm{component}} & + \text{'base': 'component'} + \end{cases} + + This applies to the calculation of the bus value analogously. + + .. math:: + + \dot{E}_\mathrm{bus} = \begin{cases} + \frac{\dot{E}_\mathrm{component}}{f\left( + \frac{\dot{E}_\mathrm{bus}}{\dot{E}_\mathrm{bus,design}}\right)} & + \text{'base': 'bus'}\\ + \dot{E}_\mathrm{component} \cdot f\left( + \frac{\dot{E}_\mathrm{component}} + {\dot{E}_\mathrm{component,design}}\right) & + \text{'base': 'component'} + \end{cases} + +The examples below show the implementation of busses in your TESPy simulation. + +Create a pump that is powered by a turbine. The turbine's :code:`turbine_fwp` +power output must therefore be equal to the pump's :code:`fwp` power +consumption. + +.. code-block:: python + + from tespy.networks import Network + from tespy.components import Pump, Turbine, CombustionEngine + from tespy.connections import Bus + + # the total power on this bus must be zero + # this way we can make sure the power of the turbine has the same value as + # the pump's power but with negative sign + fwp_bus = Bus('feed water pump bus', P=0) + fwp_bus.add_comps({'comp': turbine_fwp}, {'comp': fwp}) + my_network.add_busses(fwp_bus) + +Create two turbines :code:`turbine1` and :code:`turbine2` which have the same +power output. + +.. code-block:: python + + # the total power on this bus must be zero, too + # we make sure the two turbines yield the same power output by adding the char + # parameter for the second turbine and using -1 as char + turbine_bus = Bus('turbines', P=0) + turbine_bus.add_comps({'comp': turbine_1}, {'comp': turbine_2, 'char': -1}) + my_network.add_busses(turbine_bus) + +Create a bus for post-processing purpose only. Include a characteristic line +for a generator and add two turbines :code:`turbine_hp` and :code:`turbine_lp` +to the bus. + +.. code-block:: python + + # bus for postprocessing, no power (or heat flow) specified but with variable + # conversion efficiency + power_bus = Bus('power output') + x = np.array([0.2, 0.4, 0.6, 0.8, 1.0, 1.1]) + y = np.array([0.85, 0.93, 0.95, 0.96, 0.97, 0.96]) + # create a characteristic line for a generator + gen = CharLine(x=x, y=y) + power.add_comps( + {'comp': turbine_hp, 'char': gen1}, + {'comp': turbine_lp, 'char': gen2} + ) + my_network.add_busses(power_bus) + +Create a bus for the electrical power output of a combustion engine +:code:`comb_engine`. Use a generator for power conversion and specify the total +power output. + +.. code-block:: python + + # bus for combustion engine power + el_power_bus = Bus('combustion engine power', P=-10e6) + el_power_bus.add_comps({'comp': comb_engine, 'param': 'P', 'char': gen}) + +Create a bus for the electrical power input of a pump :code:`pu` with +:code:`'bus'` and with :code:`'component'` as base. In both cases, the value of +the component power will be identical. Due to the different efficiency +definitions the value of the bus power will differ in part load. + +.. code-block:: python + + import numpy as np + from tespy.components import Pump, Sink, Source + from tespy.connections import Bus, Connection + from tespy.networks import Network + from tespy.tools.characteristics import CharLine + + nw = Network(fluids=['H2O'], p_unit='bar', T_unit='C') + + si = Sink('sink') + so = Source('source') + pu = Pump('pump') + + so_pu = Connection(so, 'out1', pu, 'in1') + pu_si = Connection(pu, 'out1', si, 'in1') + + nw.add_conns(so_pu, pu_si) + + # bus for combustion engine power + x = np.array([0.2, 0.4, 0.6, 0.8, 1.0, 1.1]) + y = np.array([0.85, 0.93, 0.95, 0.96, 0.97, 0.96]) + # create a characteristic line for a generator + mot_bus_based = CharLine(x=x, y=y) + mot_comp_based = CharLine(x=x, y=1 / y) + bus1 = Bus('pump power bus based') + bus1.add_comps({'comp': pu, 'char': mot_bus_based, 'base': 'bus'}) + # the keyword 'base': 'component' is the default value, therefore it does + # not need to be passed + bus2 = Bus('pump power component based') + bus2.add_comps({'comp': pu, 'char': mot_comp_based}) + + nw.add_busses(bus1, bus2) + + so_pu.set_attr(fluid={'H2O': 1}, m=10, p=5, T=20) + pu_si.set_attr(p=10) + + pu.set_attr(eta_s=0.75) + + nw.solve('design') + nw.save('tmp') + print('Bus based efficiency:', pu.calc_bus_efficiency(bus1)) + print('Component based efficiency:', 1 / pu.calc_bus_efficiency(bus2)) + print('Bus based bus power:', pu.calc_bus_value(bus1)) + print('Component based bus power:', pu.calc_bus_value(bus2)) + + so_pu.set_attr(m=9) + nw.solve('offdesign', design_path='tmp') + print('Bus based efficiency:', pu.calc_bus_efficiency(bus1)) + print('Component based efficiency:', 1 / pu.calc_bus_efficiency(bus2)) + print('Bus based bus power:', pu.calc_bus_value(bus1)) + print('Component based bus power:', pu.calc_bus_value(bus2)) + + # get DataFrame with the bus results + bus_results = nw.results['pump power bus based'] + +.. note:: + + The x-values of the characteristic line represent the relative load of the + component: actual value of the bus divided by the reference/design point + value. In design-calculations the x-value used in the function evaluation + will always be at 1. + +As mentioned in the component section: It is also possible to import your +custom characteristics from the :code:`HOME/.tespy/data` folder. Read more +about this :ref:`here `. diff --git a/docs/modules/fluid_properties.rst b/docs/modules/fluid_properties.rst new file mode 100644 index 000000000..e0012e1c0 --- /dev/null +++ b/docs/modules/fluid_properties.rst @@ -0,0 +1,163 @@ +.. _tespy_fluid_properties_label: + +Fluid properties +================ +The basic fluid properties are handled by +`CoolProp `_. All available fluids can be found on +their homepage. Also see :cite:`Bell2014`. + +CoolProp back ends +------------------ +CoolProp provides multiple back ends for fluid property calculation. The +back ends vary in calculation speed and calculation accuracy. It is possible +to choose from the following back ends: + +- :code:`HEOS`: Helmhotz Equation Of State with highest accuracy and lowest + calculation speed. **This is the default back end!** +- :code:`BICUBIC`: Tabular back end with high accuracy and very high + calculation speed. +- :code:`TTSE`: Tabular back end with lowest accuracy and very high calculation + speed. +- :code:`INCOMP`: Back end for incompressible fluids. +- :code:`IF97`: Back end for the IAPWS-IF97 of water, very accurate and much + higher calculation speed than :code:`HEOS`. Due to a bug in the CoolProp + back end this option is available with a fix (not the original + implementation), for more information see the + `CoolProp issue #1918 `_. + +For more information on the Back ends please visit the CoolProp online +documentation. + +Pure and pseudo-pure fluids +--------------------------- +If you use pure fluids, TESPy directly uses CoolProp functions to gather all +fluid properties. CoolProp covers the most important fluids such as water, air +as a pseudo-pure fluid as well as its components, several fuels and +refrigerants etc.. Look for the aliases in the list of +`fluids `__. +All fluids provided in this list cover liquid and gaseous state and the +two-phase region. + +Incompressible fluids +--------------------- +If you are looking for heat transfer fluids, the list of incompressible +`fluids `__ +might be interesting for you. In contrast to the pure fluids, the properties +cover liquid state only. + +Fluid mixtures +-------------- +CoolProp provides fluid properties for two component mixtures. BUT: These are +NOT integrated in TESPy! Nevertheless, you can use fluid mixtures for gases. + +Ideal mixtures of gaseous fluids +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +TESPy can handle mixtures of gaseous fluids, by using the single fluid +properties from CoolProp together with corresponding equations for mixtures. +The equations can be found in the +:py:mod:`fluid_properties ` module and are +applied automatically to the fluid vector. + +Other mixtures +^^^^^^^^^^^^^^ +Apart from partially liquid water in flue gases it is **not possible** to use +mixtures of liquids and other liquids or gaseous fluids **at the moment**! If +you try to use a mixture of two liquid or gaseous fluids and liquid fluids, +e.g. water and methanol, the equations will still be applied, but obviously +return wrong values. If you have ideas for the implementation of new kinds of +mixtures we appreciate you contacting us. + +.. _FluProDia_label: + +Creating Fluid Property Diagrams +-------------------------------- + +.. figure:: /_static/images/modules/logph_diagram_states.svg + :align: center + :alt: logph diagram of NH3 with a simple heat pump cycle + + Figure: logph diagram of NH3 with a simple heat pump cycle + +.. figure:: /_static/images/modules/Ts_diagram_states.svg + :align: center + :alt: Ts diagram of NH3 with a simple heat pump cycle + + Figure: Ts diagram of NH3 with a simple heat pump cycle + +CoolProp has an inbuilt feature for creating fluid property diagrams. +Unfortunately, the handling is not very easy at the moment. We recommend using +fluprodia (Fluid Property Diagram) instead. You can create and customize +different types of diagrams for all pure and pseudo-pure fluids available in +CoolProp. In order to plot your process data into a diagram, you can use the +:code:`get_plotting_data` method of each component. The method returns a +dictionary, that can be passed as :code:`**kwargs` to the +:code:`calc_individual_isoline` method of a fluprodia +:code:`FluidPropertyDiagram` object. The fluprodia documentation provides +examples of how to plot a process into different diagrams, too. For more +information on fluprodia have a look at the +`online documentation `_. You can +install the package with pip. + +.. code-block:: bash + + pip install fluprodia + +.. note:: + + The plotting data a returned from the :code:`get_plotting_data` as a + nested dictionary. The first level key contains the connection id of the + state change (change state from incoming connection to outgoing + connection). The table below shows the state change and the respective id. + + .. list-table:: State change and respective ids of dictionary + :widths: 60 10 10 10 + :header-rows: 1 + + * - component + - state from + - state to + - id + * - components with one inlet and one outlet only + - :code:`in1` + - :code:`out1` + - :code:`1` + * - class HeatExchanger and subclasses + - :code:`in1` + - :code:`out1` + - :code:`1` + * - + - :code:`in2` + - :code:`out2` + - :code:`2` + * - class ORCEvaporator + - :code:`in1` + - :code:`out1` + - :code:`1` + * - + - :code:`in2` + - :code:`out2` + - :code:`2` + * - + - :code:`in3` + - :code:`out3` + - :code:`3` + * - class Merge + - :code:`in1` + - :code:`out1` + - :code:`1` + * - + - :code:`in2` + - :code:`out1` + - :code:`2` + * - + - ... + - ... + - ... + * - class Drum + - :code:`out1` + - :code:`out2` + - :code:`1` + + All other components do not return any information as either there is no + change in state or the state change is accompanied by a change in fluid + composition. diff --git a/docs/tespy_modules/networks.rst b/docs/modules/networks.rst similarity index 84% rename from docs/tespy_modules/networks.rst rename to docs/modules/networks.rst index e0f6bcf18..0150c0c1c 100644 --- a/docs/tespy_modules/networks.rst +++ b/docs/modules/networks.rst @@ -1,4 +1,4 @@ -.. _using_tespy_networks_label: +.. _tespy_modules_networks_label: Networks ======== @@ -13,10 +13,10 @@ The TESPy network contains all data of your plant, which in terms of the calculation is represented by a nonlinear system of equations. The system variables of your TESPy network are: - * mass flow, - * pressure, - * enthalpy and - * the mass fractions of the network's fluids. +* mass flow, +* pressure, +* enthalpy and +* the mass fractions of the network's fluids. The solver will solve for these variables. As stated in the introduction the list of fluids is passed to your network on creation. If your **system** @@ -219,7 +219,7 @@ with zeta values. is calculated as function of the actual mass flow to design mass flow ratio. You can provide your own (measured) data or use the already existing data from TESPy. All standard characteristic functions are available at - :py:mod:`tespy.data`. + :ref:`tespy_data_label`. For connections it works in the same way, e.g. write @@ -257,19 +257,19 @@ The initialisation is performed in the following steps. **General preprocessing:** - * check network consistency and initialise components (if network topology is - changed to a prior calculation only). - * perform design/offdesign switch (for offdesign calculations only). - * preprocessing of offdesign case using the information from the - :code:`design_path` argument. +* check network consistency and initialise components (if network topology is + changed to a prior calculation only). +* perform design/offdesign switch (for offdesign calculations only). +* preprocessing of offdesign case using the information from the + :code:`design_path` argument. **Finding starting values:** - * fluid propagation. - * fluid property initialisation. - * initialisation from previous simulation run (:code:`ìnit_previous`). - * initialisation from .csv (setting starting values from :code:`init_path` - argument). +* fluid propagation. +* fluid property initialisation. +* initialisation from previous simulation run (:code:`ìnit_previous`). +* initialisation from .csv (setting starting values from :code:`init_path` + argument). The network check is used to find errors in the network topology, the calculation can not start without a successful check. For components, a @@ -396,7 +396,7 @@ power :math:`P` to be 1000 W, the set of equations will look like this: &0 = \dot{m}_{in} - \dot{m}_{out}\\ \mathrm{additional:} \, &0 = 1000 - \dot{m}_{in} (\cdot {h_{out} - h_{in}}) -.. _using_tespy_convergence_check_label: +.. _tespy_modules_convergence_check_label: Convergence stability +++++++++++++++++++++ @@ -413,44 +413,31 @@ added a convergence check. **has been added**. This manipulation has four steps, the first two are always applied: - * Cut off fluid mass fractions smaller than 0 and larger than 1. This way a - mass fraction of a single fluid components never exceeds these boundaries. - * Check, whether the fluid properties of pure fluids are within the available - ranges of CoolProp and readjust the values if not. +* Cut off fluid mass fractions smaller than 0 and larger than 1. This way a + mass fraction of a single fluid components never exceeds these boundaries. +* Check, whether the fluid properties of pure fluids are within the available + ranges of CoolProp and readjust the values if not. The next two steps are applied, if the user did not specify an :code:`init_path` and the iteration count is lower than 3, thus in the first three iteration steps of the algorithm only. In other cases this convergence check is skipped. - * Fox mixtures: check, if the fluid properties (pressure, enthalpy and - mass flow) are within the user specified boundaries - (:code:`p_range, h_range, m_range`) and if not, cut off higher/lower - values. - * Check the fluid properties of the connections based on the components they - are connecting. For example, check if the pressure at the outlet of a - turbine is lower than the pressure at the inlet or if the flue gas - composition at a combustion chamber's outlet is within the range of a - "typical" flue gas composition. If there are any violations, the - corresponding variables are manipulated. If you want to look up, what - exactly the convergence check for a specific component does, look out for - the :code:`convergence_check` methods in the - :py:mod:`tespy.components module `. +* Fox mixtures: check, if the fluid properties (pressure, enthalpy and mass + flow) are within the user specified boundaries + (:code:`p_range, h_range, m_range`) and if not, cut off higher/lower values. +* Check the fluid properties of the connections based on the components they + are connecting. For example, check if the pressure at the outlet of a turbine + is lower than the pressure at the inlet or if the flue gas composition at a + combustion chamber's outlet is within the range of a "typical" flue gas + composition. If there are any violations, the corresponding variables are + manipulated. If you want to look up, what exactly the convergence check for a + specific component does, look out for the :code:`convergence_check` methods + in the :py:mod:`tespy.components module `. In a lot of different tests the algorithm has found a near enough solution after the third iteration, further checks are usually not required. -.. note:: - - It is possible to improve the convergence stability manually when using - pure fluids. If you know the fluid's state is liquid or gaseous prior to - the calculation, you may provide the according value for the keyword e.g. - :code:`myconn.set_attr(state='l')`. The convergence check manipulates the - enthalpy values so that the fluid is always in the desired state at that - point. For an example see the release information of - :ref:`version 0.1.1 `. **Please note, that** - **you need to adjust the other parts of the script to the latest API.** - Calculation speed improvement +++++++++++++++++++++++++++++ For improvement of calculation speed, the calculation of specific derivatives @@ -518,7 +505,7 @@ the fluid_balance parameter adds only one equation to your system. If you are modeling a cycle, e.g. the clausius rankine cylce, you need to make a cut in the cycle using the cycle_closer or a sink and a source not to overdetermine the system. Have a look in the -:ref:`heat pump tutorial ` to understand why this is +:ref:`tutorial section ` to understand why this is important and how it can be implemented. If you have provided the correct number of parameters in your system and the @@ -628,14 +615,14 @@ After having exported the LaTeX code, you can simply use :code:`\input{}` in your main LaTeX document to include the documentation of your model. In order to compile correctly you need to load the following LaTeX packages: - - graphicx - - float - - hyperref - - booktabs - - amsmath - - units - - cleveref - - longtable +* graphicx +* float +* hyperref +* booktabs +* amsmath +* units +* cleveref +* longtable For generating different file formats, like markdown, html or restructuredtext, you could try the `pandoc `_ library. @@ -653,9 +640,9 @@ To print the results in your console use the :code:`print_results()` method. It will print tables containing the component, connection and bus properties. Some of the results will be colored, the colored results indicate - * if a parameter was specified as value before calculation. - * if a parameter is out of its predefined value bounds (e.g. efficiency > 1). - * if a component parameter was set to :code:`'var'` in your calculation. +* if a parameter was specified as value before calculation. +* if a parameter is out of its predefined value bounds (e.g. efficiency > 1). +* if a component parameter was set to :code:`'var'` in your calculation. The color for each of those categories is different and might depend on the console settings of your machine. If you do not want the results to be colored @@ -737,103 +724,9 @@ The index of the DataFrames is the connection's or component's label. results_for_specific_turbine = myplant.results['Turbine'].loc['turbine 1'] results_for_component_on_bus = myplant.results['power input'].loc['turbine 1'] - The full list of connection and component parameters can be obtained from the respective API documentation. -.. _FluProDia_label: - -Creating fluid property diagrams -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. figure:: /api/_images/logph_diagram_states.svg - :align: center - - Figure: logph diagram of NH3 with a simple heat pump cycle. - -.. figure:: /api/_images/Ts_diagram_states.svg - :align: center - - Figure: Ts diagram of NH3 with a simple heat pump cycle. - -CoolProp has an inbuilt feature for creating fluid property diagrams. -Unfortunately, the handling is not very easy at the moment. We recommend using -fluprodia (Fluid Property Diagram) instead. You can create and customize -different types of diagrams for all pure and pseudo-pure fluids available in -CoolProp. In order to plot your process data into a diagram, you can use the -:code:`get_plotting_data` method of each component. The method returns a -dictionary, that can be passed as :code:`**kwargs` to the -:code:`calc_individual_isoline` method of a fluprodia -:code:`FluidPropertyDiagram` object. The fluprodia documentation provides -examples of how to plot a process into different diagrams, too. For more -information on fluprodia have a look at the -`online documentation `_. You can -install the package with pip. - -.. code-block:: bash - - pip install fluprodia - -.. note:: - - The plotting data a returned from the :code:`get_plotting_data` as a - nested dictionary. The first level key contains the connection id of the - state change (change state from incoming connection to outgoing - connection). The table below shows the state change and the respective id. - - .. list-table:: State change and respective ids of dictionary - :widths: 60 10 10 10 - :header-rows: 1 - - * - component - - state from - - state to - - id - * - components with one inlet and one outlet only - - :code:`in1` - - :code:`out1` - - :code:`1` - * - class HeatExchanger and subclasses - - :code:`in1` - - :code:`out1` - - :code:`1` - * - - - :code:`in2` - - :code:`out2` - - :code:`2` - * - class ORCEvaporator - - :code:`in1` - - :code:`out1` - - :code:`1` - * - - - :code:`in2` - - :code:`out2` - - :code:`2` - * - - - :code:`in3` - - :code:`out3` - - :code:`3` - * - class Merge - - :code:`in1` - - :code:`out1` - - :code:`1` - * - - - :code:`in2` - - :code:`out1` - - :code:`2` - * - - - ... - - ... - - ... - * - class Drum - - :code:`out1` - - :code:`out2` - - :code:`1` - - - All other components do not return any information as either there is no - change in state or the state change is accompanied by a change in fluid - composition. - Network reader ============== The network reader is a useful tool to import networks from a data structure diff --git a/docs/tespy_modules/other.rst b/docs/modules/ude.rst similarity index 92% rename from docs/tespy_modules/other.rst rename to docs/modules/ude.rst index 111294cff..a9daf3beb 100644 --- a/docs/tespy_modules/other.rst +++ b/docs/modules/ude.rst @@ -1,299 +1,288 @@ -User defined equations -====================== -User defined functions provide a powerful tool to the user as they enable -the definition of generic and individual equations that can be applied to your -TESPy model. In order to implement this functionality in your model you will -use the :py:class:`tespy.tools.helpers.UserDefinedEquation`. The API -documentation provides you with an interesting example application, too. - -Getting started ---------------- - -For an easy start, let's consider two different streams. The mass flow of both -streams should be coupled within the model. There is already a possibility -covering simple relations, i.e. applying value referencing with the -:py:class:`tespy.connections.connection.Ref` class. This class allows to -formulate simple linear relations: - -.. math:: - - 0 = \dot{m}_1 - \left(\dot{m}_2 \cdot a + b\right) - -Instead of this simple application, other relations could be useful. For -example, the mass flow of our first stream should be quadratic to the mass -flow of the second stream. - -.. math:: - - 0 = \dot{m}_1 - \dot{m}_2^2 - -In order to apply this relation, we need to import the -:py:class:`tespy.tools.helpers.UserDefinedEquation` class into our model an -create an instance with the respective data. First, we set up the TESPy model. - -.. code-block:: python - - from tespy.networks import Network - from tespy.components import Sink, Source - from tespy.connections import Connection - from tespy.tools.helpers import UserDefinedEquation - - fluids = ['water'] - - nw = Network(fluids=fluids) - nw.set_attr(p_unit='bar', T_unit='C', h_unit='kJ / kg') - - so1 = Source('source 1') - so2 = Source('source 2') - si1 = Sink('sink 1') - si2 = Sink('sink 2') - - c1 = Connection(so1, 'out1', si1, 'in1') - c2 = Connection(so2, 'out1', si2, 'in1') - - nw.add_conns(c1, c2) - - c1.set_attr(fluid={'water': 1}, p=1, T=50) - c2.set_attr(fluid={'water': 1}, p=5, T=250, v=4) - -In the model both streams are well defined regarding pressure, enthalpy and -fluid composition. The second stream's mass flow is defined through -specification of the volumetric flow, we are missing the mass flow of the -connection :code:`c1`. As described, its value should be quadratic to the -(still unknown) mass flow of :code:`c2`. First, we now need to define the -equation in a function which returns the residual value of the equation. - -.. code-block:: python - - def my_ude(self): - return self.conns[0].m.val_SI - self.conns[1].m.val_SI ** 2 - - -.. note:: - - The function must only take one parameter, i.e. the UserDefinedEquation - class instance. The **name of the parameter is arbitrary**. We will use - :code:`self` in this example. It serves to access some important parameters - of the equation: - - - connections required in the equation - - Jacobian matrix to place the partial derivatives - - automatic numerical derivatives - - other (external) parameters (e.g. the CharLine in the API docs example of - :py:class:`tespy.tools.helpers.UserDefinedEquation`) - -.. note:: - - It is only possible to use the SI-values of the connection variables as - these values are updated in every iteration. The values in the network's - specified unit system are only updated after a simulation. - -The second step is to define the derivatives with respect to all primary -variables of the network, i.e. mass flow, pressure, enthalpy and fluid -composition of every connection. The derivatives have to be passed to the -Jacobian. In order to do this, we create a function that updates the values -inside the Jacobian of the :code:`UserDefinedEquation` and returns it: - -- :code:`self.jacobian` is a dictionary containing numpy arrays for every - connection required by the :code:`UserDefinedEquation`. -- derivatives to **mass flow** are placed in the first element of the numpy - array (**index 0**) -- derivatives to **pressure** are placed in the second element of the numpy - array (**index 1**) -- derivatives to **enthalpy** are placed in the third element of the numpy - array (**index 2**) -- derivatives to **fluid composition** are placed in the remaining elements - beginning at the fourth element of the numpy array (**indices 3:**) - -If we calculate the derivatives of our equation, it is easy to find, that only -derivatives to mass flow are not zero. - -- The derivative to mass flow of connection :code:`c1` is equal to :math:`1` -- The derivative to mass flow of connection :code:`c2` is equal to - :math:`2 \cdot \dot{m}_2`. - -.. code-block:: python - - def my_ude_deriv(self): - self.jacobian[self.conns[0]][0] = 1 - self.jacobian[self.conns[1]][0] = 2 * self.conns[1].m.val_SI - return self.jacobian - -Now we can create our instance of the :code:`UserDefinedEquation` and add it to -the network. The class requires four mandatory arguments to be passed: - -- :code:`label` of type String. -- :code:`func` which is the function holding the equation to be applied. -- :code:`deriv` which is the function holding the calculation of the Jacobian. -- :code:`conns` which is a list of the connections required by the equation. - The order of the connections specified in the list is equal to the accessing - order in the equation and derivative calculation. -- :code:`params` (optional keyword argument) which is a dictionary holding - additional data required in the equation or derivative calculation. - -.. code-block:: python - - ude = UserDefinedEquation('my ude', my_ude, my_ude_deriv, [c1, c2]) - nw.add_ude(ude) - nw.solve('design') - nw.print_results() - -More examples -------------- - -After warm-up let's create some more complex examples, e.g. the -square root of the temperature of the second stream should be equal to the -the logarithmic value of the pressure squared divided by the mass flow of the -first stream. - -.. math:: - - 0 = \sqrt{T_2} - \ln\left(\frac{p_1^2}{\dot{m}_1}\right) - -In order to access the temperature within the iteration process, we need to -calculate it with the respective method. We can import it from the -:py:mod:`tespy.tools.fluid_properties` module. Additionally, import numpy for -the logarithmic value. - -.. code-block:: python - - from tespy.tools.fluid_properties import T_mix_ph - import numpy as np - - def my_ude(self): - return ( - T_mix_ph(self.conns[1].get_flow()) ** 0.5 - - np.log(abs(self.conns[0].p.val_SI ** 2 / self.conns[0].m.val_SI))) - -.. note:: - - We use the absolute value inside of the logarithm expression to avoid - ValueErrors within the solution process as the mass flow is not restricted - to positive values. - -The derivatives can be determined analytically for the pressure and mass flow -of the first stream easily. For the temperature value, you can use the -predefined fluid property functions :code:`dT_mix_dph` and :code:`dT_mix_pdh` -respectively to calculate the partial derivatives. - -.. code-block:: python - - from tespy.tools.fluid_properties import dT_mix_dph - from tespy.tools.fluid_properties import dT_mix_pdh - - def my_ude_deriv(self): - self.jacobian[self.conns[0]][0] = 1 / self.conns[0].m.val_SI - self.jacobian[self.conns[0]][1] = - 2 / self.conns[0].p.val_SI - T = T_mix_ph(self.conns[1].get_flow()) - self.jacobian[self.conns[1]][1] = ( - dT_mix_dph(self.conns[1].get_flow()) * 0.5 / (T ** 0.5)) - self.jacobian[self.conns[1]][2] = ( - dT_mix_pdh(self.conns[1].get_flow()) * 0.5 / (T ** 0.5)) - return self.jacobian - -But, what if the analytical derivative is not available? You can make use of -generic numerical derivatives using the inbuilt method :code:`numeric_deriv`. -The methods expects the variable :code:`'m'`, :code:`'p'`, :code:`'h'` or -:code:`'fluid'` (fluid composition) to derive the function to as well as the -respective connection index from the list of connections. The "lazy" solution -for the above derivatives would therefore look like this: - -.. code-block:: python - - def my_ude_deriv(self): - self.jacobian[self.conns[0]][0] = self.numeric_deriv('m', 0) - self.jacobian[self.conns[0]][1] = self.numeric_deriv('p', 0) - self.jacobian[self.conns[1]][1] = self.numeric_deriv('p', 1) - self.jacobian[self.conns[1]][2] = self.numeric_deriv('h', 1) - return self.jacobian - -Obviously, the downside is a slower performance of the solver, as for every -:code:`numeric_deriv` call the function will be evaluated fully twice -(central finite difference). - -Last, we want to consider an example using additional parameters in the -UserDefinedEquation, where :math:`a` might be a factor between 0 and 1 and -:math:`b` is the steam mass fraction (also, between 0 and 1). The difference of -the enthalpy between the two streams multiplied with factor a should be equal -to the difference of the enthalpy of stream two and the enthalpy of saturated -gas at the pressure of stream 1. The definition of the UserDefinedEquation -instance must therefore be changed as below. - -.. math:: - - 0 = a \cdot \left(h_2 - h_1 \right) - - \left(h_2 - h\left(p_1, x=b \right)\right) - -.. code-block:: python - - from tespy.tools.fluid_properties import h_mix_pQ - from tespy.tools.fluid_properties import dh_mix_dpQ - - def my_ude(self): - a = self.params['a'] - b = self.params['b'] - return ( - a * (self.conns[1].h.val_SI - self.conns[0].h.val_SI) - - (self.conns[1].h.val_SI - h_mix_pQ(self.conns[0].get_flow(), b))) - - def my_ude_deriv(self): - a = self.params['a'] - b = self.params['b'] - self.jacobian[self.conns[0]][1] = dh_mix_dpQ( - self.conns[0].get_flow(), b) - self.jacobian[self.conns[0]][2] = -a - self.jacobian[self.conns[1]][2] = a - 1 - return self.jacobian - - ude = UserDefinedEquation( - 'my ude', my_ude, my_ude_deriv, [c1, c2], params={'a': 0.5, 'b': 1}) - - -One more example (using a CharLine for datapoint interpolation) can be found in -the API documentation of class -:py:class:`tespy.tools.helpers.UserDefinedEquation`. - -Document your equations ------------------------ - -For the automatic documentation of your models just pass the :code:`latex` -keyword on creation of the UserDefinedEquation instance. It should contain the -latex equation string. For example, the last equation from above: - -.. code-block:: python - - latex = ( - r'0 = a \cdot \left(h_2 - h_1 \right) - ' - r'\left(h_2 - h\left(p_1, x=b \right)\right)') - - ude = UserDefinedEquation( - 'my ude', my_ude, my_ude_deriv, [c1, c2], params={'a': 0.5, 'b': 1}, - latex={'equation': latex}) - -The documentation will also create figures of :code:`CharLine` and -:code:`CharMap` objects provided. To add these, adjust the code like this. -Provide the :code:`CharLine` and :code:`CharMap` objects within a list. - -.. code-block:: python - - ude = UserDefinedEquation( - 'my ude', my_ude, my_ude_deriv, [c1, c2], params={'a': 0.5, 'b': 1}, - latex={ - 'equation': latex, - 'lines': [charline1, charline2], - 'maps': [map1]}) - -How can TESPy contribute to your energy system calculations? -============================================================ - -In this part you learn how you can use TESPy for your energy system -calculations: In energy system calculations, for instance in oemof-solph, -plants are usually modeled as abstract components on a much lower level of -detail. In order to represent a plant within an abstract component it is -possible to supply characteristics establishing a connection between your -energy system model and a specific plant model. Thus the characteristics are a -representation of a specific plant layout in terms of topology and process -parameters. In the examples section we have an example of a heat pump COP at -different loads and ambient temperatures as well as a CHP unit with -backpressure turbine operating at different loads and varying feed flow -temperatures of a heating system. +.. _tespy_ude_label: + +User defined equations +====================== +User defined functions provide a powerful tool to the user as they enable +the definition of generic and individual equations that can be applied to your +TESPy model. In order to implement this functionality in your model you will +use the :py:class:`tespy.tools.helpers.UserDefinedEquation`. The API +documentation provides you with an interesting example application, too. + +Getting started +--------------- + +For an easy start, let's consider two different streams. The mass flow of both +streams should be coupled within the model. There is already a possibility +covering simple relations, i.e. applying value referencing with the +:py:class:`tespy.connections.connection.Ref` class. This class allows to +formulate simple linear relations: + +.. math:: + + 0 = \dot{m}_1 - \left(\dot{m}_2 \cdot a + b\right) + +Instead of this simple application, other relations could be useful. For +example, the mass flow of our first stream should be quadratic to the mass +flow of the second stream. + +.. math:: + + 0 = \dot{m}_1 - \dot{m}_2^2 + +In order to apply this relation, we need to import the +:py:class:`tespy.tools.helpers.UserDefinedEquation` class into our model an +create an instance with the respective data. First, we set up the TESPy model. + +.. code-block:: python + + from tespy.networks import Network + from tespy.components import Sink, Source + from tespy.connections import Connection + from tespy.tools.helpers import UserDefinedEquation + + fluids = ['water'] + + nw = Network(fluids=fluids) + nw.set_attr(p_unit='bar', T_unit='C', h_unit='kJ / kg') + + so1 = Source('source 1') + so2 = Source('source 2') + si1 = Sink('sink 1') + si2 = Sink('sink 2') + + c1 = Connection(so1, 'out1', si1, 'in1') + c2 = Connection(so2, 'out1', si2, 'in1') + + nw.add_conns(c1, c2) + + c1.set_attr(fluid={'water': 1}, p=1, T=50) + c2.set_attr(fluid={'water': 1}, p=5, T=250, v=4) + +In the model both streams are well defined regarding pressure, enthalpy and +fluid composition. The second stream's mass flow is defined through +specification of the volumetric flow, we are missing the mass flow of the +connection :code:`c1`. As described, its value should be quadratic to the +(still unknown) mass flow of :code:`c2`. First, we now need to define the +equation in a function which returns the residual value of the equation. + +.. code-block:: python + + def my_ude(self): + return self.conns[0].m.val_SI - self.conns[1].m.val_SI ** 2 + + +.. note:: + + The function must only take one parameter, i.e. the UserDefinedEquation + class instance. The **name of the parameter is arbitrary**. We will use + :code:`self` in this example. It serves to access some important parameters + of the equation: + + - connections required in the equation + - Jacobian matrix to place the partial derivatives + - automatic numerical derivatives + - other (external) parameters (e.g. the CharLine in the API docs example of + :py:class:`tespy.tools.helpers.UserDefinedEquation`) + +.. note:: + + It is only possible to use the SI-values of the connection variables as + these values are updated in every iteration. The values in the network's + specified unit system are only updated after a simulation. + +The second step is to define the derivatives with respect to all primary +variables of the network, i.e. mass flow, pressure, enthalpy and fluid +composition of every connection. The derivatives have to be passed to the +Jacobian. In order to do this, we create a function that updates the values +inside the Jacobian of the :code:`UserDefinedEquation` and returns it: + +- :code:`self.jacobian` is a dictionary containing numpy arrays for every + connection required by the :code:`UserDefinedEquation`. +- derivatives to **mass flow** are placed in the first element of the numpy + array (**index 0**) +- derivatives to **pressure** are placed in the second element of the numpy + array (**index 1**) +- derivatives to **enthalpy** are placed in the third element of the numpy + array (**index 2**) +- derivatives to **fluid composition** are placed in the remaining elements + beginning at the fourth element of the numpy array (**indices 3:**) + +If we calculate the derivatives of our equation, it is easy to find, that only +derivatives to mass flow are not zero. + +- The derivative to mass flow of connection :code:`c1` is equal to :math:`1` +- The derivative to mass flow of connection :code:`c2` is equal to + :math:`2 \cdot \dot{m}_2`. + +.. code-block:: python + + def my_ude_deriv(self): + self.jacobian[self.conns[0]][0] = 1 + self.jacobian[self.conns[1]][0] = 2 * self.conns[1].m.val_SI + return self.jacobian + +Now we can create our instance of the :code:`UserDefinedEquation` and add it to +the network. The class requires four mandatory arguments to be passed: + +- :code:`label` of type String. +- :code:`func` which is the function holding the equation to be applied. +- :code:`deriv` which is the function holding the calculation of the Jacobian. +- :code:`conns` which is a list of the connections required by the equation. + The order of the connections specified in the list is equal to the accessing + order in the equation and derivative calculation. +- :code:`params` (optional keyword argument) which is a dictionary holding + additional data required in the equation or derivative calculation. + +.. code-block:: python + + ude = UserDefinedEquation('my ude', my_ude, my_ude_deriv, [c1, c2]) + nw.add_ude(ude) + nw.solve('design') + nw.print_results() + +More examples +------------- + +After warm-up let's create some more complex examples, e.g. the +square root of the temperature of the second stream should be equal to the +the logarithmic value of the pressure squared divided by the mass flow of the +first stream. + +.. math:: + + 0 = \sqrt{T_2} - \ln\left(\frac{p_1^2}{\dot{m}_1}\right) + +In order to access the temperature within the iteration process, we need to +calculate it with the respective method. We can import it from the +:py:mod:`tespy.tools.fluid_properties` module. Additionally, import numpy for +the logarithmic value. + +.. code-block:: python + + from tespy.tools.fluid_properties import T_mix_ph + import numpy as np + + def my_ude(self): + return ( + T_mix_ph(self.conns[1].get_flow()) ** 0.5 - + np.log(abs(self.conns[0].p.val_SI ** 2 / self.conns[0].m.val_SI))) + +.. note:: + + We use the absolute value inside of the logarithm expression to avoid + ValueErrors within the solution process as the mass flow is not restricted + to positive values. + +The derivatives can be determined analytically for the pressure and mass flow +of the first stream easily. For the temperature value, you can use the +predefined fluid property functions :code:`dT_mix_dph` and :code:`dT_mix_pdh` +respectively to calculate the partial derivatives. + +.. code-block:: python + + from tespy.tools.fluid_properties import dT_mix_dph + from tespy.tools.fluid_properties import dT_mix_pdh + + def my_ude_deriv(self): + self.jacobian[self.conns[0]][0] = 1 / self.conns[0].m.val_SI + self.jacobian[self.conns[0]][1] = - 2 / self.conns[0].p.val_SI + T = T_mix_ph(self.conns[1].get_flow()) + self.jacobian[self.conns[1]][1] = ( + dT_mix_dph(self.conns[1].get_flow()) * 0.5 / (T ** 0.5)) + self.jacobian[self.conns[1]][2] = ( + dT_mix_pdh(self.conns[1].get_flow()) * 0.5 / (T ** 0.5)) + return self.jacobian + +But, what if the analytical derivative is not available? You can make use of +generic numerical derivatives using the inbuilt method :code:`numeric_deriv`. +The methods expects the variable :code:`'m'`, :code:`'p'`, :code:`'h'` or +:code:`'fluid'` (fluid composition) to derive the function to as well as the +respective connection index from the list of connections. The "lazy" solution +for the above derivatives would therefore look like this: + +.. code-block:: python + + def my_ude_deriv(self): + self.jacobian[self.conns[0]][0] = self.numeric_deriv('m', 0) + self.jacobian[self.conns[0]][1] = self.numeric_deriv('p', 0) + self.jacobian[self.conns[1]][1] = self.numeric_deriv('p', 1) + self.jacobian[self.conns[1]][2] = self.numeric_deriv('h', 1) + return self.jacobian + +Obviously, the downside is a slower performance of the solver, as for every +:code:`numeric_deriv` call the function will be evaluated fully twice +(central finite difference). + +Last, we want to consider an example using additional parameters in the +UserDefinedEquation, where :math:`a` might be a factor between 0 and 1 and +:math:`b` is the steam mass fraction (also, between 0 and 1). The difference of +the enthalpy between the two streams multiplied with factor a should be equal +to the difference of the enthalpy of stream two and the enthalpy of saturated +gas at the pressure of stream 1. The definition of the UserDefinedEquation +instance must therefore be changed as below. + +.. math:: + + 0 = a \cdot \left(h_2 - h_1 \right) - + \left(h_2 - h\left(p_1, x=b \right)\right) + +.. code-block:: python + + from tespy.tools.fluid_properties import h_mix_pQ + from tespy.tools.fluid_properties import dh_mix_dpQ + + def my_ude(self): + a = self.params['a'] + b = self.params['b'] + return ( + a * (self.conns[1].h.val_SI - self.conns[0].h.val_SI) - + (self.conns[1].h.val_SI - h_mix_pQ(self.conns[0].get_flow(), b))) + + def my_ude_deriv(self): + a = self.params['a'] + b = self.params['b'] + self.jacobian[self.conns[0]][1] = dh_mix_dpQ( + self.conns[0].get_flow(), b) + self.jacobian[self.conns[0]][2] = -a + self.jacobian[self.conns[1]][2] = a - 1 + return self.jacobian + + ude = UserDefinedEquation( + 'my ude', my_ude, my_ude_deriv, [c1, c2], params={'a': 0.5, 'b': 1}) + + +One more example (using a CharLine for datapoint interpolation) can be found in +the API documentation of class +:py:class:`tespy.tools.helpers.UserDefinedEquation`. + +Document your equations +----------------------- + +For the automatic documentation of your models just pass the :code:`latex` +keyword on creation of the UserDefinedEquation instance. It should contain the +latex equation string. For example, the last equation from above: + +.. code-block:: python + + latex = ( + r'0 = a \cdot \left(h_2 - h_1 \right) - ' + r'\left(h_2 - h\left(p_1, x=b \right)\right)') + + ude = UserDefinedEquation( + 'my ude', my_ude, my_ude_deriv, [c1, c2], params={'a': 0.5, 'b': 1}, + latex={'equation': latex}) + +The documentation will also create figures of :code:`CharLine` and +:code:`CharMap` objects provided. To add these, adjust the code like this. +Provide the :code:`CharLine` and :code:`CharMap` objects within a list. + +.. code-block:: python + + ude = UserDefinedEquation( + 'my ude', my_ude, my_ude_deriv, [c1, c2], params={'a': 0.5, 'b': 1}, + latex={ + 'equation': latex, + 'lines': [charline1, charline2], + 'maps': [map1] + } + ) diff --git a/docs/references.bib b/docs/references.bib index 80f166494..a70bfdfc7 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -36,7 +36,7 @@ @TechReport{Lippke1995 url = {https://www.osti.gov/biblio/95571}, address = {Albuquerque}, groups = {solar-case-study}, - month = {6}, + month = jun, place = {United States}, year = {1995}, } @@ -266,3 +266,41 @@ @book{CRCHandbook2021 year={2021}, publisher = {CRC Press} } + +@article{Witte2022, + doi = {10.3390/en15114087}, + year = {2022}, + publisher = {{MDPI} {AG}}, + volume = {15}, + number = {11}, + article-number = {4087}, + issn = {1996-1073}, + author = {Witte, Francesco and Hofmann, Mathias and Meier, Julius and Tuschy, Ilja and Tsatsaronis, George}, + title = {Generic and Open-Source Exergy Analysis—Extending the Simulation Framework TESPy}, + journal = {Energies} +} + +@inproceedings{Hofmann2022, + editor = {Brian Elmegaard and Enrico Sciubba and Ana M Blanco-Marigorta and Jonas Kjær Jensen and Wiebke Brix Markussen and Wiebke Meesenburg and Nasrin Arjomand Kermani and Tingting Zhu and René Kofler}, + author = {Hofmann, Mathias and Witte, Francesco and Shawky, Karim and Tuschy, Ilja and Tsatsaronis, George}, + title = {{T}hermal {E}ngineering {S}ystems in {P}ython ({TESPy}): The implementation and validation of the chemical exergy}, + booktitle = {Proceedings of ECOS 2022}, + pages = {257--268}, + publisher = {DTU Construct}, + venue = {Copenhagen, Denmark}, + month = jul, + year = {2022}, +} + +@article{Valero1994, + doi = {10.1016/0360-5442(94)90112-0}, + year = 1994, + month = mar, + publisher = {Elsevier {BV}}, + volume = {19}, + number = {3}, + pages = {279--286}, + author = {Antonio Valero and Miguel A. Lozano and Luis Serra and George Tsatsaronis and Javier Pisa and Christos Frangopoulos and Michael R. von Spakovsky}, + title = {{CGAM} problem: Definition and conventional solution}, + journal = {Energy} +} diff --git a/docs/regular_meeting.rst b/docs/regular_meeting.rst index cbe2b817f..e88785b81 100644 --- a/docs/regular_meeting.rst +++ b/docs/regular_meeting.rst @@ -1,21 +1,16 @@ -.. _installation_and_setup_label: +.. _tespy_community_label: -############################### -Get in touch with the community -############################### - -.. contents:: - :depth: 1 - :local: - :backlinks: top +############### +TESPy community +############### Online "Stammtisch" =================== We have decided to start a reoccurring "Stammtisch" meeting for all interested TESPy users and (potential) developers. You are invited to join us on every 3rd -Monday of a month at 17:00 CE(S)T for a casual get together. The first meeting -will be held at June, 20, 2022. The intent of this meeting is to establish a -more active and well connected network of TESPy users and developers. +Monday of a month at 17:00 CE(S)T for a casual get together. The intent of this +meeting is to establish a more active and well connected network of TESPy users +and developers. If you are interested, you can simply join the meeting at https://meet.jit.si/tespy_user_meeting. We are looking forward to seeing you! diff --git a/docs/requirements.txt b/docs/requirements.txt index b20b9fffe..69d0a7e5f 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,3 +1,5 @@ +furo sphinx>=1.3 -sphinx-rtd-theme sphinxcontrib-bibtex +sphinx-copybutton +sphinx-design diff --git a/docs/tespy_analyses.rst b/docs/tespy_analyses.rst deleted file mode 100644 index ffe757640..000000000 --- a/docs/tespy_analyses.rst +++ /dev/null @@ -1,19 +0,0 @@ -.. _tespy_analyses_label: - -~~~~~~~~~~~~~~~~~~~~~~ -Thermodynamic analyses -~~~~~~~~~~~~~~~~~~~~~~ - -Performing thermodynamic cycle analyses making use of the second law of -thermodynamics provides further process information and uncovers potentials for -improvement in power plant engineering. Therefore, TESPy's analyses module -provides you with an inbuilt and fully automatic exergy analysis. Adding -entropy analysis is planned for the future. - -.. contents:: `Contents` - :depth: 1 - :local: - :backlinks: top - -.. _tespy_analyses_exergy_label: -.. include:: analyses/exergy.rst diff --git a/docs/tespy_modules.rst b/docs/tespy_modules.rst deleted file mode 100644 index b0cae9c53..000000000 --- a/docs/tespy_modules.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. _tespy_modules_label: - -~~~~~~~~~~~~~ -TESPy modules -~~~~~~~~~~~~~ - -The following sections give a detailed overview on the modules of TESPy. This -includes all important settings of networks, components and connections as well -as the underlying functionalities of the software. - -At the end of this page, we provide an example on how to couple energy system -simulation with TESPy. - -.. contents:: `Contents` - :depth: 1 - :local: - :backlinks: top - -.. _tespy_modules_network_label: -.. include:: tespy_modules/networks.rst -.. _using_tespy_components_label: -.. include:: tespy_modules/components.rst -.. include:: tespy_modules/subsystems.rst -.. _using_tespy_connections_label: -.. include:: tespy_modules/connections.rst -.. _using_tespy_characteristics_label: -.. include:: tespy_modules/characteristics.rst -.. _tespy_fluid_properties_label: -.. include:: tespy_modules/fluid_properties.rst -.. _tespy_other_label: -.. include:: tespy_modules/other.rst diff --git a/docs/tespy_modules/fluid_properties.rst b/docs/tespy_modules/fluid_properties.rst deleted file mode 100644 index e50198c78..000000000 --- a/docs/tespy_modules/fluid_properties.rst +++ /dev/null @@ -1,66 +0,0 @@ -Fluid properties -================ -The basic fluid properties are handled by -`CoolProp `_. All available fluids can be found on -their homepage. Also see :cite:`Bell2014`. - -CoolProp back ends ------------------- -CoolProp provides multiple back ends for fluid property calculation. The -back ends vary in calculation speed and calculation accuracy. It is possible -to choose from the following back ends: - -- :code:`HEOS`: Helmhotz Equation Of State with highest accuracy and lowest - calculation speed. **This is the default back end!** -- :code:`BICUBIC`: Tabular back end with high accuracy and very high - calculation speed. -- :code:`TTSE`: Tabular back end with lowest accuracy and very high calculation - speed. -- :code:`INCOMP`: Back end for incompressible fluids. -- :code:`IF97`: Back end for the IAPWS-IF97 of water, very accurate and much - higher calculation speed than :code:`HEOS`. Due to a bug in the CoolProp - back end this option is available with a fix (not the original - implementation), for more information see the - `CoolProp issue #1918 `_. - -For more information on the Back ends please visit the CoolProp online -documentation. - -Pure and pseudo-pure fluids ---------------------------- -If you use pure fluids, TESPy directly uses CoolProp functions to gather all -fluid properties. CoolProp covers the most important fluids such as water, air -as a pseudo-pure fluid as well as its components, several fuels and -refrigerants etc.. Look for the aliases in the list of -`fluids `_. -All fluids provided in this list cover liquid and gaseous state and the -two-phase region. - -Incompressible fluids ---------------------- -If you are looking for heat transfer fluids, the list of incompressible -`fluids `_ -might be interesting for you. In contrast to the pure fluids, the properties -cover liquid state only. - -Fluid mixtures --------------- -CoolProp provides fluid properties for two component mixtures. BUT: These are -NOT integrated in TESPy! Nevertheless, you can use fluid mixtures for gases. - -Ideal mixtures of gaseous fluids -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -TESPy can handle mixtures of gaseous fluids, by using the single fluid -properties from CoolProp together with corresponding equations for mixtures. -The equations can be found in the -:py:mod:`fluid_properties ` module and are -applied automatically to the fluid vector. - -Other mixtures -^^^^^^^^^^^^^^ -Apart from partially liquid water in flue gases it is **not possible** to use -mixtures of liquids and other liquids or gaseous fluids **at the moment**! If -you try to use a mixture of two liquid or gaseous fluids and liquid fluids, -e.g. water and methanol, the equations will still be applied, but obviously -return wrong values. If you have ideas for the implementation of new kinds of -mixtures we appreciate you contacting us. diff --git a/docs/tespy_modules/subsystems.rst b/docs/tespy_modules/subsystems.rst deleted file mode 100644 index 8ba660416..000000000 --- a/docs/tespy_modules/subsystems.rst +++ /dev/null @@ -1,178 +0,0 @@ -.. _tespy_subsystems_label: - -Subsystems and component groups -=============================== - -Subsystems are an easy way to add frequently used component groups such as a -drum with evaporator or a preheater with desuperheater to your system. In this -section you will learn how to create a subsystem and implement it in your work. -The subsystems are highly customizable and thus a very powerful tool, if you -require to use specific component groups frequently. We provide an example, of -how to create a simple subsystem and use it in a simulation. - -Custom subsystems ------------------ - -Create a :code:`.py` file in your working-directory. This file contains the -class definition of your subsystem and at minimum two methods: - -- :code:`create_comps`: Method to create the components of your subsystem and - save them in the :code:`Subsystem.comps` attribute (dictionary). -- :code:`create_conns`: Method to create the connections of your subsystem and - save them in the :code:`Subsystem.conns` attribute (dictionary). - -All other functionalities are inherited by the parent class of the -:py:class:`subsystem ` object. - -Example -------- - -Create the subsystem -^^^^^^^^^^^^^^^^^^^^ - -We create a subsystem for the usage of a waste heat steam generator. The -subsystem is built up of a superheater, an evaporator, a drum and an economizer -as seen in the figure below. - -.. figure:: /api/_images/subsystem_waste_heat_generator.svg - :align: center - - Figure: Topology of the waste heat steam generator. - -Create a file, e.g. :code:`mysubsystems.py` and add the following lines: - -- Imports of the necessary classes from tespy. -- Class definition of the subsystem (inheriting from subsystem class). -- Methods for component and connection creation. Both, components and - connections, are stored in a dictionary for easy access by their respective - label. - -.. code-block:: python - - from tespy.components import Subsystem, HeatExchanger, Drum - from tespy.connections import Connection - - - class WasteHeatSteamGenerator(Subsystem): - """Class documentation""" - - def create_comps(self): - """Create the subsystem's components.""" - self.comps['eco'] = HeatExchanger('economizer') - self.comps['eva'] = HeatExchanger('evaporator') - self.comps['sup'] = HeatExchanger('superheater') - self.comps['drum'] = Drum('drum') - - def create_conns(self): - """Define the subsystem's connections.""" - self.conns['eco_dr'] = Connection( - self.comps['eco'], 'out2', self.comps['drum'], 'in1') - self.conns['dr_eva'] = Connection( - self.comps['drum'], 'out1', self.comps['eva'], 'in2') - self.conns['eva_dr'] = Connection( - self.comps['eva'], 'out2', self.comps['drum'], 'in2') - self.conns['dr_sup'] = Connection( - self.comps['drum'], 'out2', self.comps['sup'], 'in2') - self.conns['sup_eva'] = Connection( - self.comps['sup'], 'out1', self.comps['eva'], 'in1') - self.conns['eva_eco'] = Connection( - self.comps['eva'], 'out1', self.comps['eco'], 'in1') - -Import your subsystem -^^^^^^^^^^^^^^^^^^^^^ - -In a different script, we create a network and import the subsystem we just -created along with the different tespy classes required. The location of the -:code:`mysubsystems.py` file must be known by your python installation or lie -within the same folder as your script. - -.. code-block:: python - - from tespy.networks import Network - from tespy.components import Source, Sink - from tespy.connections import Connection - import numpy as np - - from mysubsystems import WasteHeatSteamGenerator as WHSG - - # %% network definition - - fluid_list = ['air', 'water'] - nw = Network(fluid_list, p_unit='bar', T_unit='C') - - # %% component definition - - feed_water = Source('feed water inlet') - steam = Sink('live steam outlet') - - waste_heat = Source('waste heat inlet') - chimney = Sink('waste heat chimney') - - sg = WHSG('waste heat steam generator') - - # %% connection definition - - fw_sg = Connection(feed_water, 'out1', sg.comps['eco'], 'in2') - sg_ls = Connection(sg.comps['sup'], 'out2', steam, 'in1') - fg_sg = Connection(waste_heat, 'out1', sg.comps['sup'], 'in1') - sg_ch = Connection(sg.comps['eco'], 'out1', chimney, 'in1') - - nw.add_conns(fw_sg, sg_ls, fg_sg, sg_ch) - nw.add_subsys(sg) - - # %% connection parameters - - fw_sg.set_attr(fluid={'air': 0, 'water': 1}, T=25) - fg_sg.set_attr(fluid={'air': 1, 'water': 0}, T=650, m=100) - - sg_ls.set_attr(p=130) - sg_ch.set_attr(p=1) - - sg.conns['eva_dr'].set_attr(x=0.6) - - # %% component parameters - - sg.comps['eco'].set_attr(pr1=0.999, pr2=0.97, - design=['pr1', 'pr2', 'ttd_u'], - offdesign=['zeta1', 'zeta2', 'kA_char']) - - sg.comps['eva'].set_attr(pr1=0.999, ttd_l=20, design=['pr1', 'ttd_l'], - offdesign=['zeta1', 'kA_char']) - - sg.comps['sup'].set_attr(pr1=0.999, pr2=0.99, ttd_u=50, - design=['pr1', 'pr2', 'ttd_u'], - offdesign=['zeta1', 'zeta2', 'kA_char']) - - sg.conns['eco_dr'].set_attr(Td_bp=-5, design=['Td_bp']) - - # %% solve - - # solve design case - nw.solve('design') - nw.print_results() - nw.save('tmp') - - # offdesign test - nw.solve('offdesign', design_path='tmp') - - -Add more flexibility --------------------- - -If you want to add even more flexibility, you might need to manipulate the -:code:`__init__` method of your custom subsystem class. Usually, you do not -need to override this method. However, if you need additional parameters, e.g. -in order to alter the subsystem's topology or specify additional information, -take a look at the :py:class:`tespy.components.subsystem.Subsystem` class and -add your code between the label declaration and the components and connection -creation in the :code:`__init__` method. - -For example, if you want a variable number of inlets and outlets because you -have a variable number of components groups within your subsystem, you may -introduce an attribute which is set on initialisation and lets you create and -parameterize components and connections generically. This might be very -interesting for district heating systems, turbines with several sections of -equal topology, etc.. For a good start, you can have a look at the -:code:`sub_consumer.py` of the district heating network in the -`oemof_examples `_ -repository. diff --git a/docs/tutorials.rst b/docs/tutorials.rst new file mode 100644 index 000000000..90d09667e --- /dev/null +++ b/docs/tutorials.rst @@ -0,0 +1,93 @@ +.. _tespy_tutorial_label: + +~~~~~~~~~~~~~~~~~~ +Advanced Tutorials +~~~~~~~~~~~~~~~~~~ +We provide more advanced tutorials for you to better understand how to work +with more complex systems in TESPy. + +At the example of different heat pump topologies, you will learn to + +- create a more complex model *step by step* and get the idea of designing a + plant and calculating the offdesign behavior. +- set up a code structure, which allows you to generate stable starting values + flexibly, helping you to build reliable setups faster. +- use the inbuilt exergy analysis method in a simple geothermal heat pump + setting. + +Furthermore, we introduce the coupling of TESPy with pygmo in order to create +an optimization problem, which optimizes thermal efficiency of a clausius +rankine power plant. Another typical setup are heat recovery steam generators +using exhaust gases from an open cycle gas turbine. + +Finally, we provide an approach on how to model complex district heating +systems. If you have any questions, ideas for other tutorials or feedback, +please reach out to us. We are looking forward to hearing from you! + +.. grid:: 2 + :gutter: 1 + + .. grid-item-card:: Build complex systems step by step + :link: tespy_tutorial_heat_pump_label + :link-type: ref + + .. image:: /_static/images/tutorials/heat_pump_stepwise/flowsheet.svg + :class: only-light + + .. image:: /_static/images/tutorials/heat_pump_stepwise/flowsheet_darkmode.svg + :class: only-dark + + .. grid-item-card:: Generate stable starting values + :link: tespy_tutorial_starting_values_label + :link-type: ref + + .. image:: /_static/images/tutorials/heat_pump_starting_values/COP_by_wf.svg + :class: only-light + + .. image:: /_static/images/tutorials/heat_pump_starting_values/COP_by_wf_darkmode.svg + :class: only-dark + +.. grid:: 2 + :gutter: 1 + + .. grid-item-card:: Exergy analysis of a heat pump + :link: tespy_tutorial_heat_pump_exergy_label + :link-type: ref + + .. image:: /_static/images/tutorials/heat_pump_exergy/diagram_E_D.svg + :class: only-light + + .. image:: /_static/images/tutorials/heat_pump_exergy/diagram_E_D_darkmode.svg + :class: only-dark + + .. grid-item-card:: Building Complex District Heating Systems + + Coming soon! + +.. grid:: 2 + :gutter: 1 + + .. grid-item-card:: Optimization of a thermal power plant + :link: tespy_tutorial_pygmo_optimization_label + :link-type: ref + + .. image:: /_static/images/tutorials/pygmo_optimization/pygmo_optimization.svg + :class: only-light + + .. image:: /_static/images/tutorials/pygmo_optimization/pygmo_optimization_darkmode.svg + :class: only-dark + + .. grid-item-card:: Gas Turbine with Heat Recovery Steam Generator + + Coming soon! + + +.. toctree:: + :maxdepth: 1 + :glob: + :hidden: + + tutorials/heat_pump_steps.rst + tutorials/starting_values.rst + tutorials/heat_pump_exergy.rst + tutorials/pygmo_optimization.rst diff --git a/docs/tutorials_examples/district_heating.rst b/docs/tutorials/district_heating.rst similarity index 85% rename from docs/tutorials_examples/district_heating.rst rename to docs/tutorials/district_heating.rst index 11ce3d54f..f241f4b24 100644 --- a/docs/tutorials_examples/district_heating.rst +++ b/docs/tutorials/district_heating.rst @@ -1,3 +1,5 @@ +.. _tespy_tutorial_district_heating_label: + Distric heating system ---------------------- @@ -10,7 +12,7 @@ Although the structure of the system (see the Figure below) does not seem very complex, it has more than 120 components. But we can easily determine repeating structures for the consumers and this is, where the subsystems come in place. -.. figure:: /api/_images/dhs.svg +.. figure:: /_static/images/tutorials/district_heating_system/dhs.svg :align: center Figure: Topology of the heating system. @@ -22,17 +24,17 @@ closed) or is open to connect to another part of the grid (industrial area, see subsystem open). Additionally, each branch of the main grid is connected to the upstream part with the fork subsystem (Ki, see subsystem fork). -.. figure:: /api/_images/dhs_closed.svg +.. figure:: /_static/images/tutorials/district_heating_system/dhs_closed.svg :align: center Figure: Generic topology of the dead end subsystem. -.. figure:: /api/_images/dhs_open.svg +.. figure:: /_static/images/tutorials/district_heating_system/dhs_open.svg :align: center Figure: Generic topology of the open subsystem. -.. figure:: /api/_images/dhs_forks.svg +.. figure:: /_static/images/tutorials/district_heating_system/dhs_forks.svg :align: center Figure: Generic topology of the forks (variable number of branches). diff --git a/docs/tutorials_examples/tutorial_heat_pump_exergy.rst b/docs/tutorials/heat_pump_exergy.rst similarity index 86% rename from docs/tutorials_examples/tutorial_heat_pump_exergy.rst rename to docs/tutorials/heat_pump_exergy.rst index f44a38418..c9038772b 100644 --- a/docs/tutorials_examples/tutorial_heat_pump_exergy.rst +++ b/docs/tutorials/heat_pump_exergy.rst @@ -1,12 +1,8 @@ +.. _tespy_tutorial_heat_pump_exergy_label: + Exergy Analysis of a Ground-Coupled Heat Pump --------------------------------------------- -.. contents:: - :depth: 1 - :local: - :backlinks: top - - Task ^^^^ @@ -29,17 +25,22 @@ plotted. GitHub. Since there is an existing tutorial for -:ref:`creating a heat pump `, this tutorial starts -with the explanations for setting up the exergy analysis. Note, however, that -the heat pump model differs slightly in structure from the model in the +:ref:`creating a heat pump `, this tutorial +starts with the explanations for setting up the exergy analysis. However note, +that the heat pump model differs slightly in structure from the model in the previous tutorial. All related Python scripts of the fully working GCHP-model are listed in the following: -- GCHP with NH3 (the model only): :download:`NH3 ` -- GCHP with R410A (the model only): :download:`R410A ` -- GCHP with NH3 (model and post-processing): :download:`NH3_calculations ` -- GCHP with R410A (model and post-processing): :download:`R410A_calculations ` -- Plots of the results of the parameter variations: :download:`plots ` +- GCHP with NH3 (the model only): + :download:`NH3.py ` +- GCHP with R410A (the model only): + :download:`R410A.py ` +- GCHP with NH3 (model and post-processing): + :download:`NH3_calculations.py ` +- GCHP with R410A (model and post-processing): + :download:`R410A_calculations.py ` +- Plots of the results of the parameter variations: + :download:`plots.py ` The figure below shows the topology of the GCHP. In this model, a ground-coupled heat pump is modeled, which is for instance connected to a @@ -49,9 +50,17 @@ ground heat feed flow (Source) and return flow (Sink). The heat pump circuit consists of the basic components: condenser, expansion valve, evaporator and compressor. -.. figure:: /api/_images/heat_pump_exergy_flowsheet.svg +.. figure:: /_static/images/tutorials/heat_pump_exergy/flowsheet.svg + :align: center + :alt: Topology of the Ground-Couped Heat Pump (GCHP) + :figclass: only-light + + Figure: Topology of the Ground-Couped Heat Pump (GCHP). + +.. figure:: /_static/images/tutorials/heat_pump_exergy/flowsheet_darkmode.svg :align: center :alt: Topology of the Ground-Couped Heat Pump (GCHP) + :figclass: only-dark Figure: Topology of the Ground-Couped Heat Pump (GCHP). @@ -108,8 +117,10 @@ The units used and the ambient state are defined as follows: .. code-block:: python - nw = Network(fluids=['water', 'NH3'], T_unit='C', p_unit='bar', - h_unit='kJ / kg', m_unit='kg / s') + nw = Network( + fluids=['water', 'NH3'], T_unit='C', p_unit='bar', + h_unit='kJ / kg', m_unit='kg / s' + ) pamb = 1.013 Tamb = 2.8 @@ -133,14 +144,14 @@ flow temperature in the design calculation is set to :code:`Tgeo + 1.5°C` and the return flow temperature is set to :code:`Tgeo - 1.5°C`. The complete Python code of the TESPy models is available in the scripts -:download:`NH3.py ` with NH3 as refrigerant and -:download:`R410A.py ` with R410A as refrigerant. All -other specified values of the component and connection parameters can be found -in these Python scripts. +:download:`NH3.py ` with NH3 as +refrigerant and :download:`R410A.py ` +with R410A as refrigerant. All other specified values of the component and +connection parameters can be found in these Python scripts. In the scripts -:download:`NH3_calculations.py ` and -:download:`R410A_calculations.py `, +:download:`NH3_calculations.py ` and +:download:`R410A_calculations.py `, the Python code of the TESPy models of the GCHP is extended to handle the different tasks mentioned in the introduction. In these two scripts you can find the corresponding Python code for all calculations that will be presented @@ -212,7 +223,7 @@ saved with the code shown below. diagram.save('NH3_logph.svg') -.. figure:: /api/_images/NH3_logph.svg +.. figure:: /_static/images/tutorials/heat_pump_exergy/NH3_logph.svg :align: center :alt: Fluid Property Diagram h-log(p) of the GCHP @@ -293,7 +304,7 @@ The product exergy is represented by the bus :code:`power`. The busses :code:`heat_cons` and :code:`heat_geo` are passed as fuel exergy. In the example of the GCHP, only :code:`E_F` and :code:`E_P` are defined. Other examples of exergy analysis setup can be found in the -:ref:`TESPy analysis ` page and in the API +:ref:`TESPy analysis ` page and in the API documentation of class :py:class:`tespy.tools.analyses.ExergyAnalysis`. .. code-block:: python @@ -308,7 +319,7 @@ The :py:meth:`tespy.tools.analyses.ExergyAnalysis.analyse` method will run the exergy analysis automatically. This method expects information about the ambient pressure and ambient temperature. Additionally, an automatic check of consistency is performed by the analysis as further described in -:ref:`TESPy analysis `. +:ref:`TESPy analysis `. Results +++++++ @@ -321,7 +332,7 @@ The results can be printed by using the ean.print_results() Further descriptions of which tables are printed and how to select what is -printed can be found in the :ref:`TESPy analysis section `. +printed can be found in the :ref:`TESPy analysis section `. There you can also find more detailed descriptions of how to access the underlying data for the tabular printouts, which are stored in `pandas DataFrames `_. @@ -344,7 +355,7 @@ method returns a dictionary containing links and nodes for the sankey diagram. plot(fig, filename='NH3_sankey') -.. figure:: /api/_images/NH3_sankey.svg +.. figure:: /_static/images/tutorials/heat_pump_exergy/NH3_sankey.svg :align: center :alt: Sankey diagram of the Ground-Coupled Heat Pump (GCHP) @@ -354,7 +365,7 @@ method returns a dictionary containing links and nodes for the sankey diagram. In the figure above you can see the sankey diagram which is created by running the script of the GCHP with NH3 as refrigerant. Information about, for example, the colors used or the node order can be found in the -:ref:`TESPy analysis section `. +:ref:`TESPy analysis section `. Post-Processing ^^^^^^^^^^^^^^^ @@ -369,7 +380,7 @@ considered: In order to be able to compare the results of the two refrigerants NH3 and R410A, plots of the results of the mentioned issues are created in a separate -plot script :download:`plots.py `. The plots in this +plot script :download:`plots.py `. The plots in this tutorial are created with `Matplotlib `_. For installation instructions or further documentation please see the Matplotlib documentation. @@ -433,17 +444,27 @@ different refrigerants NH3 and R410A in a separate script. script for plot creation, all data frames must be saved as a file with their own individual name. -In the separate plot script (:download:`plots.py `) the :code:`.csv` files can -now be re-imported to create plots with Matplotlib. The Python code for -creating the bar chart is included in the previously referenced plot script -and can be found there. For more information on creating plots with -Matplotlib, please check the +In the separate plot script +(:download:`plots.py `) the +:code:`.csv` files can now be re-imported to create plots with Matplotlib. The +Python code for creating the bar chart is included in the previously +referenced plot script and can be found there. For more information on +creating plots with Matplotlib, please check the `Matplotlib documentation `_. The resulting bar chart is shown below. -.. figure:: /api/_images/diagram_E_D.svg +.. figure:: /_static/images/tutorials/heat_pump_exergy/diagram_E_D.svg :align: center :alt: Comparison of exergy destruction and exergy efficiency + :figclass: only-light + + Figure: Comparison of exergy destruction and exergy efficiency of both + working fluids in design case. + +.. figure:: /_static/images/tutorials/heat_pump_exergy/diagram_E_D_darkmode.svg + :align: center + :alt: Comparison of exergy destruction and exergy efficiency + :figclass: only-dark Figure: Comparison of exergy destruction and exergy efficiency of both working fluids in design case. @@ -533,12 +554,21 @@ temperatures is carried out as an offdesign calculation. Again, no new The results of the calculation can be plotted as shown in the following figure. The related Python code to create this plot can be found in the plot -script (:download:`plots.py `). For further documentation -please see the `Matplotlib documentation `_. +script (:download:`plots.py `). For +further documentation please see the `Matplotlib `__ +documentation. -.. figure:: /api/_images/diagram_eps_Tamb_Tgeo.svg +.. figure:: /_static/images/tutorials/heat_pump_exergy/diagram_eps_Tamb_Tgeo.svg :align: center :alt: Varying Tamb and Tgeo of the GCHP + :figclass: only-light + + Figure: Varying ambient and geothermal temperature. + +.. figure:: /_static/images/tutorials/heat_pump_exergy/diagram_eps_Tamb_Tgeo_darkmode.svg + :align: center + :alt: Varying Tamb and Tgeo of the GCHP + :figclass: only-dark Figure: Varying ambient and geothermal temperature. @@ -612,11 +642,19 @@ of :code:`Ths` as columns. The results of this calculation are shown in the following figure. The corresponding Python code can likewise be found in the plot script -(:download:`plots.py `). +(:download:`plots.py `). -.. figure:: /api/_images/diagram_cop_eps_Tgeo_Ths.svg +.. figure:: /_static/images/tutorials/heat_pump_exergy/diagram_cop_eps_Tgeo_Ths.svg :align: center :alt: Varying Tgeo and Ths of the GCHP + :figclass: only-light + + Figure: Varying geothermal and heating system temperature. + +.. figure:: /_static/images/tutorials/heat_pump_exergy/diagram_cop_eps_Tgeo_Ths_darkmode.svg + :align: center + :alt: Varying Tgeo and Ths of the GCHP + :figclass: only-dark Figure: Varying geothermal and heating system temperature. @@ -644,15 +682,23 @@ similarity to the previous parameter variation, the corresponding Python code is not presented, but can be found in the scripts linked at the beginning instead. -.. figure:: /api/_images/diagram_cop_eps_Tgeo_Q.svg +.. figure:: /_static/images/tutorials/heat_pump_exergy/diagram_cop_eps_Tgeo_Q.svg + :align: center + :alt: Varying Tgeo and Q of the GCHP + :figclass: only-light + + Figure: Varying geothermal temperature and heat load. + +.. figure:: /_static/images/tutorials/heat_pump_exergy/diagram_cop_eps_Tgeo_Q_darkmode.svg :align: center :alt: Varying Tgeo and Q of the GCHP + :figclass: only-dark Figure: Varying geothermal temperature and heat load. The results are shown in the figure above. As before, the Python code for creating the plot can be found in the plot script -(:download:`plots.py `). +(:download:`plots.py `). The partial load behavior of the GCHP, which results from the characteristic lines of the efficiencies of the individual components, can be recognized in the curves shown. @@ -667,7 +713,7 @@ but also in the Python script of the plots, if a plot is created with the stand-alone plot script. More examples of exergy analysis can be found in the -:ref:`TESPy analysis section ` and in the API +:ref:`TESPy analysis section ` and in the API documentation of the :py:class:`tespy.tools.analyses.ExergyAnalysis` class. If you are interested in contributing or have questions and remarks on this tutorial, you are welcome to file an issue at our GitHub page. diff --git a/docs/tutorials/heat_pump_steps.rst b/docs/tutorials/heat_pump_steps.rst new file mode 100644 index 000000000..9cbee94a7 --- /dev/null +++ b/docs/tutorials/heat_pump_steps.rst @@ -0,0 +1,491 @@ +.. _tespy_tutorial_heat_pump_label: + +Build a Heat Pump Stepwise +-------------------------- + +We provide the full script presented in this tutorial here: +:download:`stepwise.py ` + +.. figure:: /_static/images/tutorials/heat_pump_stepwise/flowsheet.svg + :align: center + :alt: Topology of the heat pump system + :figclass: only-light + + Figure: Topology of the heat pump system + +.. figure:: /_static/images/tutorials/heat_pump_stepwise/flowsheet_darkmode.svg + :align: center + :alt: Topology of the heat pump system + :figclass: only-dark + + Figure: Topology of the heat pump system + +Task +^^^^ +This tutorial introduces you in how to model a heat pump in TESPy. You can see +the plants topology in the figure. + +The main purpose of the heat pump is to deliver heat e.g. for the consumers of +a heating system. Thus, the heat pump's parameters will be set in a way, which +supports this target. Generally, if systems are getting more complex, it is +highly recommended to set up your plant in incremental steps. This tutorial +divides the plant in three sections: The consumer part, the valve and the +evaporator and the compressor as last element. Each new section will be +appended to the existing ones. + +The system will be built up in a way, that independent of what working fluid +we use, we will be able to generate stable starting values. After achieving +that, the final parameters are specified instead of the initial values. + +Set up a Network +^^^^^^^^^^^^^^^^ +First, we have to create an instance of the +:py:class:`tespy.networks.network.Network` class. The network is the main +container of the model and will be required in all following sections. First, +it is necessary to specify a list of the fluids used in the plant. In this +example we will work with water (H\ :sub:`2`\O) and ammonia (NH\ :sub:`3`\). +Water is used for the cold side of the heat exchanger, for the consumer and +for the hot side of the environmental temperature. Ammonia is used as +refrigerant within the heat pump circuit. If you don’t specify the unit +system, the variables are set to SI-Units. We also keep the working fluid a +variable to make reusing the script with a different working fluid easy. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_1] + :end-before: [sec_2] + +We will use °C, bar and kJ/kg as units for temperature and enthalpy. + +Modeling the heat pump: Consumer system +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. figure:: /_static/images/tutorials/heat_pump_stepwise/flowsheet_p1.svg + :align: center + :alt: First part of the system + :figclass: only-light + + Figure: First part of the system + +.. figure:: /_static/images/tutorials/heat_pump_stepwise/flowsheet_p1_darkmode.svg + :align: center + :alt: First part of the system + :figclass: only-dark + + Figure: First part of the system + +Components +++++++++++ +We will start with the consumer as the plant will be designed to deliver a +specific heat flow. From the figure above you can determine the components of +the consumer system: condenser, pump and the consumer ( +:py:class:`tespy.components.heat_exchangers.simple.HeatExchangerSimple` +). Additionally we need a source and a sink for the consumer and the heat pump +circuit respectively. We will import all necessary components already in the +first step, so the imports will not need further adjustment. + +.. tip:: + + We label the sink for the refrigerant :code:`"valve"`, as for our next + calculation the valve will be attached there instead of the sink. In this + way, the fluid properties can be initialized at the interface-connection, + too. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_2] + :end-before: [sec_3] + +Connections ++++++++++++ +In the next steps we will connect the components in order to form the network. +Every connection requires the source, the source id, the target and the target +id as arguments: the source is the component from which the connection +originates, the source id is the outlet id of that component. This applies +analogously to the target. To find all inlet and outlet ids of a component look +up the class documentation of the respective component. An overview of the +components available and the class documentations is provided in the +:ref:`TESPy modules overview `. The +:py:class:`tespy.connections.connection.Ref` class is used specify fluid +property values by referencing fluid properties of different connections. It +is used in a later step. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_3] + :end-before: [sec_4] + +.. seealso:: + + As we learned in the :ref:`basic introduction ` + instead of just connecting the consumer's outlet to the pump's inlet, we + must make use of the CycleCloser. Closing a cycle without further + adjustments will always result in a linear dependency in the fluid and the + mass flow equations. The + :py:class:`tespy.components.basics.cycle_closer.CycleCloser` component + makes sure, the fluid properties pressure and enthalpy are identical at + the inlet and the outlet. The component will prompt a warning, if the mass + flow or the fluid composition at its outlet are different to those at its + inlet. A different solution to this problem, is adding a merge and a + splitter at some point of your network and connect the second inlet/outlet + to a source/sink. This causes residual mass flow and residual fluids to + emerge/drain there. + +Parametrization ++++++++++++++++ +For the condenser we set pressure ratios on hot and cold side. The consumer +will have pressure losses, too. Further we set the isentropic efficiency for +the pump. The most important parameter is the consumer's heat demand since it +decides the overall mass flow in the systems. + +.. tip:: + + In this tutorial we will first build the system with parameters that + ensure stable starting values for a simulation, which in the end will be + switched to reasonable values for the individual parts of the system. For + example, instead of the evaporation pressure we will use the terminal + temperature difference at the condenser instead. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_4] + :end-before: [sec_5] + +In order to calculate this network further parametrization is necessary, as +e.g. the fluids are not determined yet: At the hot inlet of the condenser we +define the temperature, pressure and the fluid vector. A good guess for +pressure can be obtained from CoolProp's PropsSI function. We know that the +condensation temperature must be higher than the consumer's feed flow +temperature. Therefore we can set the pressure to a slightly higher value of +that temperature's corresponding condensation pressure. + +The same needs to be done for the consumer cycle. We suggest to set +the parameters at the pump's inlet. On top, we assume that the consumer +requires a constant inlet temperature. The :code:`CycleCloser` automatically +makes sure, that the fluid's state at the consumer's outlet is the same as at +the pump's inlet. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_5] + :end-before: [sec_6] + +Solve ++++++ +After creating the system, we want to solve our network. Until we have not +set up the full system we will run design case calculations. + +.. note:: + + In TESPy there are two different types of calculations: design point and + offdesign calculation. + + Generally, the design calculation is used for designing your system in the + way you want it to look like. This means, that you might want to specify a + design point isentropic efficiency, pressure loss or terminal temperature + difference. After you have designed your system, you are able to make + offdesign calculations with TESPy. The offdesign calculation is used to + predict the system's behavior at different points of operation. For this + case, this might be different ambient temperature, different feed flow + temperature, or partial load. Add the end of this tutorial, you will learn + how to run the offdesign calculation. + +.. seealso:: + + For general information on the solving process in TESPy and available + parameters check the corresponding section in the + :ref:`TESPy modules introduction `. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_6] + :end-before: [sec_7] + + +Valve and evaporator system +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Next we will add the valve and the evaporator system to our existing network. +The figure below indicates the sections we will append in this step. This part +contains of a valve followed by an evaporator with a drum (separating +saturated liquid from saturated gas) and a superheater. + +.. figure:: /_static/images/tutorials/heat_pump_stepwise/flowsheet_p2.svg + :align: center + :alt: Second part of the system + :figclass: only-light + + Figure: Second part of the system + +.. figure:: /_static/images/tutorials/heat_pump_stepwise/flowsheet_p2_darkmode.svg + :align: center + :alt: Second part of the system + :figclass: only-dark + + Figure: Second part of the system + +Components +++++++++++ +First, we need to import the new components, which are +:py:class:`tespy.components.nodes.drum.Drum`, +:py:class:`tespy.components.heat_exchangers.base.HeatExchanger` and +:py:class:`tespy.components.piping.valve.Valve`. We will add these components +to the script. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_7] + :end-before: [sec_8] + +Connections ++++++++++++ +Since the old connection :code:`1` lead to a sink, we have to replace this +connection in the network. We can do that by using the method +:code:`del_conns` passing :code:`c1`. After that, we can create the new +connections and add them to the network as we did before. + +The valve connects to the drum at the inlet :code:`'in1'`. The drum's outlet +:code:`'out1'` is saturated liquid and connects to the evaporator's cold side +inlet :code:`'in2'`. The inlet reconnects to the drum's inlet :code:`'in2'`. +The superheater's cold side connects to the drum's outlet :code:`'out2'`. +On the ambient side we simply connect the source to the superheater to the +evaporator and finally to the ambient sink. This will add the following +connections to the model: + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_8] + :end-before: [sec_9] + +.. attention:: + + The drum is special component, it has an inbuilt CycleCloser, therefore + although we are technically forming a cycle at the drum's outlet 1 to its + inlet 2, we do not need to include a CycleCloser here. + +Parametrization ++++++++++++++++ +Previous parametrization stays untouched. Regarding the evaporator, we specify +pressure ratios on hot side as well as the evaporation pressure, for which we +can obtain a good initial guess based on the ambient temperature level using +CoolProp. From this specification the pinch point layout will be a result, +similar as in waste heat steam generators. The pressure ratio of the cold side +*MUST NOT* be specified in this setup as the drum imposes pressure equality +for all inlets and outlets. + +The superheater will also use the pressure ratios on hot and cold side. +Further we set a value for the enthalpy at the working fluid side outlet. This +determines the degree of overheating and is again based on a good guess. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_9] + :end-before: [sec_10] + +Next step is the connection parametrization: The pressure in the drum and the +enthalpy of the wet steam reentering the drum need to be determined. For the +enthalpy we can specify the vapor mass fraction :code:`x` determining the +degree of evaporation. On the hot side inlet of the superheater we define the +temperature, pressure and the fluid. At last we have to fully determine the +state of the incoming fluid at the superheater's hot side. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_10] + :end-before: [sec_11] + +Solve ++++++ +We can again run a simulation after adding these parts. This step is not +required, but in larger, more complex networks, it is recommended to achieve +better convergence. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_11] + :end-before: [sec_12] + +Compressor system +^^^^^^^^^^^^^^^^^ +To complete the heat pump, we will add the compressor system to our existing +network. This requires to change the connections 0, 6 and 17. The connection 6 +has to be changed to include the compressor. After the last compressor stage, +connection 0 has to redefined, since we need to include the CycleCloser of the +working fluid's cycle. The connection 17 has to be connected to the heat +exchanger for intermittent cooling as well as the bypass. + +.. figure:: /_static/images/tutorials/heat_pump_stepwise/flowsheet.svg + :align: center + :alt: Topology of the heat pump system + :figclass: only-light + + Figure: Topology of the heat pump system + +.. figure:: /_static/images/tutorials/heat_pump_stepwise/flowsheet_darkmode.svg + :align: center + :alt: Topology of the heat pump system + :figclass: only-dark + + Figure: Topology of the heat pump system + +Components +++++++++++ +This part contains two compressors with intermittent cooling between them. The +cold side of the heat exchanger will be connected to a pump upstream and to +the superheater downstream. The bypass is used to give the system flexibility +in the temperature levels between the heat exchangers. We will also replace +the source for the refrigerant of :code:`c0` at the condenser with another +CycleCloser to make sure the fluid properties after the second compressor are +identical to the fluid properties at the condenser's inlet. + +.. tip:: + + The intermittent cooling extracts heat from the cycle. As this heat is + however used to increase the evaporation pressure of the working fluid due + to the higher temperature level of the heat source, the reduction is very + limited. We use a two stage compressor, because in a single stage + compression, the outlet temperature of the refrigerant might violate + technical boundary conditions of the real-world component. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_12] + :end-before: [sec_13] + +Connections ++++++++++++ +We remove connections 0, 6 and 13 from the network, define the new connections +and add them again. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_13] + :end-before: [sec_14] + +Parametrization ++++++++++++++++ +For the first compressor we set the pressure ratio to the square root of the +full pressure ration between condensation and evaporation. In the first step, +we do not impose isentropic efficiency, because the respective equations are +quite sensitive to good starting value. We will set these values after the +full system has been calculated. The pump's isentropic efficiency value is not +as critical, therefore we set this value. The intermittent cooling imposes +pressure losses on both sides. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_14] + :end-before: [sec_15] + +Regarding the connections we set enthalpy values for all working fluid side +connections. After the superheater and intermittent cooling the value will be +near saturation (enthalpy value of connection c5), after the compressors it +will be higher. + +For the ambient side, we set temperature, pressure and fluid +at connection 11. On top of that, we can specify the temperature of the +ambient water after leaving the intermittent cooler. + +With readding of connection 0 we have to set the fluid and the pressure again, +but not the temperature value, because this value will be a result of the +condensation pressure and the given enthalpy at the compressor's outlet. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_15] + :end-before: [sec_16] + +Solve and Set Final System Parameters ++++++++++++++++++++++++++++++++++++++ +Now we solve again. After that, we can exchange our good guesses with actual +useful parameters: + +The condensation and evaporation pressure levels will be replaced by terminal +temperature values of the condenser and the evaporator respectively. The lower +terminal temperature value of the evaporator :code:`ttd_l` defines the pinch +point. The upper terminal temperature value :code:`ttd_u` of the condenser +defines the condensation pressure. + +The degree of superheating in the superheater will be determined by the upper +terminal temperature instead of the enthalpy value at connection 6. The outlet +enthalpies after both compressors are replaced by the isentropic efficiency +values. Finally, the enthalpy after the intermittent cooling is replaced by +the temperature difference to the boiling point. With this we can ensure, the +working fluid does not start to condensate at the intermittent cooler. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_16] + :end-before: [sec_17] + +Calculate Partload Performance +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +After setting up the full system, we want to predict partload operation at +different values for the consumer's heat demand. Some of the values utilized +in the previous setup will change, if a component is not operated at its +design point. This is individual to every system, so the designer has to +answer the question: Which parameters are design point parameters and how does +the component perform at a different operation point. + +.. tip:: + + To make the necessary changes to the model, we can specify a design and an + offdesign attribute, both lists containing component or connection + parameter names. All parameters specified in the design attribute of a + component or connection, will be unset in a offdesign calculation, all + parameters specified in the offdesign attribute of a component or + connection will be set for the offdesign calculation. The value for these + parameters is the value derived from the design-calculation. + +The changes we want to apply can be summarized as follows: + +- All heat exchangers should be calculated based on their heat transfer + coefficient with a characteristic for correction of that value depending + on the change of mass flow (:code:`kA_char`). Therefore terminal temperature + value specifications need to be added to the design parameters. Also, the + temperature at connection 14 cannot be specified anymore, since it will be a + result of the intermittent cooler's characteristics. +- Pumps and compressors will have a characteristic function for their + isentropic efficiency instead of a constant value (:code:`eta_s_char`). +- Pressure drops in components will be a result of the changing mass flow + through that component given the diameter in the design. The pressure ratio + will therefore be replaced by :code:`zeta` for all heat exchangers. The zeta + value is a geometry independent value. + +On top of that, for the evaporator the characteristic function of the heat +transfer coefficient should follow different data than the default +characteristic. The name of that line is 'EVAPORATING FLUID' for the cold +side. The default line 'DEFAULT' will be kept for the hot side. These lines +are available in the :ref:`tespy.data ` module. + +.. attention:: + + If you run the offdesign simulation without any changes in the + specification values, the results must be identical as in the respective + design case! If they are not, it is likely, something went wrong. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_17] + :end-before: [sec_18] + +.. seealso:: + + If you want to learn more about handling characteristic functions you + should have a glance at the + :ref:`TESPy components section `. + +Finally, we can change the heat demand and run several offdesign calculations +to calculate the partload COP value. + +.. literalinclude:: /../tutorial/advanced/stepwise.py + :language: python + :start-after: [sec_18] + :end-before: [sec_19] + +After successfully modeling the heat pump in design and offdesign cases, you +can now start using your model for further calculations. For example, if you +have a time series of required heat flow of your consumer, you can loop over +the series and perform offdesign calculation adjusting the heat flow every +time. Of course, this is possible with every offdesign parameter. + +Have fun working with TESPy! diff --git a/docs/tutorials/pygmo_optimization.rst b/docs/tutorials/pygmo_optimization.rst new file mode 100644 index 000000000..2a4bf3fc1 --- /dev/null +++ b/docs/tutorials/pygmo_optimization.rst @@ -0,0 +1,215 @@ +.. _tespy_tutorial_pygmo_optimization_label: + +Thermal Power Plant Efficiency Optimization +------------------------------------------- + +Task +^^^^ +Designing a power plant meets multiple different tasks, such as finding the +optimal fresh steam temperature and pressure to reduce exhaust steam water +content, or the optimization of extraction pressures to maximize cycle +efficiency and many more. + +In case of a rather simple power plant topologies the task of finding +optimized values for e.g. extraction pressures is still manageable without any +optimization tool. As the topology becomes more complex and boundary +conditions come into play the usage of additional tools is recommended. The +following tutorial is intended to show the usage of PyGMO in combination with +TESPy to **maximize the cycle efficiency of a power plant with two** +**extractions.** + +You can download the code here: +:download:`optimization_example.py ` + +.. figure:: /_static/images/tutorials/pygmo_optimization/flowsheet.svg + :align: center + :alt: Topology of the power plant + :figclass: only-light + + Figure: Topology of the power plant + +.. figure:: /_static/images/tutorials/pygmo_optimization/flowsheet_darkmode.svg + :align: center + :alt: Topology of the power plant + :figclass: only-dark + + Figure: Topology of the power plant + +What is PyGMO? +^^^^^^^^^^^^^^ + +PyGMO (Python Parallel Global Multiobjective Optimizer, :cite:`Biscani2020`) +is a library that provides a large number of evolutionary optimization +algorithms. PyGMO can be used to solve constrained, unconstrained, single +objective and multi objective problems. + +Evolutionary Algorithms ++++++++++++++++++++++++ + +Evolutionary Algorithms (EA) are optimization algorithms inspired by biological +evolution. In a given population the algorithm uses the so called fitness +function to determine the quality of the solutions to each individual (set of +decision variables) problem. The best possible solution of the population is +called champion. Via mutation, recombination and selection your population +evolves to find better solutions. + +EA will never find an exact solution to your problem. They can only give an +approximation for the real optimum. + +Install PyGMO ++++++++++++++ + +.. tab-set:: + + .. tab-item:: conda + + With the conda package manager PyGMO is available for Linux, OSX and + Windows thanks to the infrastructure of + `conda-forge `_: + + .. code-block:: bash + + conda install -c conda-forge pygmo + + + Windows user can perform an installation from source as an alternative + to conda. For further information on this process we recommend the + `PyGMO installation `__ + accordingly. + + + .. tab-item:: pip (Linux only!) + + On Linux you also have the option to use the + `pip `_ package installer: + + .. code-block:: bash + + pip install pygmo + +Creating your TESPy-Model +^^^^^^^^^^^^^^^^^^^^^^^^^ +To use the API, you need to define a class holding a TESPy network. The +initialization of the class should build the network and run an initial +simulation. Furthermore, you have to define methods + +- to get component or connection parameters of the plant :code:`get_param`, +- to run a new simulation for every new input from PyGMO :code:`solve_model` + and +- to return the objective value :code:`get_objective`. + +First, we set up the class with the TESPy network. + +.. dropdown:: Display source code for the PowerPlant class + + .. literalinclude:: /../tutorial/advanced/optimization_example.py + :language: python + :start-after: [sec_1] + :end-before: [sec_2] + + +Next, we add the methods :code:`get_param`, :code:`solve_model` and +:code:`get_objective`. On top of that, we add a setter working in a similar +way as the getter. The objective is to maximize thermal efficiency as defined +in the equation below. + +.. math:: + + \eta_\mathrm{th}=\frac{|\sum P|}{\dot{Q}_{sg}} + +.. attention:: + + The sense of optimization is always minimization, therefore you need to + define your objective functions in the appropriate way: We return the + reciprocal value of the efficiency for this reason. + +We also have to make sure, only the results of physically feasible solutions +are returned. In case we have infeasible solutions, we can simply return +:code:`np.nan`. An infeasible solution is obtained in case the power of a +turbine is positive, the power of a pump is negative or the heat exchanged +in any of the preheaters is positive. We also check, if the calculation does +converge. + +.. dropdown:: Display source code for the class methods + + .. literalinclude:: /../tutorial/advanced/optimization_example.py + :language: python + :start-after: [sec_2] + :end-before: [sec_3] + +After this, we import the +:py:class:`tespy.tools.optimization.OptimizationProblem` class and create an +instance of our self defined class, which we pass to an instance of the +OptimizationProblem class. We also have to pass + +- the variables to optimize, +- the constraints to consider and +- the objective function name (you could define multiple in the + :code:`get_objective` method if you wanted). + +We set one inequality constraint, namely that the pressure of the first +extraction has to be higher than the pressure at the second one: + +.. math:: + + p_{e,1} > p_{e,2} + +To do this, we can set a lower limit for the pressure at connection 2 and +reference the pressure at connection 4 as seen in the code: + +.. literalinclude:: /../tutorial/advanced/optimization_example.py + :language: python + :start-after: [sec_3] + :end-before: [sec_4] + +Before we can run the optimization, we only need to select an appropriate +algorithm. After that we can start the optimization run. For more information +on algorithms available in the PyGMO framework and their individual +specifications please refer to the respective section in their online +documentation: +`list of algorithms `__. +Create an initial population and then specify the number of individuals, the +number of generations and call the +:py:meth:`tespy.tools.optimization.OptimizationProblem.run` method of your +:code:`OptimizationProblem` instance passing the algorithm, the population and +the number of individuals and generations. + +Run PyGMO-Optimization +^^^^^^^^^^^^^^^^^^^^^^ +The following code then simply runs the PyGMO optimization. + +.. literalinclude:: /../tutorial/advanced/optimization_example.py + :language: python + :start-after: [sec_4] + :end-before: [sec_5] + +In our run, we got: + +.. code:: bash + + Efficiency: 44.82 % + Extraction 1: 25.4756 bar + Extraction 2: 2.5428 bar + +.. figure:: /_static/images/tutorials/pygmo_optimization/pygmo_optimization.svg + :align: center + :alt: Scatter plot for all individuals during the optimization + :figclass: only-light + + Figure: Scatter plot for all individuals during the optimization + +.. figure:: /_static/images/tutorials/pygmo_optimization/pygmo_optimization_darkmode.svg + :align: center + :alt: Scatter plot for all individuals during the optimization + :figclass: only-dark + + Figure: Scatter plot for all individuals during the optimization + +Finally, you can access the individuals in each of the generations and you +can have a look at you population. For more info on the population API please +visit the pygmo documentation. + +.. literalinclude:: /../tutorial/advanced/optimization_example.py + :language: python + :start-after: [sec_5] + :end-before: [sec_6] diff --git a/docs/tutorials/starting_values.rst b/docs/tutorials/starting_values.rst new file mode 100644 index 000000000..b3d8c22dd --- /dev/null +++ b/docs/tutorials/starting_values.rst @@ -0,0 +1,210 @@ +.. _tespy_tutorial_starting_values_label: + +How to Generate Stable Starting Values +-------------------------------------- +Applying numerical algorithms and methods, the starting value of a variable +is the value used for the first iteration. With more complex TESPy models +it can happen that the simulation does not converge easily due to a +combination of "bad" starting values. The solver is especially vulnerable if +the specified parameters trigger complex equations with respect to the primary +variables. + +The primary variables of TESPy are mass flow, pressure, enthalpy and fluid +composition. If such a value is directly specified by the user, the solver has +a solution for this value before starting the first iteration. Therefore, +specifying a set of parameters largely including primary variables will +improve the convergence significantly. Based on the converged solution of a +initial simulation, it is then possible to adjust the parameters, for example, +unsetting pressure values and specifying efficiencies instead. + +Here we provide a short tutorial for you to better understand, how this +process could look like at the example of a subcritical heat pump with +different working fluids. + +.. note:: + + If the heat pump operates in trans- or supercritical range, some + modifications have to be made on this setup. We plan to include respective + examples here in the future. + +You can download the full code of this example here: +:download:`starting_values.py ` + +Topology of the heat pump +^^^^^^^^^^^^^^^^^^^^^^^^^ +Following the first tutorial a slightly different topology for a heat pump +with internal heat exchangers is considered instead of dumping the heat to the +ambient. You can see the plant topology in the figure below. + +.. figure:: /_static/images/tutorials/heat_pump_starting_values/flowsheet.svg + :align: center + :alt: Topology of heat pump with internal heat exchanger + :figclass: only-light + + Figure: Topology of heat pump with internal heat exchanger + +.. figure:: /_static/images/tutorials/heat_pump_starting_values/flowsheet_darkmode.svg + :align: center + :alt: Topology of heat pump with internal heat exchanger + :figclass: only-dark + + Figure: Topology of heat pump with internal heat exchanger + +The system consists of a consumer system, a valve, an evaporator system, a +compressor and additionally an internal heat exchanger. In order to simulate +this heat pump, the TESPy model has to be built up. First, the network has to +be initialized and the refrigerants used have to be specified. This example +shows how to make the heat pump model work with a variety of working fluids +with water on both the heat source and heat sink side of the system. + +Running into errors +^^^^^^^^^^^^^^^^^^^ +As always, we start by importing the necessary TESPy classes. + +.. literalinclude:: /../tutorial/advanced/starting_values.py + :language: python + :start-after: [sec_1] + :end-before: [sec_2] + +Then, we can build the network by defining components and connections. The +working fluid will be set with the variable `wf`, `"NH3"` is used in the first +setup. This way, we will be able to change the working fluid in a flexible +way. + +.. dropdown:: Click to expand to code section + + .. literalinclude:: /../tutorial/advanced/starting_values.py + :language: python + :start-after: [sec_2] + :end-before: [sec_3] + +After setting up the topology, the system's parameters should be set in the +following way: + +- Heat sink temperature levels (`T` at 23 and 24) +- Heat source temperature levels (`T` at 11 and 13) +- Degree of overheating after the internal heat exchanger (`Td_bp` at 2) +- Pinch point temperature difference at the evaporator (`ttd_l`) to derive + evaporation pressure +- Temperature difference at the condenser (`ttd_u`) to derive condensation + pressure +- Saturated gaseous state of the working fluid (`x=1`) after leaving the + evaporator +- Efficiencies of pumps and the compressor (`eta_s`) +- Pressure losses in all heat exchangers (`pr1`, `pr2`, `pr`) +- Consumer heat demand (`Q`) + +.. dropdown:: Click to expand to code section + + .. literalinclude:: /../tutorial/advanced/starting_values.py + :language: python + :start-after: [sec_3] + :end-before: [sec_4] + +The system should be well defined with the parameter settings, however no +solution can be found. We might run in some error, like + +.. error:: + + .. code-block:: bash + + ERROR:root:Singularity in jacobian matrix, calculation aborted! Make + sure your network does not have any linear dependencies in the + parametrisation. Other reasons might be + + -> given temperature with given pressure in two phase region, try + setting enthalpy instead or provide accurate starting value for + pressure. + + -> given logarithmic temperature differences or kA-values for heat + exchangers, + + -> support better starting values. + + -> bad starting value for fuel mass flow of combustion chamber, provide + small (near to zero, but not zero) starting value. + +or simply not making progress in the convergence + +.. error:: + + .. code-block:: bash + + WARNING:root:The solver does not seem to make any progress, aborting + calculation. Residual value is 7.43e+05. This frequently happens, if + the solver pushes the fluid properties out of their feasible range. + +Fixing the errors +^^^^^^^^^^^^^^^^^ + +To generate good starting values for the simulation, it is recommended to set +pressure and enthalpy values instead of temperature differences. In this +example, fixed points can be identified with the help of the logph diagram +which you can see in the figure below. + +.. figure:: /_static/images/tutorials/heat_pump_starting_values/logph.svg + :align: center + + Figure: Logph diagram of ammonia + +A rough estimation of the evaporation and condensation pressure can be +obtained and will be used to replace the temperature differences at the +evaporator and the condenser for the starting value generator. After +condensation, the working fluid is in saturated liquid state. We can retrieve +the condensation pressure corresponding to a temperature slightly below the +heat sink temperature by using the CoolProp `PropsSI` interface with the +respective inputs. The same step can be carried out on the heat source side. +For the internal heat exchanger, an enthalpy value is specified instead of the +temperature difference to the boiling point as well. It is important to note +that the PropertySI function (PropsSI) is used with SI units, which differ +from the units defined in the network. + +The temperature difference values are unset and pressure and enthalpy values +are set instead. + +.. literalinclude:: /../tutorial/advanced/starting_values.py + :language: python + :start-after: [sec_4] + :end-before: [sec_5] + +The model was solved successfully and has stored the starting values for any +follow-up. Therefore, we can undo our recent changes and restart the +simulation. For example, the COP is then calculated. + +.. literalinclude:: /../tutorial/advanced/starting_values.py + :language: python + :start-after: [sec_5] + :end-before: [sec_6] + +Expand fix to any working fluids +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Finally, using this strategy, it is possible to build a generic function, +building a network, that works with a variety of working fluids. + +.. dropdown:: Click to expand to code section + + .. literalinclude:: /../tutorial/advanced/starting_values.py + :language: python + :start-after: [sec_6] + :end-before: [sec_7] + +We can run that function for different working fluids and plot the results: + +.. literalinclude:: /../tutorial/advanced/starting_values.py + :language: python + :start-after: [sec_7] + :end-before: [sec_8] + +.. figure:: /_static/images/tutorials/heat_pump_starting_values/COP_by_wf.svg + :align: center + :alt: Analysis of the COP using different working fluids + :figclass: only-light + + Figure: Analysis of the COP using different working fluids + +.. figure:: /_static/images/tutorials/heat_pump_starting_values/COP_by_wf_darkmode.svg + :align: center + :alt: Analysis of the COP using different working fluids + :figclass: only-dark + + Figure: Analysis of the COP using different working fluids diff --git a/docs/tutorials_examples.rst b/docs/tutorials_examples.rst deleted file mode 100644 index 3ed461421..000000000 --- a/docs/tutorials_examples.rst +++ /dev/null @@ -1,77 +0,0 @@ -~~~~~~~~~~~~~~~~~~~~~~ -Examples and Tutorials -~~~~~~~~~~~~~~~~~~~~~~ - -.. _tespy_examples_label: - -Examples -======== - -In the example section we provide a variety of TESPy applications, among -others: - -* a very basic model of the clausius rankine process, -* the calculation of backpressure lines of a combined heat and power cycle at - different loads and feed flow temperature levels, -* modeling approach for a district heating system with various consumers and - system infrastructure as well as -* the COP of a heat pump dependent on load, ambient temperature and heat - delivering fluid (air vs. water). - -You can find all examples in the TESPy -`examples repository `__ -on github. Additional small examples can be found in the API-documentation. - -* :py:mod:`Components ` -* :py:mod:`Connections and Busses ` -* :py:mod:`Networks ` -* :py:mod:`Importing Networks ` - -.. contents:: `Examples` - :depth: 1 - :local: - :backlinks: top - -.. _basic_example_label: -.. include:: tutorials_examples/clausius_rankine.rst -.. _combined_cycle_example_label: -.. include:: tutorials_examples/combined_cycle_chp.rst -.. _chp_example_label: -.. include:: tutorials_examples/clausius_rankine_chp.rst -.. _combustion_engine_label: -.. include:: tutorials_examples/combustion_engine.rst -.. _dh_example_label: -.. include:: tutorials_examples/district_heating.rst -.. _heat_pump_cop_label: -.. include:: tutorials_examples/heat_pump.rst -.. _solar_collector_example_label: -.. include:: tutorials_examples/solar_collector.rst -.. _tespy_tutorial_label: - -Tutorials -========= - -We provide two different tutorials for you to better understand how to work -with TESPy. You will learn how to create basic models and get the idea of -designing a plant and simulating the offdesign behavior in the heat pump -tutorial. On top of that, we created a tutorial for the usage of the combustion -chamber: It is an important component for thermal power plants while being a -source for many errors in the calculation. - -The last tutorial is a plant design optimization tutorial. A thermal power -plant with two extraction stages is optimized in regard of thermal efficiency -with respect to the extraction pressure levels. - -.. contents:: `Tutorials` - :depth: 1 - :local: - :backlinks: top - -.. _heat_pump_tutorial_label: -.. include:: tutorials_examples/tutorial_heat_pump.rst -.. _combustion_chamber_tutorial_label: -.. include:: tutorials_examples/tutorial_combustion_chamber.rst -.. _pygmo_tutorial_label: -.. include:: tutorials_examples/tutorial_pygmo_optimization.rst -.. _heat_pump_exergy_tutorial_label: -.. include:: tutorials_examples/tutorial_heat_pump_exergy.rst diff --git a/docs/tutorials_examples/clausius_rankine.rst b/docs/tutorials_examples/clausius_rankine.rst deleted file mode 100644 index 19ff81b9c..000000000 --- a/docs/tutorials_examples/clausius_rankine.rst +++ /dev/null @@ -1,30 +0,0 @@ -Clausius rankine cycle ----------------------- - -This example provides a model for a basic clausius rankine cycle. -The process flow diagram is shown in the image below, the source code can be -found at the TESPy `examples repository -`__. - -.. figure:: /api/_images/basic.svg - :align: center - - Figure: Topology of the basic clausius rankine cycle. - -The basic clausius rankine cycle is built up of a steam turbine, a condenser, -the feed water pump and the steam generator. The ideal process' isentropic -efficiencies of the steam turbine and the pump are at a value of 100 %, and -pressure losses in the condenser and the steam generator are non-existent, -which would result in the thermal efficiency being equal to the Carnot -efficiency. For this example realistic figures have been chosen. -After the plant design an offdesign calculation with 90 % rated power is -performed. The inline-comments give you hints which and why offdesign -parameters have been chosen. - -For a good start you can try to modify or exchange parameters. E.g. adjust the -value of the upper terminal temperature difference at the condenser, or replace -this parameter with a pressure at the turbine's outlet. In order to get more -familiar with how TESPy works you could try to insert more components, maybe -add an extraction of the steam turbine for preheating the feed water. It is -strongly recommended to add new components bit per bit, troubleshooting is much -easier this way. diff --git a/docs/tutorials_examples/clausius_rankine_chp.rst b/docs/tutorials_examples/clausius_rankine_chp.rst deleted file mode 100644 index e7d54a842..000000000 --- a/docs/tutorials_examples/clausius_rankine_chp.rst +++ /dev/null @@ -1,29 +0,0 @@ -CHP with backpressure turbine ------------------------------ - -We have set up a simple combined heat and power unit for this example. A -backpressure steam turbine is operated with steam extraction for preheating -purposes. -You will find the source code `here -`__. - -.. figure:: /api/_images/chp.svg - :align: center - - Figure: Topology of the chp unit. - -At first, a plant design is chosen: The unit provides a total power of 5 MW and -heating at a temperature of 110 °C for the feed flow. -After that, the temperature at feed flow and live steam mass flow are altered -(70 °C to 120 °C and 60 % to 105 % in respect to design mass flow) to cover the -unit's range of operation. Thus, the calculation mode is switched to offdesign -and the temperature and mass flow are altered in two embedded loops. -The latest calculated case of the same mass flow is selected for initialisation -in order to achieve better and faster convergence. -The results are saved to .csv-files and the following plot of backpressure -lines will be created. - -.. figure:: /api/_images/chp_PQ.svg - :align: center - - Figure: Backpressure lines of a CHP unit. diff --git a/docs/tutorials_examples/combined_cycle_chp.rst b/docs/tutorials_examples/combined_cycle_chp.rst deleted file mode 100644 index ca6c80a33..000000000 --- a/docs/tutorials_examples/combined_cycle_chp.rst +++ /dev/null @@ -1,16 +0,0 @@ -Combined cycle with backpressure turbine ----------------------------------------- - -Another example for chp units, this one is a combined cycle power plant using a -backpressure steam turbine. Additionally to the heat extraction at the steam -turbine condenser, the district heating water extracts energy from the waste -heat of the waste heat steam generator. You will find the source code -`here `__. - -.. figure:: /api/_images/cc_bp.svg - :align: center - - Figure: Topology of the chp unit. - -The example file handles the plant's design as well as the offdesign -performance. diff --git a/docs/tutorials_examples/combustion_engine.rst b/docs/tutorials_examples/combustion_engine.rst deleted file mode 100644 index 2b27d62a3..000000000 --- a/docs/tutorials_examples/combustion_engine.rst +++ /dev/null @@ -1,47 +0,0 @@ -Combustion engine ------------------ - -We have added a combustion engine in version 0.0.5 of TESPy. The combustion -engine is based on the combustion chamber, and additionally provides a power -as well as two heating outlets and heat losses can be taken into account, too. -Power output, heat production and heat losses are all linked to the thermal -input of the combustion engine by characteristic lines, which usually are -provided by the manufacturer. TESPy provides a set of predefined -characteristics (documented in the :py:class:`` module). - -.. figure:: /api/_images/CombustionEngine.svg - :align: center - - Figure: Topology of the combustion engine. - -The characteristics take the power ratio (:math:`\frac{P}{P_{ref}}`) as -argument. For a design case simulation the power ratio is always assumed to be -equal to 1. For offdesign calculation TESPy will automatically take the rated -power from the design case and use it to determine the power ratio. Still it is -possible to specify the rated power manually, if you like. - -In contrast to other components, the combustion engine has several busses, -which are accessible by specifying the corresponding bus parameter: - -- TI (thermal input), -- Q (total heat output), -- Q1 and Q2 (heat output 1 and 2), -- QLOSS (heat losses) and -- P (power output). - -If you want to add a bus to the example from the TESPy examples repository, -your code could look like this: - -.. code-block:: python - - chp = CombustionEngine('chp') - - b = Bus('some label') - # for thermal input - b.add_comps({'comp': chp, 'param': 'TI'}) - # for power output - b.add_comps({'comp': chp, 'param': 'P'}) - -Enjoy fiddling around with the source code of the -`combustion engine `_ -in the examples repository! diff --git a/docs/tutorials_examples/heat_pump.rst b/docs/tutorials_examples/heat_pump.rst deleted file mode 100644 index bafe2f462..000000000 --- a/docs/tutorials_examples/heat_pump.rst +++ /dev/null @@ -1,43 +0,0 @@ -COP of a heat pump ------------------- - -This example is based on the :ref:`heat pump tutorial -` and shows how to calculate the COP of a heat pump -at different ambient temperatures and different loads of the plant. -The idea is very similar to the :ref:`CHP example `, thus -you should have a look at the tutorial and the CHP example first. -Be aware, that there are slight changes regarding the topology of the system -from the tutorial to this example. -You will find the source code `in this repository -`_. - -.. figure:: /api/_images/heat_pump_example.svg - :align: center - - Figure: Topology of the heat pump unit. - -After the plant has been designed, the consumer's heat demand and the ambient -temperature are modified within defined ranges. -Generally, if you are performing offdesign calculation, keep in mind, that a -good initial guess/solution is the key to good convergence progress. This is -why, we initialise the calculation at a higher ambient temperature with the -results from the calculation of the same load and the nearest ambient -temperature possible (in this case always the calculation one step before). -This helps the algorithm to stabilize and find a solution. -If you skip out on a large range of temperature or power, you might run into -convergence issues. The figures below show the COP of the heat pump for two -different heat sources at different temperature levels and at different loads: -In the first figure water is used as heat source, in the second one air. -Obviously, the heat pump using air performs much worse. This is mainly to the -high power consumption of the fan, as for the same amount of heat to be -transferred, a much higher volume has to be moved. - -.. figure:: /api/_images/heat_pump_COP_water.svg - :align: center - - Figure: COP of the heat pump using water as heat source. - -.. figure:: /api/_images/heat_pump_COP_air.svg - :align: center - - Figure: COP of the heat pump using air as heat source. diff --git a/docs/tutorials_examples/solar_collector.rst b/docs/tutorials_examples/solar_collector.rst deleted file mode 100644 index dd9b873e5..000000000 --- a/docs/tutorials_examples/solar_collector.rst +++ /dev/null @@ -1,44 +0,0 @@ -Solar collector ---------------- - -This example shows how you can use a solarthermal collector in TESPy. -The process flow diagram is shown in the image below, the source code can be -found at the TESPy `examples repository -`__. - -.. figure:: /api/_images/SolarCollector.svg - :align: center - - Figure: Topology of the solar collector. - -The solarthermal collector is used to transfer heat from the solar radiation to -the collector fluid. The TESPy component -:py:class:`tespy.components.heat_exchangers.solar_collector.SolarCollector` -inherits from the -:py:class:`tespy.components.heat_exchangers.simple.HeatExchangerSimple` -component. An energy balance is applied according to the -:py:meth:`tespy.components.heat_exchangers.solar_collector.SolarCollector.energy_group_func` -method, which takes the collector's - -- surface area :code:`A`, -- loss key figures :code:`lkf_lin` (linear) and :code:`lkf_quad` (quadratic), -- ambient temperature :code:`Tamb`, -- optical efficiency :code:`eta_opt` as well as -- incoming radiation :code:`E` (W/m^2) - -into account. - -In the script different ways of parametrisation are shown. In the last part a -collector is designed and the offdesign performance at different rates of -absorption and ambient temperatures is calculated subsequently. Assuming a -constant mass flow through the collector, the outlet temperature and the -pressure losses of the collector are calculated. - -For example, if you want to calculate the performance of the collector within -a specific period of time, you could have the absorbed energy and the ambient -temperature as input time series and iterate over said series. As the absorbed -energy of the collector is a function of the global radiation on the inclined -surface, datetime and location only (optical losses are not temperature -dependent), you could calculate the absorption in a preprocessing script. If -you are to create such a script, we would appreciate you sharing and adding it -to TESPy! diff --git a/docs/tutorials_examples/tutorial_combustion_chamber.rst b/docs/tutorials_examples/tutorial_combustion_chamber.rst deleted file mode 100644 index 42638de22..000000000 --- a/docs/tutorials_examples/tutorial_combustion_chamber.rst +++ /dev/null @@ -1,257 +0,0 @@ -Combustion Chamber Tutorial ---------------------------- - -.. contents:: - :depth: 1 - :local: - :backlinks: top - -There are two different types of combustion chambers available: - -- :py:class:`tespy.components.combustion.base.CombustionChamber` and -- :py:class:`tespy.components.combustion.diabatic.DiabaticCombustionChamber`. - -Both can handle varying fluid compositions for the air and the fuel and -calculates the fluid composition of the flue gas. Thus, it is possible to e.g. -specify the oxygen mass fraction in the flue gas in a calculation. The -difference between the components lies in the fact, that the -:code:`CombustionChamber` does **not consider heat or pressure losses**, while -:code:`DiabaticCombustionChamber` does so. We provide a tutorial for both -components, where you learn how they work, and what the differences are. - -CombustionChamber -^^^^^^^^^^^^^^^^^ - -The combustion chamber is an important component within thermal power plants, -but unfortunately is the reason for many issues, as the solving algorithm is -very sensitive to small changes e.g. the fluid composition. We will -demonstrate how to handle the combustion chamber in a very small, simple -example. You can download the full code from the TESPy -`examples repository `__. - -First of all you need to define the network containing all fluid components -used for the combustion chamber. **These are at least the fuel, oxygen, -carbon-dioxide and water**. For this example we added Argon, and of course - as -we are using Air for the combustion - Nitrogen. - -.. code-block:: python - - from tespy.networks import Network - - # define full fluid list for the network's variable space - fluid_list = ['Ar', 'N2', 'O2', 'CO2', 'CH4', 'H2O'] - - # define unit systems - nw = Network(fluids=fluid_list, p_unit='bar', T_unit='C') - -As components there are two sources required, one for the fresh air, one for -the fuel, a sink for the flue gas and the combustion chamber. Connect the -components and add the connections to your network afterwards. - -.. code-block:: python - - from tespy.components import Sink, Source, CombustionChamber - - # sinks & sources - amb = Source('ambient') - sf = Source('fuel') - fg = Sink('flue gas outlet') - - # combustion chamber - comb = CombustionChamber(label='combustion chamber') - -.. code-block:: python - - from tespy.connections import Connection - - amb_comb = Connection(amb, 'out1', comb, 'in1') - sf_comb = Connection(sf, 'out1', comb, 'in2') - comb_fg = Connection(comb, 'out1', fg, 'in1') - - nw.add_conns(sf_comb, amb_comb, comb_fg) - -For the parametrisation we specify the combustion chamber's air to -stoichiometric air ratio lamb and the thermal input -(:math:`LHV \cdot \dot{m}_{f}`). - -.. code-block:: python - - # set combustion chamber air to stoichiometric air ratio and thermal input - comb.set_attr(lamb=3, ti=2e6) - -The ambient conditions as well as the fuel gas inlet temperature are defined in -the next step. The air and the fuel gas composition must fully be stated, the -component combustion chamber can not handle "Air" as input fluid! - -.. code-block:: python - - # air from ambient (ambient pressure and temperature), air composition must - # be stated component wise. - amb_comb.set_attr(p=1, T=20, fluid={'Ar': 0.0129, 'N2': 0.7553, 'H2O': 0, - 'CH4': 0, 'CO2': 0.0004, 'O2': 0.2314}) - - # fuel, pressure must not be stated, as pressure is the same at all inlets - # and outlets of the combustion chamber - sf_comb.set_attr(T=25, fluid={'CO2': 0.04, 'Ar': 0, 'N2': 0, 'O2': 0, - 'H2O': 0, 'CH4': 0.96}) - -Finally run the code: - -.. code-block:: python - - nw.solve('design') - nw.print_results() - -Of course, you can change the parametrisation in any desired way. For example -instead of stating the thermal input, you could choose any of the mass flows, -or instead of the air to stoichiometric air ratio you could specify the flue -gas temperature. It is also possible to make modifications on the fluid -composition, for example stating the oxygen content in the flue gas or to -change the fuel composition. Make sure, all desired fuels of your fuel mixture -are also within the fluid_list of the network. For the example below we added -hydrogen to the fuel mixture. - -.. code-block:: python - - from tespy.networks import Network - from tespy.components import Sink, Source, CombustionChamber - from tespy.connections import Connection - - # %% network - - fluid_list = ['Ar', 'N2', 'O2', 'CO2', 'CH4', 'H2O', 'H2'] - nw = Network(fluids=fluid_list, p_unit='bar', T_unit='C') - - # %% components - - # sinks & sources - amb = Source('ambient') - sf = Source('fuel') - fg = Sink('flue gas outlet') - - # combustion chamber - comb = CombustionChamber(label='combustion chamber') - - # %% connections - - amb_comb = Connection(amb, 'out1', comb, 'in1') - sf_comb = Connection(sf, 'out1', comb, 'in2') - comb_fg = Connection(comb, 'out1', fg, 'in1') - - nw.add_conns(sf_comb, amb_comb, comb_fg) - - # %% component parameters - - # set combustion chamber air to stoichometric air ratio and thermal input - comb.set_attr(lamb=3, ti=2e6) - - # %% connection parameters - - amb_comb.set_attr(p=1, T=20, fluid={'Ar': 0.0129, 'N2': 0.7553, 'H2O': 0, - 'CH4': 0, 'CO2': 0.0004, 'O2': 0.2314, - 'H2': 0}) - - sf_comb.set_attr(T=25, fluid={'CO2': 0, 'Ar': 0, 'N2': 0,'O2': 0, 'H2O': 0, - 'CH4': 0.95, 'H2': 0.05}) - - # %% solving - - nw.solve('design') - nw.print_results() - -DiabaticCombustionChamber -^^^^^^^^^^^^^^^^^^^^^^^^^ - -The example for the diabatic combustion chamber can as well be taken from the -TESPy -`examples repository `__. - -The setup of the network, connections and components is identical to the -first setup, therefore we skip over that part in this section. Note, that -instead of :code:`CombustionChamber` we are importing the component -:code:`DiabaticCombustionChamber`. Since heat losses and pressure losses are -considered in this component, we have to make additional assumptions to -simulate it. First, we will make run the simulation with inputs in a way, that -the outcome is identical to the behavior of the adiabatic version without -pressure losses as described above. - -As in the example above, we also specify thermal input and lambda, as well as -identical parameters for the connections. Furthermore, we specify the efficiency -:code:`eta` of the component, which determines the heat loss as ratio of the -thermal input. :code:`eta=1` means, no heat losses, thus adiabatic behavior. -On top of that, we set the pressure ratio :code:`pr`, which describes the -ratio of the pressure at the outlet to the pressure at **the inlet 1**. The -pressure value at the inlet 2 is detached from the other pressure values, it -must be a result of a different parameter specification. In this example, we -set it directly. To match the inputs of the first tutorial, we set -:code:`pr=1` and :code:`p=1` for connection :code:`sf_comb`. - -.. note:: - - A warning message is promted at the end of the simulation, if the pressure - of the inlet 2 is lower or equal to the pressure of inlet 1. - -.. code-block:: python - - from tespy.networks import Network - from tespy.components import Sink, Source, DiabaticCombustionChamber - from tespy.connections import Connection - - # %% network - - fluid_list = ['Ar', 'N2', 'O2', 'CO2', 'CH4', 'H2O', 'H2'] - nw = Network(fluids=fluid_list, p_unit='bar', T_unit='C') - - # %% components - - # sinks & sources - amb = Source('ambient') - sf = Source('fuel') - fg = Sink('flue gas outlet') - - # combustion chamber - comb = DiabaticCombustionChamber(label='combustion chamber') - - # %% connections - - amb_comb = Connection(amb, 'out1', comb, 'in1') - sf_comb = Connection(sf, 'out1', comb, 'in2') - comb_fg = Connection(comb, 'out1', fg, 'in1') - - nw.add_conns(sf_comb, amb_comb, comb_fg) - - # set combustion chamber air to stoichometric air ratio, thermal input - # and efficiency - comb.set_attr(lamb=3, ti=2e6, eta=1, pr=1) - - # %% connection parameters - - amb_comb.set_attr(p=1, T=20, fluid={'Ar': 0.0129, 'N2': 0.7553, 'H2O': 0, - 'CH4': 0, 'CO2': 0.0004, 'O2': 0.2314, - 'H2': 0}) - - sf_comb.set_attr(p=1, T=25, fluid={'CO2': 0, 'Ar': 0, 'N2': 0,'O2': 0, - 'H2O': 0, 'CH4': 0.95, 'H2': 0.05}) - - # %% solving - - nw.solve('design') - nw.print_results() - -Now, consider heat loss of the surface of the component. This is simply done by -specifying the value for :code:`eta`. We assume 4 % of thermal input as heat -loss and set that value accordingly. Furthermore, the pressure of the fuel is -set to 1.5 bar. The air inlet pressure will be the result of the specified -pressure ratio and the outlet pressure assuming 2 % pressure losses. All -other parameters stay untouched. - -.. code-block:: python - - comb.set_attr(eta=0.96, pr=0.98) - - amb_comb.set_attr(p=None) - sf_comb.set_attr(p=1.5) - comb_fg.set_attr(p=1.0) - - nw.solve('design') - nw.print_results() diff --git a/docs/tutorials_examples/tutorial_heat_pump.rst b/docs/tutorials_examples/tutorial_heat_pump.rst deleted file mode 100644 index e91f2da45..000000000 --- a/docs/tutorials_examples/tutorial_heat_pump.rst +++ /dev/null @@ -1,513 +0,0 @@ -Heat pump tutorial ------------------- - -.. contents:: - :depth: 1 - :local: - :backlinks: top - -Task -^^^^ - -This tutorial introduces you in how to model a heat pump in TESPy. You can see -the plants topology in the figure. Also, you will find a fully working model in -the last chapter of this tutorial. - -.. figure:: /api/_images/tutorial_heat_pump.svg - :align: center - - Figure: Topology of the heat pump. - -The main purpose of the heat pump is to deliver heat e.g. for the consumers of -a heating system. Thus, the heat pump's parameters will be set in a way, which -supports this target. -Generally, if systems are getting more complex, it is highly recommended to set -up your plant in incremental steps. This tutorial divides the plant in three -sections: The consumer part, the valve and the evaporator and the compressor as -last element. Each new section will be appended to the existing ones. - - -Set up a Network -^^^^^^^^^^^^^^^^ - -In order to simulate our heat pump we have to create an instance of the -:py:class:`tespy.networks.network.Network` class. The network is the main -container of the model and will be required in all following sections. First, -it is necessary to specify a list of the fluids used in the plant. In this -example we will work with water (H\ :sub:`2`\O) and ammonia (NH\ :sub:`3`\). -Water is used for the cold side of the heat exchanger, for the consumer and for -the hot side of the environmental temperature. Ammonia is used as coolant -within the heat pump circuit. If you don’t specify the unit system, the -variables are set to SI-Units. - -.. code-block:: python - - from tespy.networks import Network - - nw = Network(fluids=['water', 'NH3'], - T_unit='C', p_unit='bar', h_unit='kJ / kg', m_unit='kg / s') - -We will use °C, bar and kJ/kg as units for temperature and enthalpy. - -Modeling the heat pump: Consumer system -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Components -++++++++++ - -We will start with the consumer as the plant will be designed to deliver a -specific heat flow. From figure 1 you can determine the components of the -consumer system: condenser, pump and the consumer ( -:py:class:`tespy.components.heat_exchangers.simple.HeatExchangerSimple` -). Additionally we need a source and a sink for the consumer and the heat pump -circuit respectively. We will import all necessary components already in the -first step, so the imports will not need further adjustment. - -We label the sink for the coolant "valve", as for our next calculation the -valve (labeled "valve") will be attached there. In this way, the fluid -properties can be initialized by .csv at the interface-connection, too. - -.. code-block:: python - - from tespy.components import ( - Source, Sink, CycleCloser, Valve, Drum, Pump, Compressor, - Condenser, HeatExchangerSimple, HeatExchanger) - - # sources & sinks - - c_in = Source('coolant in') - cons_closer = CycleCloser('consumer cycle closer') - - va = Sink('valve') - - # consumer system - - cd = Condenser('condenser') - rp = Pump('recirculation pump') - cons = HeatExchangerSimple('consumer') - -Connections -+++++++++++ - -In the next steps we will connect the components in order to form a network. -Every connection requires the source, the source id, the target and the target -id as arguments: the source is the component from which the connection -originates, the source id is the outlet id of that component. This applies -analogously to the target. To find all inlet and outlet ids of a component look -up the class documentation of the respective component. An overview of the -components available and the class documentations is provided in the -:ref:`TESPy modules overview `. The -:py:class:`tespy.connections.connection.Ref` class is used specify fluid -property values by referencing fluid properties of different connections. It is -used in a later step. - -.. code-block:: python - - from tespy.connections import Connection, Ref - - # consumer system - - c_in_cd = Connection(c_in, 'out1', cd, 'in1') - - close_rp = Connection(cons_closer, 'out1', rp, 'in1') - rp_cd = Connection(rp, 'out1', cd, 'in2') - cd_cons = Connection(cd, 'out2', cons, 'in1') - cons_close = Connection(cons, 'out1', cons_closer, 'in1') - - nw.add_conns(c_in_cd, close_rp, rp_cd, cd_cons, cons_close) - - # connection condenser - evaporator system - - cd_va = Connection(cd, 'out1', va, 'in1') - - nw.add_conns(cd_va) - -.. note:: - - Instead of just connecting the consumers outlet to the pumps inlet, we must - make use of an auxiliary component: Closing a cycle without further - adjustments will always result in a linear dependency in the fluid and the - mass flow equations. We therefore need implement a CycleCloser. The - :py:class:`tespy.components.basics.cycle_closer.CycleCloser` component makes - sure, the fluid properties pressure and enthalpy are identical at the inlet - and the outlet. The component will prompt a warning, if the mass flow or - the fluid composition at its outlet are different to those at its inlet. A - different solution to this problem, is adding a merge and a splitter at - some point of your network and connect the second inlet/outlet to a - source/sink. This causes residual mass flow and residual fluids to - emerge/drain there. - -Parametrization -+++++++++++++++ - -For the condenser we set pressure ratios on hot and cold side and additionally -we set a value for the upper terminal temperature difference as design -parameter and the heat transfer coefficient as offdesign parameter. The -consumer will have pressure losses, too. Further we set the isentropic -efficiency for the pump, the offdesign efficiency is calculated with a -characteristic function. Thus, we set the efficiency as design parameter and -the characteristic function as offdesign parameter. In offdesign calculation -the consumer's pressure ratio will be a function of the mass flow, thus as -offdesign parameter we select zeta. The most important parameter is the -consumers heat demand. We marked this setting as "key parameter". - -.. code-block:: python - - cd.set_attr(pr1=1, pr2=0.99, ttd_u=5, design=['pr2', 'ttd_u'], - offdesign=['zeta2', 'kA_char']) - rp.set_attr(eta_s=0.8, design=['eta_s'], offdesign=['eta_s_char']) - cons.set_attr(pr=0.99, design=['pr'], offdesign=['zeta']) - -In order to calculate this network further parametrization is necessary, as -e.g. the fluids are not determined yet: At the hot inlet of the condenser we -define the temperature and the fluid vector. In order to fully determine the -fluid's state at this point, an information on the pressure is required. This -is achieved by setting the terminal temperature difference (see above). The -same needs to be done for the consumer cycle. We suggest to set the parameters -at the pump's inlet. On top, we assume that the consumer requires a constant -inlet temperature. The CycleCloser automatically makes sure, that the fluid's -state at the consumer's outlet is the same as at the pump's inlet. - -.. code-block:: python - - c_in_cd.set_attr(T=170, fluid={'water': 0, 'NH3': 1}) - close_rp.set_attr(T=60, p=10, fluid={'water': 1, 'NH3': 0}) - cd_cons.set_attr(T=90) - -.. code-block:: python - - # %% key parameter - - cons.set_attr(Q=-230e3) - -.. note:: - - In TESPy there are two different types of calculations: design point and - offdesign calculation. All parameters specified in the design attribute of - a component or connection, will be unset in a offdesign calculation, all - parameters specified in the offdesign attribute of a component or - connection will be set for the offdesign calculation. The value for these - parameters is the value derived from the design-calculation. - - Generally, the design calculation is used for designing your system in the - way you want it to look like. This means, that you might want to specify a - design point isentropic efficiency, pressure loss or terminal temperature - difference. After you have designed your system, you are able to make - offdesign calculations with TESPy. The offdesign calculation is used to - predict the system's behavior at different points of operation. For this - case, this might be different ambient temperature, different feed flow - temperature, or partial load. - -Solve -+++++ - -After creating the system, we want to solve our network. First, we calculate -the design case and directly after we can perform the offdesign calculation at -a different value for our key parameter. For general information on the solving -process in TESPy and available parameters check the corresponding section in -the :ref:`TESPy modules introduction `. - -.. code-block:: python - - nw.solve('design') - nw.print_results() - nw.save('condenser') - - cons.set_attr(Q=-200e3) - - nw.solve('offdesign', design_path='condenser') - nw.print_results() - - -Valve and evaporator system -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Next we will add the valve and the evaporator system to our existing network. - -Components -++++++++++ - -This part contains of a valve followed by a drum with evaporator in forced flow -and a superheater. Do not forget to change the old sink labeled "valve" to an -actual valve and the sink used in the previous calculation will represent the -first compressor, labeled "compressor 1". Add the following components to the -script. - -.. code-block:: python - - # sources & sinks - - amb_in = Source('source ambient') - amb_out = Sink('sink ambient') - - cp1 = Sink('compressor 1') - - # evaporator system - - va = Valve('valve') - dr = Drum('drum') - ev = HeatExchanger('evaporator') - su = HeatExchanger('superheater') - pu = Pump('pump evaporator') - -Connections -+++++++++++ - -As we already redefined our variable "va" to be a valve instead of a sink (see -above), we do not need any adjustments to the connection between the condenser -and the former sink "cd_va". The valve connects to the drum at the inlet 'in1'. -The pump of the forced flow evaporation system connects to the drum's outlet -'out1', the evaporator's cold side connects to the drum's inlet 'in2' and the -superheater's cold side connects to the drum's outlet 'out2'. This will add the -following connections to the model: - -.. code-block:: python - - # evaporator system - - va_dr = Connection(va, 'out1', dr, 'in1') - dr_pu = Connection(dr, 'out1', pu, 'in1') - pu_ev = Connection(pu, 'out1', ev, 'in2') - ev_dr = Connection(ev, 'out2', dr, 'in2') - dr_su = Connection(dr, 'out2', su, 'in2') - - nw.add_conns(va_dr, dr_pu, pu_ev, ev_dr, dr_su) - - amb_in_su = Connection(amb_in, 'out1', su, 'in1') - su_ev = Connection(su, 'out1', ev, 'in1') - ev_amb_out = Connection(ev, 'out1', amb_out, 'in1') - - nw.add_conns(amb_in_su, su_ev, ev_amb_out) - - # connection evaporator system - compressor system - - su_cp1 = Connection(su, 'out2', cp1, 'in1') - - nw.add_conns(su_cp1) - -Parametrization -+++++++++++++++ - -Previous parametrization stays untouched. Regarding the evaporator, we specify -pressure ratios on hot and cold side as well as the lower terminal temperature -difference. We use the hot side pressure ratio and the lower terminal -temperature (similar to pinch point layout for waste heat steam generators) -difference as design parameters and choose zeta as well as the area independent -heat transfer coefficient as its offdesign parameters. - -On top of that, the characteristic function of the evaporator should follow the -default characteristic line of 'EVAPORATING FLUID' on the cold side and the -default line 'DEFAULT' on the hot side. These lines are defined in the -:py:mod:`tespy.data` module. If you want to learn more about handling -characteristic functions you should have a glance at the -:ref:`TESPy components section `. The superheater -will also use the pressure ratios on hot and cold side. Further we set a value -for the upper terminal temperature difference. For the pump we set the -isentropic efficiency. For offdesign and design parameter specification of -these components the same logic as for the evaporator and the already existing -part of the network is applied. The system designer has to answer the question: -Which parameters are design point parameters and how does the component perform -at a different operation point. - -.. code-block:: python - - from tespy.tools.characteristics import CharLine - from tespy.tools.characteristics import load_default_char as ldc - # evaporator system - - kA_char1 = ldc('heat exchanger', 'kA_char1', 'DEFAULT', CharLine) - kA_char2 = ldc('heat exchanger', 'kA_char2', 'EVAPORATING FLUID', CharLine) - - ev.set_attr(pr1=0.99, pr2=0.99, ttd_l=5, - kA_char1=kA_char1, kA_char2=kA_char2, - design=['pr1', 'ttd_l'], offdesign=['zeta1', 'kA_char']) - su.set_attr(pr1=0.99, pr2=0.99, ttd_u=2, design=['pr1', 'pr2', 'ttd_u'], - offdesign=['zeta1', 'zeta2', 'kA_char']) - pu.set_attr(eta_s=0.8, design=['eta_s'], offdesign=['eta_s_char']) - -Next step is the connection parametrization: The pressure in the drum and the -enthalpy of the wet steam reentering the drum need to be determined. For the -enthalpy we can specify a reference of the circulating mass flow to the main -cycle mass flow. The pressure is achieved through the given lower terminal -temperature difference of the evaporator and its hot side outlet temperature. -As we have specified a terminal temperature difference at the evaporator's cold -side inlet (:code:`ttd_l`), it might be necessary to state a starting value for -the pressure or the state of the fluid (gaseous), as we are near to the -wo-phase region. On the hot side inlet of the superheater we define the -temperature, pressure and the fluid. Since the pressure between superheater and -first compressor will be a result of the pressure losses in the superheater and -we set the terminal temperature difference there, bad starting values will lead -to a linear dependency, as a temperature and a pressure are set while the -fluid's state could be within the two phase region. Thus, we choose to specify -:code:`state='g'`, so the solver will keep the fluid in gaseous state at all -times. At last we have to fully determine the state of the incoming fluid at -the superheater's hot side. - -.. note:: - - Do only use the :code:`state` keyword if you know the fluid's state prior - to the simulation. If you specify the fluid to be gaseous but the correct - result of the simulation would be within the two-phase region, your - calculation most likely will not converge. - -.. code-block:: python - - # evaporator system cold side - - pu_ev.set_attr(m=Ref(va_dr, 0.75, 0)) - su_cp1.set_attr(state='g') - - # evaporator system hot side - - amb_in_su.set_attr(T=12, p=1, fluid={'water': 1, 'NH3': 0}) - ev_amb_out.set_attr(T=9) - -Solve -+++++ - -Again, you should calculate your network after you added these parts. As we -have already calculated one part of our network, this time we can use the -:code:`init_path` for the design calculation and load the results from the -previous network. This step is not required, but in larger, more complex -networks, it might help, to achieve better convergence. - - -Compressor system -^^^^^^^^^^^^^^^^^ - -To complete the heat pump, we will add the compressor system to our existing -network. - -Components -++++++++++ - -This part contains two compressors with an intercooler between them. The cold -side of the intercooler requires a source and a sink. Again, remember -redefining the former sink :code:`"cp1"` to a compressor. We will now replace -the source for the coolant :code:`c_in` at the condenser with another cycle -closer (:code:`cool_closer`), to make sure the fluid properties after the -second compressor are identical to the fluid properties at the condenser inlet. - -.. note:: - - The intercooling leads to a lower COP but may be necessary depending on - your temperature level requirement on the consumer's side. In a single - stage compression, the outlet temperature of the coolant might violated - technical boundary conditions of the real-world component. - -.. code-block:: python - - # sources & sinks - - ic_in = Source('source intercool') - ic_out = Sink('sink intercool') - - cool_closer = CycleCloser('coolant cycle closer') - - # compressor-system - - cp1 = Compressor('compressor 1') - cp2 = Compressor('compressor 2') - he = HeatExchanger('intercooler') - -Connections -+++++++++++ - -Consequently to the addition of the cycle closer we have to adjust the -connection definition touching the new cycle closer. Replace - -.. code-block:: python - - c_in_cd = Connection(c_in, 'out1', cd, 'in1') - -with - -.. code-block:: python - - c_in_cd = Connection(cool_closer, 'out1', cd, 'in1') - -Of course, do not forget to add the new connections to the script. - -.. code-block:: python - - # compressor-system - - cp1_he = Connection(cp1, 'out1', he, 'in1') - he_cp2 = Connection(he, 'out1', cp2, 'in1') - cp2_close = Connection(cp2, 'out1', cool_closer, 'in1') - - ic_in_he = Connection(ic_in, 'out1', he, 'in2') - he_ic_out = Connection(he, 'out2', ic_out, 'in1') - - nw.add_conns(cp1_he, he_cp2, ic_in_he, he_ic_out, cp2_close) - -Parametrization -+++++++++++++++ - -For the two compressor we defined an isentropic efficiency and for the -offdesign calculation a generic characteristic line for the isentropic -efficiency will be applied. The first compressor has a fixed pressure ratio, -the seconds compressor pressure ratio will result from the required pressure -at the condenser. The heat exchanger comes with pressure ratios on both sides. -The parametrization of all other components remains identical. - -.. code-block:: python - - cp1.set_attr(eta_s=0.8, design=['eta_s'], offdesign=['eta_s_char']) - cp2.set_attr(eta_s=0.8, pr=5, design=['eta_s'], offdesign=['eta_s_char']) - he.set_attr(pr1=0.99, pr2=0.98, design=['pr1', 'pr2'], - offdesign=['zeta1', 'zeta2', 'kA_char']) - -Regarding the connections, on the hot side after the intercooler we set the -temperature. For the cold side of the heat exchanger we set the temperature, -the pressure and the fluid on the inlet flow, at the outlet we specify the -temperature as a design parameter. In offdesign calculation, this will be a -result from the given heat transfer coefficient (see parametrisation of -intercooler, kA_char is an offdesign parameter). Last, make sure the fluid -properties after the compressor outlet are identical to those at the condenser -inlet using the references. - -The last step leads to a necessary redefinition of the parametrization of the -existing model: As the enthalpy at the outlet of the second compressor is a -result of the given pressure ratio and the isentropic efficiency, it is not -allowed to set the temperature at the condenser's hot inlet anymore. - -.. code-block:: python - - # condenser system - - c_in_cd.set_attr(fluid={'water': 0, 'NH3': 1}) - - # compressor-system - - he_cp2.set_attr(T=40, p0=10) - ic_in_he.set_attr(p=5, T=20, fluid={'water': 1, 'NH3': 0}) - he_ic_out.set_attr(T=30, design=['T']) - -Solve -+++++ - -Here again, using the saved results from previous calculations is always -favorable, but with manually adjusted starting values and the :code:`state` -specifier, the calculation should still converge. If you want to use the -previous part to initialise start the solver with - -.. code-block:: python - - nw.solve('design', init_path='condenser') - - -Further tasks -^^^^^^^^^^^^^ - -After successfully modeling the heat pump in design and offdesign cases, you -can now start using your model for further calculations. For example, if you -have a time series of required heat flow of your consumer, you can loop over -the series and perform offdesign calculation adjusting the heat flow every -time. Of course, this is possible with every offdesign parameter. We provide -the scripts after each of the three steps of the tutorial: -:download:`Step 1 `, -:download:`Step 2 `, -:download:`Step 3 `. - -Have fun working with TESPy! diff --git a/docs/tutorials_examples/tutorial_pygmo_optimization.rst b/docs/tutorials_examples/tutorial_pygmo_optimization.rst deleted file mode 100644 index ba94a2f08..000000000 --- a/docs/tutorials_examples/tutorial_pygmo_optimization.rst +++ /dev/null @@ -1,392 +0,0 @@ -Thermal Power Plant Efficiency Optimization -------------------------------------------- - -.. contents:: - :depth: 1 - :local: - :backlinks: top - -Task -^^^^ - -Designing a power plant meets multiple different tasks, such as finding the -optimal fresh steam temperature and pressure to reduce exhaust steam water -content, or the optimization of extraction pressures to maximize cycle -efficiency and many more. - -In case of a rather simple power plant topologies the task of finding optimized -values for e.g. extraction pressures is still manageable without any -optimization tool. As the topology becomes more complex and boundary -conditions come into play the usage of additional tools is recommended. The -following tutorial is intended to show the usage of PyGMO in combination with -TESPy to **maximize the cycle efficiency of a power plant with two** -**extractions.** - -The source code can be found at the TESPy -`examples repository `__. - -.. figure:: /api/_images/power_plant_two_extractions.svg - :align: center - - Figure: Topology of the power plant. - -What is PyGMO? -^^^^^^^^^^^^^^ - -PyGMO (Python Parallel Global Multiobjective Optimizer, :cite:`Biscani2020`) is -a library that provides a large number of evolutionary optimization algorithms. -PyGMO can be used to solve constrained, unconstrained, single objective and -multi objective problems. - -Evolutionary Algorithms -+++++++++++++++++++++++ - -Evolutionary Algorithms (EA) are optimization algorithms inspired by biological -evolution. In a given population the algorithm uses the so called fitness -function to determine the quality of the solutions to each individual (set of -decision variables) problem. The best possible solution of the population is -called champion. Via mutation, recombination and selection your population -evolves to find better solutions. - -EA will never find an exact solution to your problem. They can only give an -approximation for the real optimum. - -Install PyGMO -+++++++++++++ - - -Conda -##### - -With the `conda `_ package manager PyGMO is -available for Linux, OSX and Windows thanks to the infrastructure of -`conda-forge `_: - -.. code-block:: bash - - conda install -c conda-forge pygmo - -pip -### - -On Linux you also have the option to use the -`pip `_ package installer: - -.. code-block:: bash - - pip install pygmo - -Windows user can perform an installation from source as an alternative to conda. -For further information on this process we recommend the `PyGMO installation -`_ accordingly. - -Creating your TESPy-Model -^^^^^^^^^^^^^^^^^^^^^^^^^ - -It is necessary to use object oriented programming in PyGMO. Therefore we create -a class :code:`PowerPlant` which contains our TESPy-Model and a function to -return the cycle efficiency. - -.. code-block:: python - - from tespy.networks import Network - from tespy.components import ( - Turbine, Splitter, Merge, Condenser, Pump, Sink, Source, - HeatExchangerSimple, Desuperheater, CycleCloser - ) - from tespy.connections import Connection, Bus - from tespy.tools import logger - import logging - - import numpy as np - - - logger.define_logging(screen_level=logging.ERROR) - - - class PowerPlant(): - - def __init__(self): - self.nw = Network( - fluids=['BICUBIC::water'], - p_unit='bar', T_unit='C', h_unit='kJ / kg', - iterinfo=False) - # components - # main cycle - eco = HeatExchangerSimple('economizer') - eva = HeatExchangerSimple('evaporator') - sup = HeatExchangerSimple('superheater') - cc = CycleCloser('cycle closer') - hpt = Turbine('high pressure turbine') - sp1 = Splitter('splitter 1', num_out=2) - mpt = Turbine('mid pressure turbine') - sp2 = Splitter('splitter 2', num_out=2) - lpt = Turbine('low pressure turbine') - con = Condenser('condenser') - pu1 = Pump('feed water pump') - fwh1 = Condenser('feed water preheater 1') - fwh2 = Condenser('feed water preheater 2') - dsh = Desuperheater('desuperheater') - me2 = Merge('merge2', num_in=2) - pu2 = Pump('feed water pump 2') - pu3 = Pump('feed water pump 3') - me = Merge('merge', num_in=2) - - # cooling water - cwi = Source('cooling water source') - cwo = Sink('cooling water sink') - - # connections - # main cycle - cc_hpt = Connection(cc, 'out1', hpt, 'in1', label='feed steam') - hpt_sp1 = Connection(hpt, 'out1', sp1, 'in1', label='extraction1') - sp1_mpt = Connection(sp1, 'out1', mpt, 'in1', state='g') - mpt_sp2 = Connection(mpt, 'out1', sp2, 'in1', label='extraction2') - sp2_lpt = Connection(sp2, 'out1', lpt, 'in1') - lpt_con = Connection(lpt, 'out1', con, 'in1') - con_pu1 = Connection(con, 'out1', pu1, 'in1') - pu1_fwh1 = Connection(pu1, 'out1', fwh1, 'in2') - fwh1_me = Connection(fwh1, 'out2', me, 'in1', state='l') - me_fwh2 = Connection(me, 'out1', fwh2, 'in2', state='l') - fwh2_dsh = Connection(fwh2, 'out2', dsh, 'in2', state='l') - dsh_me2 = Connection(dsh, 'out2', me2, 'in1') - me2_eco = Connection(me2, 'out1', eco, 'in1', state='l') - eco_eva = Connection(eco, 'out1', eva, 'in1') - eva_sup = Connection(eva, 'out1', sup, 'in1') - sup_cc = Connection(sup, 'out1', cc, 'in1') - - self.nw.add_conns(cc_hpt, hpt_sp1, sp1_mpt, mpt_sp2, sp2_lpt, - lpt_con, con_pu1, pu1_fwh1, fwh1_me, me_fwh2, - fwh2_dsh, dsh_me2, me2_eco, eco_eva, eva_sup, sup_cc) - - # cooling water - cwi_con = Connection(cwi, 'out1', con, 'in2') - con_cwo = Connection(con, 'out2', cwo, 'in1') - - self.nw.add_conns(cwi_con, con_cwo) - - # preheating - sp1_dsh = Connection(sp1, 'out2', dsh, 'in1') - dsh_fwh2 = Connection(dsh, 'out1', fwh2, 'in1') - fwh2_pu2 = Connection(fwh2, 'out1', pu2, 'in1') - pu2_me2 = Connection(pu2, 'out1', me2, 'in2') - - sp2_fwh1 = Connection(sp2, 'out2', fwh1, 'in1') - fwh1_pu3 = Connection(fwh1, 'out1', pu3, 'in1') - pu3_me = Connection(pu3, 'out1', me, 'in2') - - self.nw.add_conns(sp1_dsh, dsh_fwh2, fwh2_pu2, pu2_me2, - sp2_fwh1, fwh1_pu3, pu3_me) - - # busses - # power bus - self.power = Bus('power') - self.power.add_comps( - {'comp': hpt, 'char': -1}, {'comp': mpt, 'char': -1}, - {'comp': lpt, 'char': -1}, {'comp': pu1, 'char': -1}, - {'comp': pu2, 'char': -1}, {'comp': pu3, 'char': -1}) - - # heating bus - self.heat = Bus('heat') - self.heat.add_comps( - {'comp': eco, 'char': 1}, {'comp': eva, 'char': 1}, - {'comp': sup, 'char': 1}) - - self.nw.add_busses(self.power, self.heat) - - # parametrization - # components - hpt.set_attr(eta_s=0.9) - mpt.set_attr(eta_s=0.9) - lpt.set_attr(eta_s=0.9) - - pu1.set_attr(eta_s=0.8) - pu2.set_attr(eta_s=0.8) - pu3.set_attr(eta_s=0.8) - - eco.set_attr(pr=0.99) - eva.set_attr(pr=0.99) - sup.set_attr(pr=0.99) - - con.set_attr(pr1=1, pr2=0.99, ttd_u=5) - fwh1.set_attr(pr1=1, pr2=0.99, ttd_u=5) - fwh2.set_attr(pr1=1, pr2=0.99, ttd_u=5) - dsh.set_attr(pr1=0.99, pr2=0.99) - - # connections - eco_eva.set_attr(x=0) - eva_sup.set_attr(x=1) - - cc_hpt.set_attr(m=200, T=650, p=100, fluid={'water': 1}) - hpt_sp1.set_attr(p=20) - mpt_sp2.set_attr(p=3) - lpt_con.set_attr(p=0.05) - - cwi_con.set_attr(T=20, p=10, fluid={'water': 1}) - - def calculate_efficiency(self, x): - # set extraction pressure - self.nw.get_conn('extraction1').set_attr(p=x[0]) - self.nw.get_conn('extraction2').set_attr(p=x[1]) - - self.nw.solve('design') - - # components are saved in a DataFrame, column 'object' holds the - # component instances - for cp in self.nw.comps['object']: - if isinstance(cp, Condenser) or isinstance(cp, Desuperheater): - if cp.Q.val > 0: - return np.nan - elif isinstance(cp, Pump): - if cp.P.val < 0: - return np.nan - elif isinstance(cp, Turbine): - if cp.P.val > 0: - return np.nan - - if self.nw.res[-1] > 1e-3 or self.nw.lin_dep: - return np.nan - else: - return self.nw.busses['power'].P.val / self.nw.busses['heat'].P.val - -Note, that you have to label all busses and connections you want to access -later on with PyGMO. In :code:`calculate_efficiency(self, x)` the variable -:code:`x` is a list containing your decision variables. This function returns -the cycle efficiency for a specific set of decision variables. The efficiency -is defined by the ratio of total power transferred (including turbines and -pumps) to steam generator heat input. - -Additionally, we have to make sure, only the result of physically feasible -solutions is returned. In case we have infeasible solutions, we can simply -return :code:`np.nan`. An infeasible solution is obtained in case the power -of a turbine is positive, the power of a pump is negative or the heat exchanged -in any of the preheaters is positive. We also check, if the calculation does -converge. - -.. math:: - - \eta_\mathrm{th}=\frac{|\sum P|}{\dot{Q}_{sg}} - -Creating your PyGMO-Model -^^^^^^^^^^^^^^^^^^^^^^^^^ - -The optimization in PyGMO starts by defining the problem. You can set the -number of objectives your problem has in :code:`get_nobj()`. The number of -constraints is set in :code:`get_nec()` (equality constraints) and -:code:`get_nic()` (inequality constraints). In :code:`get_bounds()` you set the -bounds of your decision variables. Finally, you define your fitness function -and constraints in :code:`fitness(self, x)`: - -.. code-block:: python - - import pygmo as pg - - - class optimization_problem(): - - def fitness(self, x): - f1 = 1 / self.model.calculate_efficiency(x) - ci1 = -x[0] + x[1] - print(x) - return [f1, ci1] - - def get_nobj(self): - """Return number of objectives.""" - return 1 - - # equality constraints - def get_nec(self): - return 0 - - # inequality constraints - def get_nic(self): - return 1 - - def get_bounds(self): - """Return bounds of decision variables.""" - return ([1, 1], [40, 40]) - -By default PyGMO minimizes the fitness function. Therefore we set the fitness -function f1 to the reciprocal of the cycle efficiency. We set one inequality -constraint so that the pressure of the first extraction has to be bigger than -the second one: - -.. math:: - - p_{e,1} > p_{e,2} - -In PyGMO your inequality constraint has to be in form of <0: - -.. math:: - - - p_{e,1} + p_{e,2} < 0 - -We expect that the extraction pressure won't be more than 40 bar and not less -1 bar. Therefore we set the bounds of our decision variables: - -.. math:: - - 1 bar < p_{e,1} < 40 bar\\ - 1 bar < p_{e,2} < 40 bar - - -Run PyGMO-Optimization -^^^^^^^^^^^^^^^^^^^^^^ - -The following code shows how to run the PyGMO optimization. - -.. code-block:: python - - optimize = optimization_problem() - optimize.model = PowerPlant() - prob = pg.problem(optimize) - num_gen = 15 - - pop = pg.population(prob, size=10) - algo = pg.algorithm(pg.ihs(gen=num_gen)) - - -With optimize you tell PyGMO which problem you want to optimize. In the class -:code:`optimization_problem()` we defined our problem be setting fitness -function and inequality constraint. With :code:`optimize.model` we set the -model we want to optimize. In our case we want to optimize the extraction -pressures in our instance of class :code:`PowerPlant`. Finally, our problem is -set in :code:`prob = pg.problem(optimize)`. - -With :code:`pop` we define the size of each population for the optimization, -:code:`algo` is used to set the algorithm you want to use. A list of available -algorithms can be found in -`List of algorithms `_. -The choice of your algorithm depends on the type of problem. Have you set -equality or inequality constraints? Do you perform a single- or multi-objective -optimization? - -We choose a population size of 10 individuals and want to carry out 15 -generations. We can evolve the population generation by generation, e.g. using -a for loop. At the end, we print out the information of the best individual. - -.. code-block:: python - - for gen in range(num_gen): - print('Evolution: {}'.format(gen)) - print('Efficiency: {} %'.format(round(100 / pop.champion_f[0], 4))) - pop = algo.evolve(pop) - - print() - print('Efficiency: {} %'.format(round(100 / pop.champion_f[0], 4))) - print('Extraction 1: {} bar'.format(round(pop.champion_x[0], 4))) - print('Extraction 2: {} bar'.format(round(pop.champion_x[1], 4))) - -In our run, we got: - -.. code:: bash - - Efficiency: 44.8596 % - Extraction 1: 25.8585 bar - Extraction 2: 2.6903 bar - - -.. figure:: /api/_images/scatterplot_efficiency_optimization.svg - :align: center - - Figure: Scatter plot for all individuals during the optimization. diff --git a/docs/whats_new.rst b/docs/whats_new.rst index c8f7f803c..b90e28fb2 100644 --- a/docs/whats_new.rst +++ b/docs/whats_new.rst @@ -3,11 +3,7 @@ What's New Discover noteable new features and improvements in each release -.. contents:: `Releases` - :depth: 1 - :local: - :backlinks: top - +.. include:: whats_new/v0-6-1.rst .. include:: whats_new/v0-6-0.rst .. include:: whats_new/v0-5-1.rst .. include:: whats_new/v0-5-0.rst diff --git a/docs/whats_new/v0-0-3.rst b/docs/whats_new/v0-0-3.rst index 3d3b538cd..512f872ac 100644 --- a/docs/whats_new/v0-0-3.rst +++ b/docs/whats_new/v0-0-3.rst @@ -16,7 +16,7 @@ Documentation ############# - internal adjustments for links in the documentation and API. - added a tutorial for the combustion chamber and moved tutorials to the :ref:`appropriate section ` (`8c0034d `_, `fd7a8e7 `_, `e887478 `_). -- added installation guide for :ref:`windows ` windows (`ca5eaa1 `_). +- added installation guide for :ref:`windows ` windows (`ca5eaa1 `_). Testing ####### diff --git a/docs/whats_new/v0-1-1.rst b/docs/whats_new/v0-1-1.rst index cd8ee80bf..7658e884e 100644 --- a/docs/whats_new/v0-1-1.rst +++ b/docs/whats_new/v0-1-1.rst @@ -29,8 +29,6 @@ Other changes - Changed access to imported network's connections (:code:`mynetwork.imp_conns['{source}:{source id}_{target}:{target id}']`, replace :code:`{...}` by the respectve component or id). (`a5a867 `_). - Improved convergence stability for temperatures specified near to the two phase area using the keyowrd :code:`state='l'` (for liquid) or :code:`state='g'` (for gaseous). The convergence check manipulates the enthalpy values at this connection in order to meet the phase specification (`PR #64 `_). - -.. _whats_new_011_example_label: Example ####### diff --git a/docs/whats_new/v0-1-2.rst b/docs/whats_new/v0-1-2.rst index d0902af3f..efa0a2501 100644 --- a/docs/whats_new/v0-1-2.rst +++ b/docs/whats_new/v0-1-2.rst @@ -33,8 +33,6 @@ Other changes - Add method to calculate and export vapour mass fraction values of pure fluids in the post processing (`PR #74 `_). - Only allow label and P as parameters for busses to avoid misleading parameter specification (`PR #78 `_). -.. _whats_new_012_example_label: - Water Electrolyzer Example ########################## diff --git a/docs/whats_new/v0-1-3.rst b/docs/whats_new/v0-1-3.rst index 00b3517c9..8afbddbd6 100644 --- a/docs/whats_new/v0-1-3.rst +++ b/docs/whats_new/v0-1-3.rst @@ -1,43 +1,43 @@ -v0.1.3 (November, 6, 2019) -++++++++++++++++++++++++++ - -New Features -############ -- Individual design path specification is available: Specify the design_path individually for single connections or a components in your network, if - you want the individual design parameters be loaded from a different design case than the network's design case given in the network's - design path (`PR #84 `_). -- Implement local design and local offdesign features: It is possible to design a plant while some parts of the plant are in offdesign mode. This is useful, - e.g. when designing an extraction turbine, where the district heating condenser is designed for maximum extraction and the backpressure turbine is designed - for minimum extraction (`PR #92 `_). -- Implement warning messages for all components, if the component's properties are out of physical bounds. The bounds can be customized when specifying a property - by data containers (read more at :ref:`component parameter specification `), (`PR #85 `_). - -Documentation -############# -- Change license from GPLv3 to MIT (`PR #93 `_). -- Fix unit error in component documentation for the zeta-value (`PR #93 `_). -- Improve documentation of the functions :func:`tespy.components.components.component.zeta_func` and :func:`tespy.components.components.component.zeta2_func` - (`4291bd `_). - -Parameter renaming -################## - -Testing -####### -- Added tests for the new design path feature (`PR #84 `_). -- Implemented additional network and component tests, (`PR #86 `_). - -Bug fixes -######### -- Offdesign values for connections are specified from the design case files (`PR #84 `_). Before, the offdesign values - were the actual values of the fluid property in the last calculation (which is not necessarily the design case). -- Add debug logging message, if the enthalpy is adjusted on connections with the keyword :code:`state` specified (`PR #85 `_). - -Other changes -############# -- Improved calculation speed for fluid mixture properties with the parameter T0 as starting value for root finding (`PR #84 `_). - -Contributors -############ - -- Francesco Witte +v0.1.3 (November, 6, 2019) +++++++++++++++++++++++++++ + +New Features +############ +- Individual design path specification is available: Specify the design_path individually for single connections or a components in your network, if + you want the individual design parameters be loaded from a different design case than the network's design case given in the network's + design path (`PR #84 `_). +- Implement local design and local offdesign features: It is possible to design a plant while some parts of the plant are in offdesign mode. This is useful, + e.g. when designing an extraction turbine, where the district heating condenser is designed for maximum extraction and the backpressure turbine is designed + for minimum extraction (`PR #92 `_). +- Implement warning messages for all components, if the component's properties are out of physical bounds. The bounds can be customized when specifying a property + by data containers (read more at :ref:`component parameter specification `), (`PR #85 `_). + +Documentation +############# +- Change license from GPLv3 to MIT (`PR #93 `_). +- Fix unit error in component documentation for the zeta-value (`PR #93 `_). +- Improve documentation of the functions :func:`tespy.components.components.component.zeta_func` and :func:`tespy.components.components.component.zeta2_func` + (`4291bd `_). + +Parameter renaming +################## + +Testing +####### +- Added tests for the new design path feature (`PR #84 `_). +- Implemented additional network and component tests, (`PR #86 `_). + +Bug fixes +######### +- Offdesign values for connections are specified from the design case files (`PR #84 `_). Before, the offdesign values + were the actual values of the fluid property in the last calculation (which is not necessarily the design case). +- Add debug logging message, if the enthalpy is adjusted on connections with the keyword :code:`state` specified (`PR #85 `_). + +Other changes +############# +- Improved calculation speed for fluid mixture properties with the parameter T0 as starting value for root finding (`PR #84 `_). + +Contributors +############ + +- Francesco Witte diff --git a/docs/whats_new/v0-2-0.rst b/docs/whats_new/v0-2-0.rst index 2e8b39c8f..ecc6bc7e4 100644 --- a/docs/whats_new/v0-2-0.rst +++ b/docs/whats_new/v0-2-0.rst @@ -6,9 +6,6 @@ new features have been implemented improving the usage of the software. Due to changes in the API, **version 0.2.0 will not be compatible with older** **versions of TESPy!** -The :ref:`example section below ` quickly shows, -how to modify your scripts in order to work with the new version. - New Features ############ - Implemented a new component "cycle_closer". This component may serve as substitute for a @@ -71,10 +68,10 @@ Other changes - Implement pep8speaks (PEP8 checker) in GitHub repository (`PR #131 `_). - The subsystem architecture has been simplified. Your connections and components are saved to dictionaries to make accessing the individual properties much easier (`PR #126 `_). For a use - case of subsystems, have a look at the :ref:`district heating example `. + case of subsystems, have a look at the :ref:`district heating example `. - Change the specification of set value for :py:class:`dc_simple ` class from :code:`val_set` to :code:`is_set` (`PR #138 `_). -- Move the default characteristic function plots to the :py:mod:`tespy.data ` module documentation +- Move the default characteristic function plots to the :ref:`tespy_data_label` documentation (`PR #138 `_). Contributors @@ -86,8 +83,6 @@ Contributors - @stianchris - @FranziPl -.. _tespy_v020_examples_label: - Examples ######## diff --git a/docs/whats_new/v0-2-2.rst b/docs/whats_new/v0-2-2.rst index 40c153357..4376a817b 100644 --- a/docs/whats_new/v0-2-2.rst +++ b/docs/whats_new/v0-2-2.rst @@ -1,65 +1,65 @@ -v0.2.2 - Rankine's Realm (March, 6, 2020) -+++++++++++++++++++++++++++++++++++++++++ - -New Features -############ -- Allow initialisation for the primary variables from previous calculation. - Until now, the user needed to save the network's state and reload that state - for his next simulation. This feature is enabled as default. If you want to - disable this feature, you need to state - :code:`mynetwork.solve(..., init_previous=False)` - (`PR #156 `_). -- Extrapolation for characteristic lines is available. In default state, the - upper or lower value range limit is used when a characteristic line is - evaluated outside of the available x-value range. The :code:`extrapolate` - parameter allows linear extrapolation, for an example see the corresponding - sections in the online documentation: - :ref:`component characteristics `, - :ref:`tespy characteristics ` - (`PR #159 `_). -- Add a new component evaporator for geothermal organic rankine cycle. The - component has inlets for geothermal steam brine. On the cold side, the orc - working fluid is evaporated. Read more about this component in the API - documentation: :py:class:`tespy.components.customs.orc_evaporator` - (`PR #148 `_). - -Documentation -############# -- Add method for automatic citations and references - (`PR #163 `_). - -Parameter renaming -################## - -Testing -####### -- Add convergence checks for all component tests. Some tests did not fail, even - if the calculation did not converge - (`PR #153 `_). -- Improve coverage of the networks module - (`PR #153 `_). -- Add tests for characteristic line and map evaluation - (`PR #159 `_). - -Bug fixes -######### -- Fix the bugged tests for compressor characteristic maps - (:py:meth:`tespy.components.turbomachinery.compressor.char_map_func`). The - pressure ratio factor of the lowest speedline available in the default data - ranges from about 0.2 to 0.5. Therefore the design pressure ratio should be - higher than 5 (`PR #156 `_). - -Other changes -############# -- Use the method :py:meth:`tespy.components.components.component.fluid_deriv` - for all components, that do not change composition between an inlet and the - respective outlet (`PR #153 `_). -- Adjust the method :py:meth:`tespy.components.components.component.zeta_func` - to work with all zeta value specifications - (`PR #153 `_). - -Contributors -############ -- Francesco Witte (`@fwitte `_) -- `@maltefritz `_ -- `@ChaofanChen `_ +v0.2.2 - Rankine's Realm (March, 6, 2020) ++++++++++++++++++++++++++++++++++++++++++ + +New Features +############ +- Allow initialisation for the primary variables from previous calculation. + Until now, the user needed to save the network's state and reload that state + for his next simulation. This feature is enabled as default. If you want to + disable this feature, you need to state + :code:`mynetwork.solve(..., init_previous=False)` + (`PR #156 `_). +- Extrapolation for characteristic lines is available. In default state, the + upper or lower value range limit is used when a characteristic line is + evaluated outside of the available x-value range. The :code:`extrapolate` + parameter allows linear extrapolation, for an example see the corresponding + sections in the online documentation: + :ref:`component characteristics `, + :ref:`tespy characteristics ` + (`PR #159 `_). +- Add a new component evaporator for geothermal organic rankine cycle. The + component has inlets for geothermal steam brine. On the cold side, the orc + working fluid is evaporated. Read more about this component in the API + documentation: :py:class:`tespy.components.customs.orc_evaporator` + (`PR #148 `_). + +Documentation +############# +- Add method for automatic citations and references + (`PR #163 `_). + +Parameter renaming +################## + +Testing +####### +- Add convergence checks for all component tests. Some tests did not fail, even + if the calculation did not converge + (`PR #153 `_). +- Improve coverage of the networks module + (`PR #153 `_). +- Add tests for characteristic line and map evaluation + (`PR #159 `_). + +Bug fixes +######### +- Fix the bugged tests for compressor characteristic maps + (:py:meth:`tespy.components.turbomachinery.compressor.char_map_func`). The + pressure ratio factor of the lowest speedline available in the default data + ranges from about 0.2 to 0.5. Therefore the design pressure ratio should be + higher than 5 (`PR #156 `_). + +Other changes +############# +- Use the method :py:meth:`tespy.components.components.component.fluid_deriv` + for all components, that do not change composition between an inlet and the + respective outlet (`PR #153 `_). +- Adjust the method :py:meth:`tespy.components.components.component.zeta_func` + to work with all zeta value specifications + (`PR #153 `_). + +Contributors +############ +- Francesco Witte (`@fwitte `_) +- `@maltefritz `_ +- `@ChaofanChen `_ diff --git a/docs/whats_new/v0-3-0.rst b/docs/whats_new/v0-3-0.rst index c727e76aa..2884c620e 100644 --- a/docs/whats_new/v0-3-0.rst +++ b/docs/whats_new/v0-3-0.rst @@ -211,12 +211,6 @@ which has been used until version 0.2.x in TESPy. "h_range": [150, 3000] } -Due to the addition of the CoolProp back end selection the -:py:class:`tespy.components.combustion.stoichiometric` API changed -as well. Please refer to the -:ref:`combustion chamber tutorial` for the -new implementation. - If you are having trouble applying these changes, you are welcome to open an issue on our `github repository `_. diff --git a/docs/whats_new/v0-3-4.rst b/docs/whats_new/v0-3-4.rst index 07f70687a..f15597fd9 100644 --- a/docs/whats_new/v0-3-4.rst +++ b/docs/whats_new/v0-3-4.rst @@ -4,7 +4,7 @@ v0.3.4 - Darwin's Delight (October, 13, 2020) Documentation ############# - Replace enthalpy starting value with :code:`state` keyword in the - :ref:`heat pump tutorial` and the examples from the + :ref:`heat pump tutorial ` and the examples from the oemof_examples repository (`PR #214 `_, `743bfeb `_). diff --git a/docs/whats_new/v0-4-0.rst b/docs/whats_new/v0-4-0.rst index cdec58a5c..d470650b4 100644 --- a/docs/whats_new/v0-4-0.rst +++ b/docs/whats_new/v0-4-0.rst @@ -140,12 +140,12 @@ New Features The diagrams could look like this: - .. figure:: /api/_images/logph_diagram_states.svg + .. figure:: /_static/images/modules/logph_diagram_states.svg :align: center Figure: logph diagram of NH3 with a simple heat pump cycle. - .. figure:: /api/_images/Ts_diagram_states.svg + .. figure:: /_static/images/modules/Ts_diagram_states.svg :align: center Figure: Ts diagram of NH3 with a simple heat pump cycle. diff --git a/docs/whats_new/v0-4-1.rst b/docs/whats_new/v0-4-1.rst index df2bdfccf..5517c19ba 100644 --- a/docs/whats_new/v0-4-1.rst +++ b/docs/whats_new/v0-4-1.rst @@ -10,7 +10,7 @@ New Features restrictions as long as the partial derivatives are provided correctly. For extensive examples have a look at the API documentation of class :py:class:`tespy.tools.helpers.UserDefinedEquation` or in the respective - section in the online :ref:`documentation ` + section in the online :ref:`documentation ` (`PR #245 `_). Documentation diff --git a/docs/whats_new/v0-4-3-003.rst b/docs/whats_new/v0-4-3-003.rst index 57d2e4bdb..5d05df4c8 100644 --- a/docs/whats_new/v0-4-3-003.rst +++ b/docs/whats_new/v0-4-3-003.rst @@ -1,19 +1,19 @@ -v0.4.3-003 - Grassmann's Graph (May, 17, 2021) -++++++++++++++++++++++++++++++++++++++++++++++ - -Documentation -############# -- Fix typos in the HeatExchanger classes API docs. -- Add two more examples for exergy analysis setups. - -Other Changes -############# -- Remove Python3.6 support. -- Make it possible to include results in automatic model report, for more - information see the corresponding section in the documentation: - :ref:`TESPy Networks Postprocessing ` - (`PR #267 `_). - -Contributors -############ -- Francesco Witte (`@fwitte `_) +v0.4.3-003 - Grassmann's Graph (May, 17, 2021) +++++++++++++++++++++++++++++++++++++++++++++++ + +Documentation +############# +- Fix typos in the HeatExchanger classes API docs. +- Add two more examples for exergy analysis setups. + +Other Changes +############# +- Remove Python3.6 support. +- Make it possible to include results in automatic model report, for more + information see the corresponding section in the documentation: + :ref:`TESPy Networks Postprocessing ` + (`PR #267 `_). + +Contributors +############ +- Francesco Witte (`@fwitte `_) diff --git a/docs/whats_new/v0-4-3.rst b/docs/whats_new/v0-4-3.rst index 96778fb5c..84eda0a84 100644 --- a/docs/whats_new/v0-4-3.rst +++ b/docs/whats_new/v0-4-3.rst @@ -8,7 +8,7 @@ New Features exergy sankey diagrams. For example, the diagram of the solar thermal power plant presented in the thermodynamic analyses section - .. figure:: /api/_images/SEGS_sankey.png + .. figure:: /_static/images/advanced/exergy/sankey.svg :align: center :alt: Example of the sankey diagram @@ -37,7 +37,7 @@ New Features Documentation ############# - An own chapter for the - :ref:`exergy analysis toolbox ` has been added + :ref:`exergy analysis toolbox ` has been added (`PR #251 `_). - Fix some typos in the code of heat pump tutorial (`PR #260 `_). diff --git a/docs/whats_new/v0-6-0.rst b/docs/whats_new/v0-6-0.rst index c912ff8a0..56648937c 100644 --- a/docs/whats_new/v0-6-0.rst +++ b/docs/whats_new/v0-6-0.rst @@ -16,6 +16,7 @@ New Features - Gaseous mixtures now check for condensation of water in enthalpy and entropy functions (`PR #318 `_). + Documentation ############# - Add tutorial for the :code:`DiabaticCombustionChamber` @@ -53,3 +54,4 @@ Contributors - `@tub-hofmann `_ - `@nkawerau `_ - `@BenPortner `_ +- `@matbock `_ diff --git a/docs/whats_new/v0-6-1.rst b/docs/whats_new/v0-6-1.rst new file mode 100644 index 000000000..59322fa20 --- /dev/null +++ b/docs/whats_new/v0-6-1.rst @@ -0,0 +1,45 @@ +v0.6.1 - Leidenfrost's Library (October, 02, 2022) +++++++++++++++++++++++++++++++++++++++++++++++++++ +We have completely revised the documentation improving the overall structure +and introducing a modern look +(`PR #355 `_). Have fun exploring the +website! + +New Features +############ +- Add support for higher Python versions and remove upper limit + (`PR #350 `_). +- A new component FuelCell is available: + :py:class:`tespy.components.reactors.fuel_cell.FuelCell`. It is analogously + defined to the WaterElectrolyzer + :py:class:`tespy.components.reactors.water_electrolyzer.WaterElectrolyzer` + (`PR #329 `_). +- Integration of an optimization suite using pygmo :cite:`Biscani2020` to apply + a variety of state of the art optimization algorithms to your TESPy model + (`PR #296 `__). It has been further + improved in `PR #357 `__. +- Volumetric flow can be referenced using the + :py:class:`tespy.connections.connection.Ref` class + (`Discussion #352 `__). + +Bug Fixes +######### +- The Network's component DataFrame is now available as soon as a connection + is added to the network. It is possible to use the + :py:meth:`tespy.networks.network.Network.get_comp` method prior to + initializing or solving + (`PR #362 `_). + +Documentation +############# +- Fix some typos in the online documentation + (`PR #342 `_). +- New tutorial on starting values for a subcritical heat pump setup + (`PR #346 `_). + +Contributors +############ +- Francesco Witte (`@fwitte `_) +- `@NicholasFry `_ +- Matthias Bock (`@matbock `_) +- `@maltefritz `_ diff --git a/docs/zliterature.rst b/docs/zliterature.rst index 5d756bbc2..ba7707151 100644 --- a/docs/zliterature.rst +++ b/docs/zliterature.rst @@ -3,3 +3,4 @@ Literature .. bibliography:: references.bib :all: + :style: unsrt diff --git a/setup.cfg b/setup.cfg index fc3581aa2..f6b660aed 100644 --- a/setup.cfg +++ b/setup.cfg @@ -102,9 +102,10 @@ skip = migrations # - can use as many you want python_versions = - py36 py37 py38 + py39 + py310 dependencies = # 1.4: Django==1.4.16 !python_versions[py3*] diff --git a/setup.py b/setup.py index 8655568f4..45ee3a7d1 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ def read(*names, **kwargs): setup( name='TESPy', - version='0.6.0', + version='0.6.1', license='MIT', description='Thermal Engineering Systems in Python (TESPy)', long_description='%s' % ( @@ -41,8 +41,7 @@ def read(*names, **kwargs): py_modules=[splitext(basename(path))[0] for path in glob('src/*.py')], include_package_data=True, zip_safe=False, - data_files=[('src/tespy/data', [ - 'src/tespy/data/char_lines.json', 'src/tespy/data/char_maps.json'])], + package_data={'src': ['*.json']}, classifiers=[ 'Development Status :: 4 - Beta', 'Intended Audience :: Education', @@ -54,6 +53,8 @@ def read(*names, **kwargs): 'Programming Language :: Python', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', 'Topic :: Scientific/Engineering', ], project_urls={ @@ -61,7 +62,7 @@ def read(*names, **kwargs): 'Changelog': 'https://tespy.readthedocs.io/en/main/whats_new.html', 'Issue Tracker': 'https://github.com/oemof/tespy/issues', }, - python_requires='>=3.7, <3.9', + python_requires='>=3.7', install_requires=[ 'CoolProp>=6.4,<7', 'matplotlib>=3.2.1,<4', @@ -70,7 +71,15 @@ def read(*names, **kwargs): 'tabulate>=0.8.2,<0.9' ], extras_require={ - 'dev': ['pytest', 'sphinx', 'sphinx_rtd_theme', - 'sphinxcontrib.bibtex', 'tox', ], - 'dummy': ['tespy']} + 'dev': [ + 'furo', + 'pytest', + 'sphinx', + 'sphinx-copybutton', + 'sphinx-design', + 'sphinxcontrib.bibtex', + 'tox', + ], + 'dummy': ['tespy'] + } ) diff --git a/src/tespy/__init__.py b/src/tespy/__init__.py index 51e54b383..590e30e16 100644 --- a/src/tespy/__init__.py +++ b/src/tespy/__init__.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 +from pkg_resources import resource_filename -__version__ = '0.6.0 - Colored Chemicals' +__datapath__ = resource_filename('tespy', 'data/') +__version__ = '0.6.1 - Leidenfrost\'s Library' # tespy data and connections import from . import connections # noqa: F401 diff --git a/src/tespy/components/__init__.py b/src/tespy/components/__init__.py index 9286f785a..8d0921c9f 100644 --- a/src/tespy/components/__init__.py +++ b/src/tespy/components/__init__.py @@ -21,6 +21,7 @@ from .nodes.splitter import Splitter # noqa: F401 from .piping.pipe import Pipe # noqa: F401 from .piping.valve import Valve # noqa: F401 +from .reactors.fuel_cell import FuelCell # noqa: F401 from .reactors.water_electrolyzer import WaterElectrolyzer # noqa: F401 from .subsystem import Subsystem # noqa: F401 from .turbomachinery.compressor import Compressor # noqa: F401 diff --git a/src/tespy/components/basics/subsystem_interface.py b/src/tespy/components/basics/subsystem_interface.py index 259bf2265..62d208f89 100644 --- a/src/tespy/components/basics/subsystem_interface.py +++ b/src/tespy/components/basics/subsystem_interface.py @@ -23,10 +23,8 @@ class SubsystemInterface(Component): - :py:meth:`tespy.components.component.Component.fluid_func` - :py:meth:`tespy.components.component.Component.mass_flow_func` - - Pressure: - :py:meth:`tespy.components.basics.subsystem_interface.SubsystemInterface.variable_equality_func` - - Enthalpy: - :py:meth:`tespy.components.basics.subsystem_interface.SubsystemInterface.variable_equality_func` + - :py:meth:`tespy.components.component.Component.pressure_equality_func` + - :py:meth:`tespy.components.component.Component.enthalpy_equality_func` Inlets/Outlets @@ -35,9 +33,15 @@ class SubsystemInterface(Component): Image - .. image:: _images/SubsystemInterface.svg - :alt: alternative text + .. image:: /api/_images/SubsystemInterface.svg + :alt: flowsheet of the subsystem interface :align: center + :class: only-light + + .. image:: /api/_images/SubsystemInterface_darkmode.svg + :alt: flowsheet of the subsystem interface + :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/components/combustion/base.py b/src/tespy/components/combustion/base.py index db12f6f8a..eeeca15e7 100644 --- a/src/tespy/components/combustion/base.py +++ b/src/tespy/components/combustion/base.py @@ -53,9 +53,15 @@ class CombustionChamber(Component): Image - .. image:: _images/CombustionChamber.svg - :alt: alternative text + .. image:: /api/_images/CombustionChamber.svg + :alt: flowsheet of the combustion chamber :align: center + :class: only-light + + .. image:: /api/_images/CombustionChamber_darkmode.svg + :alt: flowsheet of the combustion chamber + :align: center + :class: only-dark .. note:: diff --git a/src/tespy/components/combustion/diabatic.py b/src/tespy/components/combustion/diabatic.py index 41c0ae0aa..92351fef6 100644 --- a/src/tespy/components/combustion/diabatic.py +++ b/src/tespy/components/combustion/diabatic.py @@ -47,15 +47,21 @@ class DiabaticCombustionChamber(CombustionChamber): Image - .. image:: _images/CombustionChamber.svg - :alt: alternative text + .. image:: /api/_images/CombustionChamber.svg + :alt: flowsheet of the combustion chamber :align: center + :class: only-light + + .. image:: /api/_images/CombustionChamber_darkmode.svg + :alt: flowsheet of the combustion chamber + :align: center + :class: only-dark .. note:: The fuel and the air components can be connected to either of the inlets. The pressure of inlet 2 is disconnected from the pressure of - inlet 1. A warning is promted, if the pressure at inlet 2 is lower than + inlet 1. A warning is prompted, if the pressure at inlet 2 is lower than the pressure at inlet 1. Parameters @@ -189,7 +195,7 @@ def get_variables(self): max_val=1, min_val=0, deriv=self.energy_balance_deriv, func=self.energy_balance_func, latex=self.energy_balance_func_doc, num_eq=1), - 'Q_loss': dc_cp(max_val=0) + 'Q_loss': dc_cp(max_val=0, is_result=True) } def get_mandatory_constraints(self): diff --git a/src/tespy/components/combustion/engine.py b/src/tespy/components/combustion/engine.py index 4050c6b6b..bdf9a072e 100644 --- a/src/tespy/components/combustion/engine.py +++ b/src/tespy/components/combustion/engine.py @@ -74,9 +74,15 @@ class CombustionEngine(CombustionChamber): Image - .. image:: _images/CombustionEngine.svg - :alt: alternative text + .. image:: /api/_images/CombustionEngine.svg + :alt: flowsheet of the combustion engine :align: center + :class: only-light + + .. image:: /api/_images/CombustionEngine_darkmode.svg + :alt: flowsheet of the combustion engine + :align: center + :class: only-dark .. note:: @@ -215,7 +221,7 @@ class CombustionEngine(CombustionChamber): ... design=['pr1'], offdesign=['zeta1']) >>> amb_comb.set_attr(p=5, T=30, fluid={'Ar': 0.0129, 'N2': 0.7553, ... 'H2O': 0, 'CH4': 0, 'CO2': 0.0004, 'O2': 0.2314}) - >>> sf_comb.set_attr(m0=0.1, T=30, fluid={'CO2': 0, 'Ar': 0, 'N2': 0, + >>> sf_comb.set_attr(T=30, fluid={'CO2': 0, 'Ar': 0, 'N2': 0, ... 'O2': 0, 'H2O': 0, 'CH4': 1}) >>> cw_sp.set_attr(p=3, T=60, m=50, fluid={'CO2': 0, 'Ar': 0, 'N2': 0, ... 'O2': 0, 'H2O': 1, 'CH4': 0}) diff --git a/src/tespy/components/heat_exchangers/base.py b/src/tespy/components/heat_exchangers/base.py index a7a69fcc2..ec890aa0d 100644 --- a/src/tespy/components/heat_exchangers/base.py +++ b/src/tespy/components/heat_exchangers/base.py @@ -56,9 +56,15 @@ class HeatExchanger(Component): Image - .. image:: _images/HeatExchanger.svg - :alt: alternative text + .. image:: /api/_images/HeatExchanger.svg + :alt: flowsheet of the heat exchanger :align: center + :class: only-light + + .. image:: /api/_images/HeatExchanger_darkmode.svg + :alt: flowsheet of the heat exchanger + :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/components/heat_exchangers/condenser.py b/src/tespy/components/heat_exchangers/condenser.py index 178235548..2f21d36da 100644 --- a/src/tespy/components/heat_exchangers/condenser.py +++ b/src/tespy/components/heat_exchangers/condenser.py @@ -61,9 +61,15 @@ class Condenser(HeatExchanger): Image - .. image:: _images/Condenser.svg - :alt: alternative text + .. image:: /api/_images/Condenser.svg + :alt: flowsheet of the condenser :align: center + :class: only-light + + .. image:: /api/_images/Condenser_darkmode.svg + :alt: flowsheet of the condenser + :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/components/heat_exchangers/desuperheater.py b/src/tespy/components/heat_exchangers/desuperheater.py index 64cc974ff..f9906792a 100644 --- a/src/tespy/components/heat_exchangers/desuperheater.py +++ b/src/tespy/components/heat_exchangers/desuperheater.py @@ -47,9 +47,15 @@ class Desuperheater(HeatExchanger): Image - .. image:: _images/HeatExchanger.svg - :alt: alternative text + .. image:: /api/_images/HeatExchanger.svg + :alt: flowsheet of the desuperheater :align: center + :class: only-light + + .. image:: /api/_images/HeatExchanger_darkmode.svg + :alt: flowsheet of the desuperheater + :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/components/heat_exchangers/parabolic_trough.py b/src/tespy/components/heat_exchangers/parabolic_trough.py index 387eb426a..5f445a49c 100644 --- a/src/tespy/components/heat_exchangers/parabolic_trough.py +++ b/src/tespy/components/heat_exchangers/parabolic_trough.py @@ -45,9 +45,15 @@ class ParabolicTrough(HeatExchangerSimple): Image - .. image:: _images/ParabolicTrough.svg - :alt: alternative text + .. image:: /api/_images/ParabolicTrough.svg + :alt: flowsheet of the parabolic trough :align: center + :class: only-light + + .. image:: /api/_images/ParabolicTrough_darkmode.svg + :alt: flowsheet of the parabolic trough + :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/components/heat_exchangers/simple.py b/src/tespy/components/heat_exchangers/simple.py index f2468afc5..91b68e5be 100644 --- a/src/tespy/components/heat_exchangers/simple.py +++ b/src/tespy/components/heat_exchangers/simple.py @@ -60,9 +60,15 @@ class HeatExchangerSimple(Component): Image - .. image:: _images/Pipe.svg - :alt: alternative text + .. image:: /api/_images/Pipe.svg + :alt: flowsheet of the simple heat exchanger :align: center + :class: only-light + + .. image:: /api/_images/Pipe_darkmode.svg + :alt: flowsheet of the simple heat exchanger + :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/components/heat_exchangers/solar_collector.py b/src/tespy/components/heat_exchangers/solar_collector.py index 669b07226..b66680204 100644 --- a/src/tespy/components/heat_exchangers/solar_collector.py +++ b/src/tespy/components/heat_exchangers/solar_collector.py @@ -45,9 +45,15 @@ class SolarCollector(HeatExchangerSimple): Image - .. image:: _images/SolarCollector.svg - :alt: alternative text + .. image:: /api/_images/SolarCollector.svg + :alt: flowsheet of the solar collector :align: center + :class: only-light + + .. image:: /api/_images/SolarCollector_darkmode.svg + :alt: flowsheet of the solar collector + :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/components/nodes/droplet_separator.py b/src/tespy/components/nodes/droplet_separator.py index 276e0d0cb..74943bbd6 100644 --- a/src/tespy/components/nodes/droplet_separator.py +++ b/src/tespy/components/nodes/droplet_separator.py @@ -40,9 +40,15 @@ class DropletSeparator(NodeBase): Image - .. image:: _images/DropletSeparator.svg - :alt: alternative text + .. image:: /api/_images/DropletSeparator.svg + :alt: flowsheet of the droplet separator :align: center + :class: only-light + + .. image:: /api/_images/DropletSeparator_darkmode.svg + :alt: flowsheet of the droplet separator + :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/components/nodes/drum.py b/src/tespy/components/nodes/drum.py index f67984f86..657573ef3 100644 --- a/src/tespy/components/nodes/drum.py +++ b/src/tespy/components/nodes/drum.py @@ -35,9 +35,15 @@ class Drum(DropletSeparator): Image - .. image:: _images/Drum.svg - :alt: alternative text + .. image:: /api/_images/Drum.svg + :alt: flowsheet of the drum :align: center + :class: only-light + + .. image:: /api/_images/Drum_darkmode.svg + :alt: flowsheet of the drum + :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/components/nodes/merge.py b/src/tespy/components/nodes/merge.py index 53e7bd25d..ceda8c098 100644 --- a/src/tespy/components/nodes/merge.py +++ b/src/tespy/components/nodes/merge.py @@ -37,9 +37,15 @@ class Merge(NodeBase): Image - .. image:: _images/Merge.svg - :alt: alternative text + .. image:: /api/_images/Merge.svg + :alt: flowsheet of the merge :align: center + :class: only-light + + .. image:: /api/_images/Merge_darkmode.svg + :alt: flowsheet of the merge + :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/components/nodes/separator.py b/src/tespy/components/nodes/separator.py index ab107cc1b..48661293c 100644 --- a/src/tespy/components/nodes/separator.py +++ b/src/tespy/components/nodes/separator.py @@ -39,9 +39,15 @@ class Separator(NodeBase): Image - .. image:: _images/Splitter.svg - :alt: alternative text + .. image:: /api/_images/Splitter.svg + :alt: flowsheet of the splitter :align: center + :class: only-light + + .. image:: /api/_images/Splitter_darkmode.svg + :alt: flowsheet of the splitter + :align: center + :class: only-dark Note ---- diff --git a/src/tespy/components/nodes/splitter.py b/src/tespy/components/nodes/splitter.py index c010d7453..b8bde6885 100644 --- a/src/tespy/components/nodes/splitter.py +++ b/src/tespy/components/nodes/splitter.py @@ -35,9 +35,15 @@ class Splitter(NodeBase): Image - .. image:: _images/Splitter.svg - :alt: alternative text + .. image:: /api/_images/Splitter.svg + :alt: flowsheet of the splitter :align: center + :class: only-light + + .. image:: /api/_images/Splitter_darkmode.svg + :alt: flowsheet of the splitter + :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/components/piping/pipe.py b/src/tespy/components/piping/pipe.py index 7be2d211f..53bf10984 100644 --- a/src/tespy/components/piping/pipe.py +++ b/src/tespy/components/piping/pipe.py @@ -38,9 +38,15 @@ class Pipe(HeatExchangerSimple): Image - .. image:: _images/Pipe.svg - :alt: alternative text + .. image:: /api/_images/Pipe.svg + :alt: flowsheet of the pipe :align: center + :class: only-light + + .. image:: /api/_images/Pipe_darkmode.svg + :alt: flowsheet of the pipe + :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/components/piping/valve.py b/src/tespy/components/piping/valve.py index bc86864c6..4d7b85361 100644 --- a/src/tespy/components/piping/valve.py +++ b/src/tespy/components/piping/valve.py @@ -42,9 +42,15 @@ class Valve(Component): Image - .. image:: _images/Valve.svg - :alt: alternative text + .. image:: /api/_images/Valve.svg + :alt: flowsheet of the valve :align: center + :class: only-light + + .. image:: /api/_images/Valve_darkmode.svg + :alt: flowsheet of the valve + :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/components/reactors/fuel_cell.py b/src/tespy/components/reactors/fuel_cell.py new file mode 100644 index 000000000..b65889a07 --- /dev/null +++ b/src/tespy/components/reactors/fuel_cell.py @@ -0,0 +1,975 @@ +import logging + +import CoolProp.CoolProp as CP +import numpy as np + +from tespy.components.component import Component +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.document_models import generate_latex_eq +from tespy.tools.fluid_properties import h_mix_pT +from tespy.tools.global_vars import molar_masses +from tespy.tools.helpers import TESPyComponentError + + +class FuelCell(Component): + r""" + The fuel cell produces power by oxidation of hydrogen. + + **Mandatory Equations** + + - :py:meth:`tespy.components.reactors.fuel_cell.FuelCell.fluid_func` + - :py:meth:`tespy.components.reactors.fuel_cell.FuelCell.mass_flow_func` + - :py:meth:`tespy.components.reactors.fuel_cell.FuelCell.reactor_pressure_func` + - :py:meth:`tespy.components.reactors.fuel_cell.FuelCell.energy_balance_func` + + **Optional Equations** + + - cooling loop: + + - :py:meth:`tespy.components.component.Component.zeta_func` + - :py:meth:`tespy.components.component.Component.pr_func` + + - :py:meth:`tespy.components.reactors.fuel_cell.FuelCell.eta_func` + - :py:meth:`tespy.components.reactors.fuel_cell.FuelCell.heat_func` + - :py:meth:`tespy.components.reactors.fuel_cell.FuelCell.specific_energy_func` + + Inlets/Outlets + + - in1 (cooling inlet), in2 (oxygen inlet), in3 (hydrogen inlet) + - out1 (cooling outlet), out2 (water outlet) + + Image + + .. image:: _images/FuelCell.svg + :alt: alternative text + :align: center + + Parameters + ---------- + label : str + The label of the component. + + design : list + List containing design parameters (stated as String). + + offdesign : list + List containing offdesign parameters (stated as String). + + design_path : str + Path to the components design case. + + local_offdesign : boolean + Treat this component in offdesign mode in a design calculation. + + local_design : boolean + Treat this component in design mode in an offdesign calculation. + + char_warnings : boolean + Ignore warnings on default characteristics usage for this component. + + printout : boolean + Include this component in the network's results printout. + + P : float, dict, :code:`"var"` + Power input, :math:`P/\text{W}`. + + Q : float, dict + Heat output of cooling, :math:`Q/\text{W}` + + e : float, dict, :code:`"var"` + Electrolysis specific energy consumption, + :math:`e/(\text{J}/\text{m}^3)`. + + eta : float, dict + Electrolysis efficiency, :math:`\eta/1`. + + pr : float, dict, :code:`"var"` + Cooling loop pressure ratio, :math:`pr/1`. + + zeta : float, dict, :code:`"var"` + Geometry independent friction coefficient for cooling loop pressure + drop, :math:`\frac{\zeta}{D^4}/\frac{1}{\text{m}^4}`. + + Note + ---- + Other than usual components, the fuel cell has the fluid composition + built into its equations for the feed hydrogen and oxygen inlets as well + as the water outlet. Thus, the user must not specify the fluid composition + at these connections! + + Example + ------- + The example shows a simple adaptation of the fuel cell. It works with water + as cooling fluid. + + >>> from tespy.components import (Sink, Source, FuelCell) + >>> from tespy.connections import Connection + >>> from tespy.networks import Network + >>> from tespy.tools import ComponentCharacteristics as dc_cc + >>> import shutil + >>> fluid_list = ['H2O', 'O2', 'H2'] + >>> nw = Network(fluids=fluid_list, T_unit='C', p_unit='bar', + ... v_unit='l / s', iterinfo=False) + >>> fc = FuelCell('fuel cell') + >>> fc.component() + 'fuel cell' + >>> oxygen_source = Source('oxygen_source') + >>> hydrogen_source = Source('hydrogen_source') + >>> cw_source = Source('cw_source') + >>> cw_sink = Sink('cw_sink') + >>> water_sink = Sink('water_sink') + >>> cw_in = Connection(cw_source, 'out1', fc, 'in1') + >>> cw_out = Connection(fc, 'out1', cw_sink, 'in1') + >>> oxygen_in = Connection(oxygen_source, 'out1', fc, 'in2') + >>> hydrogen_in = Connection(hydrogen_source, 'out1', fc, 'in3') + >>> water_out = Connection(fc, 'out2', water_sink, 'in1') + >>> nw.add_conns(cw_in, cw_out, oxygen_in, hydrogen_in, water_out) + + The fuel cell shall produce 200kW of electrical power and 200kW of heat + with an efficiency of 0.45. The thermodynamic parameters of the input + oxygen and hydrogen are given, the mass flow rates are calculated out of + the given power output. The cooling fluid is pure water. + + >>> fc.set_attr(eta=0.45, P=-200e03, Q=-200e03, pr=0.9) + >>> cw_in.set_attr(T=25, p=1, m=1, fluid={'H2O': 1, 'O2': 0, 'H2': 0}) + >>> oxygen_in.set_attr(T=25, p=1) + >>> hydrogen_in.set_attr(T=25) + >>> nw.solve('design') + >>> P_design = fc.P.val / 1e3 + >>> round(P_design, 0) + -200.0 + >>> round(fc.eta.val, 2) + 0.45 + """ + @staticmethod + def component(): + return 'fuel cell' + +# %% Variables + + def get_variables(self): + return { + 'P': dc_cp(max_val=0), + 'Q': dc_cp( + max_val=0, num_eq=1, + deriv=self.heat_deriv, func=self.heat_func, + latex=self.heat_func_doc), + 'pr': dc_cp( + max_val=1, num_eq=1, + deriv=self.pr_deriv, func=self.pr_func, + func_params={'pr': 'pr'}, latex=self.pr_func_doc), + 'zeta': dc_cp( + min_val=0, num_eq=1, + deriv=self.zeta_deriv, func=self.zeta_func, + func_params={'zeta': 'zeta'}, latex=self.zeta_func_doc), + 'eta': dc_cp( + min_val=0, max_val=1, num_eq=1, latex=self.eta_func_doc, + deriv=self.eta_deriv, func=self.eta_func), + 'e': dc_cp( + max_val=0, num_eq=1, + deriv=self.specific_energy_deriv, + func=self.specific_energy_func, + latex=self.specific_energy_func_doc) + } + +# %% Mandatory constraints + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 3}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': True, 'latex': self.fluid_func_doc, + 'num_eq': self.num_nw_fluids * 4}, + 'energy_balance_constraints': { + 'func': self.energy_balance_func, + 'deriv': self.energy_balance_deriv, + 'constant_deriv': False, 'latex': self.energy_balance_func_doc, + 'num_eq': 1}, + 'reactor_pressure_constraints': { + 'func': self.reactor_pressure_func, + 'deriv': self.reactor_pressure_deriv, + 'constant_deriv': True, + 'latex': self.reactor_pressure_func_doc, + 'num_eq': 2}, + } + +# %% Inlets and outlets + + def inlets(self): + return ['in1', 'in2', 'in3'] + + def outlets(self): + return ['out1', 'out2'] + +# %% Equations and derivatives + + def comp_init(self, nw): + + if not self.P.is_set: + self.set_attr(P='var') + msg = ('The power output of a fuel cell must be set! ' + 'We are adding the power output of component ' + + self.label + ' as custom variable of the system.') + logging.info(msg) + + for fluid in ['H2', 'H2O', 'O2']: + try: + setattr( + self, fluid, [x for x in nw.fluids if x in [ + a.replace(' ', '') for a in + CP.get_aliases(fluid.upper()) + ]][0]) + except IndexError: + msg = ( + 'The component ' + self.label + ' (class ' + + self.__class__.__name__ + ') requires that the fluid ' + '[fluid] is in the network\'s list of fluids.') + aliases = ', '.join(CP.get_aliases(fluid.upper())) + msg = msg.replace( + '[fluid]', fluid.upper() + ' (aliases: ' + aliases + ')') + logging.error(msg) + raise TESPyComponentError(msg) + + self.e0 = self.calc_e0() + + Component.comp_init(self, nw) + + def calc_e0(self): + r""" + Calculate the specific energy output of the fuel cell. + + Returns + ------- + val : float + Specific energy. + + .. math:: + + e0 = \frac{\sum_i {\Delta H_f^0}_i - + \sum_j {\Delta H_f^0}_j } + {M_{H_2}}\\ + \forall i \in \text{reation products},\\ + \forall j \in \text{reation educts},\\ + \Delta H_f^0: \text{molar formation enthalpy} + """ + hf = {} + hf['H2O'] = -286000 + hf['H2'] = 0 + hf['O2'] = 0 + M = molar_masses[self.H2] + e0 = (2 * hf['H2O'] - 2 * hf['H2'] - hf['O2']) / (2 * M) + + return e0 + + def eta_func(self): + r""" + Equation for efficiency. + + Returns + ------- + residual : float + Residual value of equation. + + .. math:: + + 0 = P - \eta \cdot \dot{m}_{H_2,in} \cdot e_0 + """ + return self.P.val - self.eta.val * self.inl[2].m.val_SI * self.e0 + + def eta_func_doc(self, label): + r""" + Equation for efficiency. + + Parameters + ---------- + label : str + Label for equation. + + Returns + ------- + latex : str + LaTeX code of equations applied. + """ + latex = r'0 = P - \eta \cdot \dot{m}_\mathrm{H_2,in,3} \cdot e_0' + return generate_latex_eq(self, latex, label) + + def eta_deriv(self, increment_filter, k): + r""" + Partial derivatives for efficiency function. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of derivatives in Jacobian matrix (k-th equation). + """ + # derivative for m_H2,in: + self.jacobian[k, 2, 0] = -self.eta.val * self.e0 + # derivatives for variable P: + if self.P.is_var: + self.jacobian[k, 5 + self.P.var_pos, 0] = 1 + + def heat_func(self): + r""" + Equation for heat output. + + Returns + ------- + residual : float + Residual value of equation. + + .. math:: + + 0 = \dot{Q}-\dot{m}_{in,1}\cdot \left(h_{out,1}-h_{in,1}\right) + """ + return self.Q.val + self.inl[0].m.val_SI * ( + self.outl[0].h.val_SI - self.inl[0].h.val_SI) + + def heat_func_doc(self, label): + r""" + Equation for heat output. + + Parameters + ---------- + label : str + Label for equation. + + Returns + ------- + latex : str + LaTeX code of equations applied. + """ + latex = ( + r'0=\dot{Q}+\dot{m}_\mathrm{in,1}\cdot\left(h_\mathrm{out,1}-' + r'h_\mathrm{in,1}\right)') + return generate_latex_eq(self, latex, label) + + def heat_deriv(self, increment_filter, k): + r""" + Partial derivatives for heat output function. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of derivatives in Jacobian matrix (k-th equation). + """ + self.jacobian[k, 0, 0] = -( + self.inl[0].h.val_SI - self.outl[0].h.val_SI + ) + self.jacobian[k, 0, 2] = -self.inl[0].m.val_SI + self.jacobian[k, 3, 2] = self.inl[0].m.val_SI + + def specific_energy_func(self): + r""" + Equation for specific energy output. + + Returns + ------- + residual : float + Residual value of equation. + + .. math:: + + 0 = P - \dot{m}_{H_2,in} \cdot e + """ + return self.P.val - self.inl[2].m.val_SI * self.e.val + + def specific_energy_func_doc(self, label): + r""" + Equation for specific energy output. + + Parameters + ---------- + label : str + Label for equation. + + Returns + ------- + latex : str + LaTeX code of equations applied. + """ + latex = r'0=P - \dot{m}_\mathrm{H_2,in} \cdot e' + return generate_latex_eq(self, latex, label) + + def specific_energy_deriv(self, increment_filter, k): + r""" + Partial derivatives for specific energy function. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of derivatives in Jacobian matrix (k-th equation). + """ + self.jacobian[k, 2, 0] = -self.e.val + # derivatives for variable P + if self.P.is_var: + self.jacobian[k, 5 + self.P.var_pos, 0] = 1 + # derivatives for variable e + if self.e.is_var: + self.jacobian[k, 5 + self.e.var_pos, 0] = -self.inl[2].m.val_SI + + def energy_balance_func(self): + r""" + Calculate the residual in energy balance. + + Returns + ------- + residual : float + Residual value of energy balance equation. + + .. math:: + + \begin{split} + 0=&P + \dot{m}_\mathrm{out,2}\cdot\left(h_\mathrm{out,2}- + h_\mathrm{out,2,ref}\right)\\ + &+\dot{m}_\mathrm{in,1}\cdot\left( h_\mathrm{out,1} - + h_\mathrm{in,1} \right)\\ + & -\dot{m}_\mathrm{in,2} \cdot \left( h_\mathrm{in,2} - + h_\mathrm{in,2,ref} \right)\\ + & -\dot{m}_\mathrm{in,3} \cdot \left( h_\mathrm{in,3} - + h_\mathrm{in,3,ref} - e_0\right)\\ + \end{split} + + - Reference temperature: 298.15 K. + - Reference pressure: 1 bar. + """ + return self.P.val - self.calc_P() + + def energy_balance_func_doc(self, label): + r""" + Calculate the residual in energy balance. + + Parameters + ---------- + label : str + Label for equation. + + Returns + ------- + latex : str + LaTeX code of equations applied. + """ + latex = ( + r'\begin{split}' + '\n' + r'0=&P + \dot{m}_\mathrm{out,2}\cdot\left(h_\mathrm{out,2}-' + r'h_\mathrm{out,2,ref}\right)\\' + '\n' + r'&+\dot{m}_\mathrm{in,1}\cdot\left( h_\mathrm{out,1} -' + r'h_\mathrm{in,1} \right)\\' + '\n' + r'& - \dot{m}_\mathrm{in,2} \cdot \left( h_\mathrm{in,2} -' + r'h_\mathrm{in,2,ref} \right)\\' + '\n' + r'& - \dot{m}_\mathrm{in,3} \cdot \left( h_\mathrm{in,3} -' + r'h_\mathrm{in,3,ref} - e_0\right)\\' + '\n' + r'&p_\mathrm{ref}=\unit[1]{bar},' + r'\;T_\mathrm{ref}=\unit[25]{^\circ C}\\' + '\n' + r'\end{split}' + ) + return generate_latex_eq(self, latex, label) + + def energy_balance_deriv(self, increment_filter, k): + r""" + Partial derivatives for reactor energy balance. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of derivatives in Jacobian matrix (k-th equation). + """ + # derivatives determined from calc_P function + T_ref = 298.15 + p_ref = 1e5 + h_refh2o = h_mix_pT([1, p_ref, 0, self.outl[1].fluid.val], T_ref) + h_refh2 = h_mix_pT([1, p_ref, 0, self.inl[2].fluid.val], T_ref) + h_refo2 = h_mix_pT([1, p_ref, 0, self.inl[1].fluid.val], T_ref) + + # derivatives cooling water inlet + self.jacobian[k, 0, 0] = self.outl[0].h.val_SI - self.inl[0].h.val_SI + self.jacobian[k, 0, 2] = -self.inl[0].m.val_SI + + # derivatives water outlet + self.jacobian[k, 4, 0] = (self.outl[1].h.val_SI - h_refh2o) + self.jacobian[k, 4, 2] = self.outl[1].m.val_SI + + # derivative cooling water outlet + self.jacobian[k, 3, 2] = self.inl[0].m.val_SI + + # derivatives oxygen inlet + self.jacobian[k, 1, 0] = -(self.inl[1].h.val_SI - h_refo2) + self.jacobian[k, 1, 2] = -self.inl[1].m.val_SI + + # derivatives hydrogen inlet + self.jacobian[k, 2, 0] = -(self.inl[2].h.val_SI - h_refh2 - self.e0) + self.jacobian[k, 2, 2] = -self.inl[2].m.val_SI + + # derivatives for variable P + if self.P.is_var: + self.jacobian[k, 5 + self.P.var_pos, 0] = 1 + + def fluid_func(self): + r""" + Equations for fluid composition. + + Returns + ------- + residual : list + Residual values of equation. + + .. math:: + + 0 = x_\mathrm{i,in,1} - x_\mathrm{i,out,1} + \forall i \in \text{network fluids}\\ + 0 = \begin{cases} + 1 - x_\mathrm{i,in2} & \text{i=}H_{2}O\\ + x_\mathrm{i,in2} & \text{else} + \end{cases} \forall i \in \text{network fluids}\\ + 0 = \begin{cases} + 1 - x_\mathrm{i,out,2} & \text{i=}O_{2}\\ + x_\mathrm{i,out,2} & \text{else} + \end{cases} \forall i \in \text{network fluids}\\ + 0 = \begin{cases} + 1 - x_\mathrm{i,out,3} & \text{i=}H_{2}\\ + x_\mathrm{i,out,3} & \text{else} + \end{cases} \forall i \in \text{network fluids} + """ + residual = [] + # equations for fluid composition in cooling loop + for fluid, x in self.inl[0].fluid.val.items(): + residual += [x - self.outl[0].fluid.val[fluid]] + + # equations to constrain fluids to inlets/outlets + residual += [1 - self.inl[1].fluid.val[self.O2]] + residual += [1 - self.inl[2].fluid.val[self.H2]] + residual += [1 - self.outl[1].fluid.val[self.H2O]] + + # equations to ban other fluids off inlets/outlets + for fluid in self.inl[1].fluid.val.keys(): + if fluid != self.H2O: + residual += [0 - self.outl[1].fluid.val[fluid]] + if fluid != self.O2: + residual += [0 - self.inl[1].fluid.val[fluid]] + if fluid != self.H2: + residual += [0 - self.inl[2].fluid.val[fluid]] + + return residual + + def fluid_func_doc(self, label): + r""" + Equations for fluid composition. + + Parameters + ---------- + label : str + Label for equation. + + Returns + ------- + latex : str + LaTeX code of equations applied. + """ + latex = ( + r'\begin{split}' + '\n' + r'0 = &x_\mathrm{i,in,1} - x_\mathrm{i,out,1}\\' + '\n' + r'0 = &\begin{cases}' + '\n' + r'1 - x_\mathrm{i,out,2} & \text{i=}H_{2}O\\' + '\n' + r'x_\mathrm{i,out,2} & \text{else}\\' + '\n' + r'\end{cases}\\' + '\n' + r'0 =&\begin{cases}' + '\n' + r'1 - x_\mathrm{i,in,2} & \text{i=}O_{2}\\' + '\n' + r'x_\mathrm{i,in,2} & \text{else}\\' + '\n' + r'\end{cases}\\' + '\n' + r'0 =&\begin{cases}' + '\n' + r'1 - x_\mathrm{i,in,3} & \text{i=}H_{2}\\' + '\n' + r'x_\mathrm{i,in,3} & \text{else}\\' + '\n' + r'\end{cases}\\' + '\n' + r'&\forall i \in \text{network fluids}' + '\n' + r'\end{split}') + return generate_latex_eq(self, latex, label) + + def fluid_deriv(self): + r""" + Calculate the partial derivatives for cooling loop fluid balance. + + Returns + ------- + deriv : ndarray + Matrix with partial derivatives for the fluid equations. + """ + # derivatives for cooling fluid composition + deriv = np.zeros(( + self.num_nw_fluids * 4, + 5 + self.num_vars, + self.num_nw_vars)) + + k = 0 + for fluid, x in self.inl[0].fluid.val.items(): + deriv[k, 0, 3 + k] = 1 + deriv[k, 3, 3 + k] = -1 + k += 1 + + # derivatives to constrain fluids to inlets/outlets + i = 0 + for fluid in self.nw_fluids: + if fluid == self.H2O: + deriv[k, 4, 3 + i] = -1 + elif fluid == self.O2: + deriv[k + 1, 1, 3 + i] = -1 + elif fluid == self.H2: + deriv[k + 2, 2, 3 + i] = -1 + i += 1 + k += 3 + + # derivatives to ban fluids off inlets/outlets + i = 0 + for fluid in self.nw_fluids: + if fluid != self.H2O: + deriv[k, 4, 3 + i] = -1 + k += 1 + if fluid != self.O2: + deriv[k, 1, 3 + i] = -1 + k += 1 + if fluid != self.H2: + deriv[k, 2, 3 + i] = -1 + k += 1 + i += 1 + + return deriv + + def mass_flow_func(self): + r""" + Equations for mass conservation. + + Returns + ------- + residual : list + Residual values of equation. + + .. math:: + + O_2 = \frac{M_{O_2}}{M_{O_2} + 2 \cdot M_{H_2}}\\ + 0=O_2\cdot\dot{m}_\mathrm{H_{2}O,out,1}- + \dot{m}_\mathrm{O_2,in,2}\\ + 0 = \left(1 - O_2\right) \cdot \dot{m}_\mathrm{H_{2}O,out,1} - + \dot{m}_\mathrm{H_2,in,1} + """ + # calculate the ratio of o2 in water + o2 = molar_masses[self.O2] / ( + molar_masses[self.O2] + 2 * molar_masses[self.H2]) + # equation for mass flow balance cooling water + residual = [] + residual += [self.inl[0].m.val_SI - self.outl[0].m.val_SI] + # equations for mass flow balance of the fuel cell + residual += [o2 * self.outl[1].m.val_SI - self.inl[1].m.val_SI] + residual += [(1 - o2) * self.outl[1].m.val_SI - self.inl[2].m.val_SI] + return residual + + def mass_flow_func_doc(self, label): + r""" + Equations for mass conservation. + + Parameters + ---------- + label : str + Label for equation. + + Returns + ------- + latex : str + LaTeX code of equations applied. + """ + latex = ( + r'\begin{split}' + '\n' + r'O_2 = &\frac{M_{O_2}}{M_{O_2} + 2 \cdot M_{H_2}}\\' + '\n' + r'0=&O_2\cdot\dot{m}_\mathrm{H_{2}O,out,1}-' + r'\dot{m}_\mathrm{O_2,in,2}\\' + '\n' + r'0 =&\left(1 - O_2\right) \cdot \dot{m}_\mathrm{H_{2}O,out,2}-' + r'\dot{m}_\mathrm{H_2,in,3}\\' + '\n' + r'\end{split}' + ) + return generate_latex_eq(self, latex, label) + + def mass_flow_deriv(self): + r""" + Calculate the partial derivatives for all mass flow balance equations. + + Returns + ------- + deriv : ndarray + Matrix with partial derivatives for the mass flow equations. + """ + # derivatives for mass flow balance in the heat exchanger + deriv = np.zeros((3, 5 + self.num_vars, self.num_nw_vars)) + deriv[0, 0, 0] = 1 + deriv[0, 3, 0] = -1 + # derivatives for mass flow balance for oxygen input + o2 = molar_masses[self.O2] / ( + molar_masses[self.O2] + 2 * molar_masses[self.H2]) + deriv[1, 4, 0] = o2 + deriv[1, 1, 0] = -1 + # derivatives for mass flow balance for hydrogen input + deriv[2, 4, 0] = (1 - o2) + deriv[2, 2, 0] = -1 + + return deriv + + def reactor_pressure_func(self): + r""" + Equations for reactor pressure balance. + + Returns + ------- + residual : list + Residual values of equation. + + .. math:: + + 0 = p_\mathrm{in,2} - p_\mathrm{out,2}\\ + 0 = p_\mathrm{in,3} - p_\mathrm{out,2} + """ + return [ + self.outl[1].p.val_SI - self.inl[1].p.val_SI, + self.outl[1].p.val_SI - self.inl[2].p.val_SI] + + def reactor_pressure_func_doc(self, label): + r""" + Equations for reactor pressure balance. + + Parameters + ---------- + label : str + Label for equation. + + Returns + ------- + latex : str + LaTeX code of equations applied. + """ + latex = ( + r'\begin{split}' + '\n' + r'0 = & p_\mathrm{in,2} - p_\mathrm{out,2}\\' + '\n' + r'0 = & p_\mathrm{in,3} - p_\mathrm{out,2}\\' + '\n' + r'\end{split}') + return generate_latex_eq(self, latex, label) + + def reactor_pressure_deriv(self): + r""" + Calculate the partial derivatives for combustion pressure equations. + + Returns + ------- + deriv : ndarray + Matrix with partial derivatives for the pressure equations. + """ + deriv = np.zeros((2, 5 + self.num_vars, self.num_nw_vars)) + # derivatives for pressure oxygen inlet + deriv[0, 1, 1] = -1 + deriv[0, 4, 1] = 1 + # derivatives for pressure hydrogen inlet + deriv[1, 2, 1] = -1 + deriv[1, 4, 1] = 1 + + return deriv + + def calc_P(self): + r""" + Calculate fuel cell power output. + + Returns + ------- + P : float + Value of power output. + + .. math:: + + \begin{split} + P = & +\dot{m}_{in,2} \cdot \left( h_{in,2} - h_{in,2,ref} + \right)\\ + & + \dot{m}_{in,3} \cdot \left( h_{in,3} - h_{in,3,ref} - e_0 + \right)\\ + & - \dot{m}_{in,1} \cdot \left( h_{out,1} - h_{in,1} \right)\\ + & - \dot{m}_{out,2} \cdot \left( h_{out,2} - h_{out,2,ref} + \right)\\ + \end{split} + + Note + ---- + The temperature for the reference state is set to 25 °C, thus + the produced water must be liquid as proposed in the calculation of + the minimum specific energy for oxidation: + :py:meth:`tespy.components.reactors.fuel_cell.FuelCell.calc_e0`. + The part of the equation regarding the cooling water is implemented + with negative sign as the energy for cooling is extracted from the + reactor. + - Reference temperature: 298.15 K. + - Reference pressure: 1 bar. + """ + T_ref = 298.15 + p_ref = 1e5 + + # equations to set a reference point for each h2o, h2 and o2 + h_refh2o = h_mix_pT([1, p_ref, 0, self.outl[1].fluid.val], T_ref) + h_refh2 = h_mix_pT([1, p_ref, 0, self.inl[2].fluid.val], T_ref) + h_refo2 = h_mix_pT([1, p_ref, 0, self.inl[1].fluid.val], T_ref) + + val = ( + self.inl[2].m.val_SI * ( + self.inl[2].h.val_SI - h_refh2 - self.e0 + ) + + self.inl[1].m.val_SI * (self.inl[1].h.val_SI - h_refo2) + - self.inl[0].m.val_SI * ( + self.outl[0].h.val_SI - self.inl[0].h.val_SI + ) + - self.outl[1].m.val_SI * (self.outl[1].h.val_SI - h_refh2o) + ) + + return val + + def initialise_fluids(self): + # Set values to pure fluid on gas inlets and water outlet. + self.inl[1].fluid.val[self.O2] = 1 + self.inl[2].fluid.val[self.H2] = 1 + self.outl[1].fluid.val[self.H2O] = 1 + self.inl[1].source.propagate_fluid_to_source( + self.inl[1], self.inl[1].source) + self.inl[2].source.propagate_fluid_to_source( + self.inl[2], self.inl[2].source) + self.outl[1].target.propagate_fluid_to_target( + self.outl[1], self.outl[1].target) + + def initialise_source(self, c, key): + r""" + Return a starting value for pressure and enthalpy at inlet. + + Parameters + ---------- + c : tespy.connections.connection.Connection + Connection to perform initialisation on. + + key : str + Fluid property to retrieve. + + Returns + ------- + val : float + Starting value for pressure/enthalpy in SI units. + + .. math:: + + val = \begin{cases} + 5 \cdot 10^5 & \text{key = 'p'}\\ + h\left(T=293.15, p=5 \cdot 10^5\right) & \text{key = 'h'} + \end{cases} + """ + if key == 'p': + return 5e5 + elif key == 'h': + flow = c.get_flow() + T = 20 + 273.15 + return h_mix_pT(flow, T) + + def initialise_target(self, c, key): + r""" + Return a starting value for pressure and enthalpy at outlet. + + Parameters + ---------- + c : tespy.connections.connection.Connection + Connection to perform initialisation on. + + key : str + Fluid property to retrieve. + + Returns + ------- + val : float + Starting value for pressure/enthalpy in SI units. + + .. math:: + + val = \begin{cases} + 5 \cdot 10^5 & \text{key = 'p'}\\ + h\left(T=323.15, p=5 \cdot 10^5\right) & \text{key = 'h'} + \end{cases} + """ + if key == 'p': + return 5e5 + elif key == 'h': + flow = c.get_flow() + T = 50 + 273.15 + return h_mix_pT(flow, T) + + def propagate_fluid_to_target(self, inconn, start): + r""" + Propagate the fluids towards connection's target in recursion. + + Parameters + ---------- + inconn : tespy.connections.connection.Connection + Connection to initialise. + + start : tespy.components.component.Component + This component is the fluid propagation starting point. + The starting component is saved to prevent infinite looping. + """ + if inconn == self.inl[0]: + outconn = self.outl[0] + + for fluid, x in inconn.fluid.val.items(): + if (outconn.fluid.val_set[fluid] is False and + outconn.good_starting_values is False): + outconn.fluid.val[fluid] = x + + outconn.target.propagate_fluid_to_target(outconn, start) + + def propagate_fluid_to_source(self, outconn, start): + r""" + Propagate the fluids towards connection's source in recursion. + + Parameters + ---------- + outconn : tespy.connections.connection.Connection + Connection to initialise. + + start : tespy.components.component.Component + This component is the fluid propagation starting point. + The starting component is saved to prevent infinite looping. + """ + if outconn == self.outl[0]: + inconn = self.inl[0] + + for fluid, x in outconn.fluid.val.items(): + if (inconn.fluid.val_set[fluid] is False and + inconn.good_starting_values is False): + inconn.fluid.val[fluid] = x + + inconn.source.propagate_fluid_to_source(inconn, start) + + def calc_parameters(self): + r"""Postprocessing parameter calculation.""" + self.Q.val = - self.inl[0].m.val_SI * ( + self.outl[0].h.val_SI - self.inl[0].h.val_SI) + self.pr.val = self.outl[0].p.val_SI / self.inl[0].p.val_SI + self.e.val = self.P.val / self.inl[2].m.val_SI + self.eta.val = self.e.val / self.e0 + + i = self.inl[0].get_flow() + o = self.outl[0].get_flow() + self.zeta.val = ( + (i[1] - o[1]) * np.pi ** 2 / ( + 4 * i[0] ** 2 * + (self.inl[0].vol.val_SI + self.outl[0].vol.val_SI) + ) + ) diff --git a/src/tespy/components/reactors/water_electrolyzer.py b/src/tespy/components/reactors/water_electrolyzer.py index ae981d499..aa2a30c1a 100644 --- a/src/tespy/components/reactors/water_electrolyzer.py +++ b/src/tespy/components/reactors/water_electrolyzer.py @@ -27,8 +27,6 @@ from tespy.tools.global_vars import molar_masses from tespy.tools.helpers import TESPyComponentError -# %% - class WaterElectrolyzer(Component): r""" @@ -61,9 +59,15 @@ class WaterElectrolyzer(Component): Image - .. image:: _images/WaterElectrolyzer.svg - :alt: alternative text + .. image:: /api/_images/WaterElectrolyzer.svg + :alt: flowsheet of the water electrolyzer + :align: center + :class: only-light + + .. image:: /api/_images/WaterElectrolyzer_darkmode.svg + :alt: flowsheet of the water electrolyzer :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/components/turbomachinery/compressor.py b/src/tespy/components/turbomachinery/compressor.py index f9173c287..02bc41c86 100644 --- a/src/tespy/components/turbomachinery/compressor.py +++ b/src/tespy/components/turbomachinery/compressor.py @@ -51,9 +51,15 @@ class Compressor(Turbomachine): Image - .. image:: _images/Compressor.svg - :alt: alternative text + .. image:: /api/_images/Compressor.svg + :alt: flowsheet of the compressor :align: center + :class: only-light + + .. image:: /api/_images/Compressor_darkmode.svg + :alt: flowsheet of the compressor + :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/components/turbomachinery/pump.py b/src/tespy/components/turbomachinery/pump.py index 1fb6e0ab4..7335253e3 100644 --- a/src/tespy/components/turbomachinery/pump.py +++ b/src/tespy/components/turbomachinery/pump.py @@ -46,9 +46,15 @@ class Pump(Turbomachine): Image - .. image:: _images/Pump.svg - :alt: alternative text + .. image:: /api/_images/Pump.svg + :alt: flowsheet of the pump :align: center + :class: only-light + + .. image:: /api/_images/Pump_darkmode.svg + :alt: flowsheet of the pump + :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/components/turbomachinery/turbine.py b/src/tespy/components/turbomachinery/turbine.py index 386f9d908..8d363ab0f 100644 --- a/src/tespy/components/turbomachinery/turbine.py +++ b/src/tespy/components/turbomachinery/turbine.py @@ -47,9 +47,15 @@ class Turbine(Turbomachine): Image - .. image:: _images/Turbine.svg - :alt: alternative text + .. image:: /api/_images/Turbine.svg + :alt: flowsheet of the turbine :align: center + :class: only-light + + .. image:: /api/_images/Turbine_darkmode.svg + :alt: flowsheet of the turbine + :align: center + :class: only-dark Parameters ---------- diff --git a/src/tespy/connections/bus.py b/src/tespy/connections/bus.py index d81e74f38..05bb5687a 100644 --- a/src/tespy/connections/bus.py +++ b/src/tespy/connections/bus.py @@ -93,7 +93,7 @@ class Bus: >>> pu.set_attr(eta_s=0.8, design=['eta_s'], offdesign=['eta_s_char']) >>> amb_comb.set_attr(p=5, T=30, fluid={'Ar': 0.0129, 'N2': 0.7553, ... 'H2O': 0, 'CH4': 0, 'CO2': 0.0004, 'O2': 0.2314}) - >>> sf_comb.set_attr(m0=0.1, T=30, fluid={'CO2': 0, 'Ar': 0, 'N2': 0, + >>> sf_comb.set_attr(T=30, fluid={'CO2': 0, 'Ar': 0, 'N2': 0, ... 'O2': 0, 'H2O': 0, 'CH4': 1}) >>> cw_pu.set_attr(p=3, T=60, fluid={'CO2': 0, 'Ar': 0, 'N2': 0, ... 'O2': 0, 'H2O': 1, 'CH4': 0}) diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index 5998dd47f..214efe025 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -443,11 +443,11 @@ def set_attr(self, **kwargs): # reference object elif isinstance(kwargs[key], Ref): - if key in ['x', 'v', 'Td_bp']: + if key in ['x', 'Td_bp']: msg = ( - 'References for volumetric flow, vapor mass ' - 'fraction and subcooling/superheating are not ' - 'implemented.') + 'References for vapor mass fraction and ' + 'subcooling/superheating are not implemented.' + ) logging.error(msg) raise NotImplementedError(msg) else: diff --git a/src/tespy/data/__init__.py b/src/tespy/data/__init__.py deleted file mode 100644 index cf09fc14d..000000000 --- a/src/tespy/data/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# -*- coding: utf-8 diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 29b68ab91..1e71f5efe 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -17,7 +17,6 @@ import json import logging import os -from collections import Counter from collections import OrderedDict from time import time @@ -175,7 +174,10 @@ def set_defaults(self): # connection dataframe self.conns = pd.DataFrame( columns=['object', 'source', 'source_id', 'target', 'target_id'], - dtype='object') + dtype='object' + ) + # component dataframe + self.comps = pd.DataFrame(dtype='object') # user defined function dictionary for fast access self.user_defined_eq = {} # bus dictionary @@ -471,6 +473,7 @@ def add_conns(self, *args): logging.debug(msg) # set status "checked" to false, if connection is added to network. self.checked = False + self._add_comps(*args) def del_conns(self, *args): """ @@ -525,6 +528,40 @@ def check_conns(self): logging.error(msg) raise hlp.TESPyNetworkError(msg) + def _add_comps(self, *args): + r""" + Add to network's component DataFrame from added connections. + + Parameters + ---------- + c : tespy.connections.connection.Connection + The connections, which have been added to the network. The + components are extracted from these information. + """ + # get unique components in new connections + comps = list(set([cp for c in args for cp in [c.source, c.target]])) + # add to the dataframe of components + for comp in comps: + if comp.label in self.comps.index: + if self.comps.loc[comp.label, 'object'] == comp: + continue + else: + comp_type = comp.__class__.__name__ + other_obj = self.comps.loc[comp.label, "object"] + other_comp_type = other_obj.__class__.__name__ + msg = ( + f"The component with the label {comp.label} of type " + f"{comp_type} cannot be added to the network as a " + f"different component of type {other_comp_type} with " + "the same label has already been added. All " + "components must have unique values!" + ) + raise hlp.TESPyNetworkError(msg) + + comp_type = comp.__class__.__name__ + self.comps.loc[comp.label, 'comp_type'] = comp_type + self.comps.loc[comp.label, 'object'] = comp + def add_ude(self, *args): r""" Add a user defined function to the network. @@ -644,21 +681,21 @@ def check_network(self): if len(self.conns) == 0: msg = ( 'No connections have been added to the network, please make ' - 'sure to add your connections with the .add_conns() method.') + 'sure to add your connections with the .add_conns() method.' + ) logging.error(msg) raise hlp.TESPyNetworkError(msg) if len(self.fluids) == 0: - msg = ('Network has no fluids, please specify a list with fluids ' - 'on network creation.') + msg = ( + 'Network has no fluids, please specify a list with fluids on ' + 'network creation.' + ) logging.error(msg) raise hlp.TESPyNetworkError(msg) self.check_conns() - # get unique components in connections dataframe - comps = pd.unique(self.conns[['source', 'target']].values.ravel()) - # build the dataframe for components - self.init_components(comps) + self.init_components() # count number of incoming and outgoing connections and compare to # expected values for comp in self.comps['object']: @@ -686,32 +723,9 @@ def check_network(self): msg = 'Networkcheck successful.' logging.info(msg) - def init_components(self, comps): - r""" - Set up a dataframe for the network's components. - - Additionally, check, if all components have unique labels. - - Parameters - ---------- - comps : pandas.core.frame.DataFrame - DataFrame containing all components of the network gathered from - the network's connection information. - - Note - ---- - The dataframe for the components is derived from the network's - connections. Thus it does not hold any additional information, the - dataframe is used to simplify the code, only. - """ - self.comps = pd.DataFrame(dtype='object') - - labels = [] - for comp in comps: - # this is required for printing and saving - comp_type = comp.__class__.__name__ - self.comps.loc[comp, 'comp_type'] = comp_type - self.comps.loc[comp, 'label'] = comp.label + def init_components(self): + r"""Set up necessary component information.""" + for comp in self.comps["object"]: # get incoming and outgoing connections of a component sources = self.conns[self.conns['source'] == comp] sources = sources['source_id'].sort_values().index.tolist() @@ -723,13 +737,14 @@ def init_components(self, comps): comp.outl = self.conns.loc[sources, 'object'].tolist() comp.num_i = len(comp.inlets()) comp.num_o = len(comp.outlets()) - labels += [comp.label] # save the connection locations to the components comp.conn_loc = [] for c in comp.inl + comp.outl: comp.conn_loc += [self.conns.index.get_loc(c.label)] + # set up restults and specification dataframes + comp_type = comp.__class__.__name__ if comp_type not in self.results: cols = [col for col, data in comp.variables.items() if isinstance(data, dc_cp)] @@ -751,18 +766,6 @@ def init_components(self, comps): 'properties': pd.DataFrame(columns=cols, dtype='bool') } - self.comps = self.comps.reset_index().set_index('label') - self.comps.rename(columns={'index': 'object'}, inplace=True) - - # check for duplicates in the component labels - if len(labels) != len(list(set(labels))): - duplicates = [ - item for item, count in Counter(labels).items() if count > 1] - msg = ('All Components must have unique labels, duplicate labels ' - 'are: "' + '", "'.join(duplicates) + '".') - logging.error(msg) - raise hlp.TESPyNetworkError(msg) - def initialise(self): r""" Initilialise the network depending on calclation mode. @@ -1464,9 +1467,10 @@ def init_val0(self, c, key): Connection to initialise. """ if np.isnan(c.get_attr(key).val0): - # starting value for mass flow is 1 kg/s + # starting value for mass flow is random between 1 and 2 kg/s + # (should be generated based on some hash maybe?) if key == 'm': - c.get_attr(key).val0 = 1 + c.get_attr(key).val0 = np.random.random() + 1 # generic starting values for pressure and enthalpy else: @@ -2380,6 +2384,37 @@ def solve_connections(self): fp.dv_mix_pdh(flow, T0=c.T.val_SI) * c.m.val_SI) k += 1 + # referenced volumetric flow + if c.v.ref_set: + ref = c.v.ref + flow_ref = ref.obj.get_flow() + ref_col = ref.obj.conn_loc * self.num_conn_vars + v = fp.v_mix_ph(flow, T0=c.T.val_SI) + v_ref = fp.v_mix_ph(flow_ref, T0=ref.obj.T.val_SI) + self.residual[k] = ( + (v * c.m.val_SI) + - ((v_ref * ref.obj.m.val_SI) * ref.factor + ref.delta_SI) + ) + + self.jacobian[k, col] = v + self.jacobian[k, col + 1] = ( + fp.dv_mix_dph(flow, T0=c.T.val_SI) * c.m.val_SI + ) + self.jacobian[k, col + 2] = ( + fp.dv_mix_pdh(flow, T0=c.T.val_SI) * c.m.val_SI + ) + + self.jacobian[k, ref_col] = -v_ref * ref.factor + self.jacobian[k, ref_col + 1] = -( + fp.dv_mix_dph(flow_ref, T0=ref.obj.T.val_SI) + * ref.factor * ref.obj.m.val_SI + ) + self.jacobian[k, ref_col + 2] = -( + fp.dv_mix_pdh(flow_ref, T0=ref.obj.T.val_SI) + * ref.factor * ref.obj.m.val_SI + ) + k += 1 + # temperature difference to boiling point if c.Td_bp.val_set: if (np.absolute(self.residual[k]) > err ** 2 or @@ -2595,9 +2630,12 @@ def print_results(self, colored=True, colors={}): if len(df) > 0: # printout with tabulate print('##### RESULTS (' + cp + ') #####') - print(tabulate( - df, headers='keys', tablefmt='psql', - floatfmt='.2e')) + print( + tabulate( + df, headers='keys', tablefmt='psql', + floatfmt='.2e' + ) + ) # connection properties df = self.results['Connection'].loc[:, ['m', 'p', 'h', 'T']] @@ -2616,7 +2654,8 @@ def print_results(self, colored=True, colors={}): if len(df) > 0: print('##### RESULTS (Connection) #####') print( - tabulate(df, headers='keys', tablefmt='psql', floatfmt='.3e')) + tabulate(df, headers='keys', tablefmt='psql', floatfmt='.3e') + ) for b in self.busses.values(): if b.printout: @@ -2629,8 +2668,12 @@ def print_results(self, colored=True, colors={}): coloring['set'] + str(df.loc['total', 'bus value']) + coloring['end']) print('##### RESULTS (Bus: ' + b.label + ') #####') - print(tabulate(df, headers='keys', tablefmt='psql', - floatfmt='.3e')) + print( + tabulate( + df, headers='keys', tablefmt='psql', + floatfmt='.3e' + ) + ) def print_components(self, c, *args): """ diff --git a/src/tespy/tools/__init__.py b/src/tespy/tools/__init__.py index 603fa8b93..269fb1a9f 100644 --- a/src/tespy/tools/__init__.py +++ b/src/tespy/tools/__init__.py @@ -13,3 +13,4 @@ from .data_containers import FluidProperties # noqa: F401 from .data_containers import GroupedComponentProperties # noqa: F401 from .document_models import document_model # noqa: F401 +from .optimization import OptimizationProblem # noqa: F401 diff --git a/src/tespy/tools/analyses.py b/src/tespy/tools/analyses.py index 82784cab6..4926075e6 100644 --- a/src/tespy/tools/analyses.py +++ b/src/tespy/tools/analyses.py @@ -24,8 +24,6 @@ from tespy.tools import helpers as hlp from tespy.tools.global_vars import err -# %% - class ExergyAnalysis: r"""Class for exergy analysis of TESPy models.""" diff --git a/src/tespy/tools/characteristics.py b/src/tespy/tools/characteristics.py index 53f02c253..75bfa413a 100644 --- a/src/tespy/tools/characteristics.py +++ b/src/tespy/tools/characteristics.py @@ -19,9 +19,8 @@ import os import numpy as np -from matplotlib import pyplot as plt -from pkg_resources import resource_filename +from tespy import __datapath__ from tespy.tools.helpers import extend_basic_path # %% @@ -170,6 +169,8 @@ def get_attr(self, key): def plot(self, path, title, xlabel, ylabel): + from matplotlib import pyplot as plt + # plotting fig = plt.figure() ax = plt.subplot() @@ -446,6 +447,8 @@ def get_attr(self, key): def plot(self, path, title, xlabel, ylabel): + from matplotlib import pyplot as plt + # plotting fig = plt.figure() ax = plt.subplot() @@ -486,9 +489,9 @@ def load_default_char(component, parameter, function_name, char_type): The characteristics (CharLine, CharMap) object. """ if char_type == CharLine: - path = resource_filename('tespy.data', 'char_lines.json') + path = __datapath__ + 'char_lines.json' else: - path = resource_filename('tespy.data', 'char_maps.json') + path = __datapath__ + 'char_maps.json' with open(path) as f: data = json.loads(f.read()) diff --git a/src/tespy/tools/helpers.py b/src/tespy/tools/helpers.py index 5d86ce5fe..d16858297 100644 --- a/src/tespy/tools/helpers.py +++ b/src/tespy/tools/helpers.py @@ -10,7 +10,6 @@ """ import logging import os - from collections import OrderedDict from collections.abc import Mapping from copy import deepcopy @@ -39,10 +38,12 @@ def merge_dicts(dict1, dict2): def nested_OrderedDict(dictionary): """Create a nested OrderedDict from a nested dict. + Parameters ---------- dictionary : dict Nested dict. + Returns ------- dictionary : collections.OrderedDict diff --git a/src/tespy/tools/optimization.py b/src/tespy/tools/optimization.py new file mode 100644 index 000000000..0c6014ae2 --- /dev/null +++ b/src/tespy/tools/optimization.py @@ -0,0 +1,307 @@ +try: + import pygmo as pg +except ImportError: + pg = None + +import pandas as pd + +from tespy.tools.helpers import merge_dicts +from tespy.tools.helpers import nested_OrderedDict + + +class OptimizationProblem: + r""" + The OptimizationProblem handles the optimization. + + - Set up the optimization problems by specifying constraints, upper and + lower bounds for the decision variables and selection of the objective + function. + - Run the optimization, see + :py:meth:`tespy.tools.optimization.OptimizationProblem.run`. + - Provide the optimization results DataFrame in the + :code:`.individuals` attribute of the :code:`OptimizationProblem` class. + + Parameters + ---------- + model : custom class + Object of some class, which provides all the methods required by the + optimization suite, see the Example section for a downloadable + template of the implementation. + + variables : dict + Dictionary containing the decision variables and their respective + bounds. + + constraints : dict + Dictionary containing the constraints for the model. + + objective : str + Name of the objective. :code:`objective` is passed to the + :code:`get_objective` method of your tespy model instance. + + Note + ---- + For the required structure of the input dictionaries see the example in + below. + + Installation of pygmo via pip is not available for Windows and OSX users + currently. Please use conda instead or refer to their + `documentation `_. + + Example + ------- + For an example please go to the tutorials section of TESPy's online + documentation. + """ + + def __init__(self, model, variables={}, constraints={}, objective="objective"): + if pg is None: + msg = ( + "For this function of TESPy pygmo has to be installed. Either" + " use pip (Linux users only) or conda to install the latest" + " pygmo version." + ) + raise ImportError(msg) + + self.model = model + default_variables = {"Connections": {}, "Components": {}} + default_constraints = { + "lower limits": {"Connections": {}, "Components": {}}, + "upper limits": {"Connections": {}, "Components": {}} + } + # merge the passed values into the default dictionary structure + variables = merge_dicts(variables, default_variables) + constraints = merge_dicts(constraints, default_constraints) + + # pygmo creates a vector for the variables and constraints, which has + # to be in consistent order. Therefore use OrderedDicts instead of + # dictionaries + self.variables = nested_OrderedDict(variables) + self.constraints = nested_OrderedDict(constraints) + self.objective = objective + self.variable_list = [] + self.constraint_list = [] + + self.objective_list = [objective] + self.nobj = len(self.objective_list) + + self.bounds = [[], []] + for obj, data in self.variables.items(): + for label, params in data.items(): + if obj in ["Connections", "Components"]: + for param in params: + self.bounds[0] += [ + self.variables[obj][label][param]['min'] + ] + self.bounds[1] += [ + self.variables[obj][label][param]['max'] + ] + self.variable_list += [obj + '-' + label + '-' + param] + else: + self.bounds[0] += [self.variables[obj][label]['min']] + self.bounds[1] += [self.variables[obj][label]['max']] + self.variable_list += [obj + '-' + label] + + self.input_dict = self.variables.copy() + + self.nic = 0 + self.collect_constraints("upper", build=True) + self.collect_constraints("lower", build=True) + + def collect_constraints(self, border, build=False): + """Collect the constraints + + Parameters + ---------- + border : str + "upper" or "lower", determine which constraints to collect. + build : bool, optional + If True, the constraints are evaluated and returned, by default + False + + Returns + ------- + tuple + Return the upper and lower constraints evaluation lists. + """ + evaluation = [] + for obj, data in self.constraints[f'{border} limits'].items(): + for label, constraints in data.items(): + for param, constraint in constraints.items(): + # to build the equations + if build: + self.nic += 1 + if isinstance(constraint, str): + right_side = '-'.join(self.constraints[constraint]) + else: + right_side = str(constraint) + + direction = '>=' if border == 'lower' else '<=' + self.constraint_list += [ + obj + '-' + label + '-' + param + direction + + right_side + ] + # to get the constraints evaluation + else: + if isinstance(constraint, str): + c = ( + self.model.get_param( + *self.constraints[constraint] + ) - self.model.get_param(obj, label, param) + ) + else: + c = ( + constraint - + self.model.get_param(obj, label, param) + ) + if border == 'lower': + evaluation += [c] + else: + evaluation += [-c] + + if build: + return None + else: + return evaluation + + def fitness(self, x): + """Evaluate the fitness function of an individual. + + Parameters + ---------- + x : list + List of the decision variables' values of the current individual. + + Returns + ------- + fitness : list + A list containing the fitness function evaluation as well as the + evaluation of the upper and lower constraints. + """ + i = 0 + for obj, data in self.variables.items(): + for label, params in data.items(): + if obj in ["Connections", "Components"]: + for param in params: + self.input_dict[obj][label][param] = x[i] + i += 1 + else: + self.input_dict[obj][label] = x[i] + i += 1 + + self.model.solve_model(**self.input_dict) + f1 = [self.model.get_objective(self.objective)] + + cu = self.collect_constraints("upper") + cl = self.collect_constraints("lower") + + return f1 + cu + cl + + def get_nobj(self): + """Return number of objectives.""" + return self.nobj + + # inequality constraints (equality constraints not required) + def get_nic(self): + """Return number of inequality constraints.""" + return self.nic + + def get_bounds(self): + """Return bounds of decision variables.""" + return self.bounds + + def _process_generation_data(self, gen, pop): + """Process the data of the individuals within one generation. + + Parameters + ---------- + gen : int + Generation number. + + pop : pygmo.population + PyGMO population object. + """ + individual = 0 + for x in pop.get_x(): + self.individuals.loc[(gen, individual), self.variable_list] = x + individual += 1 + + individual = 0 + for objective in pop.get_f(): + self.individuals.loc[ + (gen, individual), + self.objective_list + self.constraint_list + ] = objective + individual += 1 + + self.individuals['valid'] = ( + self.individuals[self.constraint_list] < 0 + ).all(axis='columns') + + def run(self, algo, pop, num_ind, num_gen): + """Run the optimization algorithm. + + Parameters + ---------- + algo : pygmo.core.algorithm + PyGMO optimization algorithm. + + pop : pygmo.core.population + PyGMO population. + + num_ind : int + Number of individuals. + + num_gen : int + Number of generations. + """ + + self.individuals = pd.DataFrame( + index=range(num_gen * num_ind) + ) + + self.individuals["gen"] = [ + gen for gen in range(num_gen) for ind in range(num_ind) + ] + self.individuals["ind"] = [ + ind for gen in range(num_gen) for ind in range(num_ind) + ] + + self.individuals.set_index(["gen", "ind"], inplace=True) + + # replace prints with logging + gen = 0 + for gen in range(num_gen - 1): + self._process_generation_data(gen, pop) + + print('Evolution: {}'.format(gen)) + for i in range(len(self.objective_list)): + print( + self.objective_list[i] + ': {}'.format( + round(pop.champion_f[i], 4) + ) + ) + for i in range(len(self.variable_list)): + print( + self.variable_list[i] + ': {}'.format( + round(pop.champion_x[i], 4) + ) + ) + pop = algo.evolve(pop) + + gen += 1 + self._process_generation_data(gen, pop) + + print('Final evolution: {}'.format(gen)) + for i in range(len(self.objective_list)): + print( + self.objective_list[i] + ': {}'.format( + round(pop.champion_f[i], 4) + ) + ) + for i in range(len(self.variable_list)): + print( + self.variable_list[i] + ': {}'.format( + round(pop.champion_x[i], 4) + ) + ) diff --git a/tests/test_connections.py b/tests/test_connections.py new file mode 100644 index 000000000..94a281298 --- /dev/null +++ b/tests/test_connections.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 + +"""Module for testing busses. + +This file is part of project TESPy (github.com/oemof/tespy). It's copyrighted +by the contributors recorded in the version control history of the file, +available from its original location +tests/test_busses.py + +SPDX-License-Identifier: MIT +""" + +from tespy.components import Sink +from tespy.components import Source +from tespy.connections import Connection +from tespy.connections import Ref +from tespy.networks import Network + + +class TestConnections: + + def setup(self): + """Set up the model.""" + # %% network setup + fluid_list = ['Air'] + self.nw = Network( + fluids=fluid_list, p_unit='bar', T_unit='C', p_range=[0.5, 20]) + + # %% components + so1 = Source('source 1') + so2 = Source('source 2') + si1 = Sink('sink 1') + si2 = Sink('sink 2') + + # %% connections + c1 = Connection(so1, 'out1', si1, 'in1', label='Some example label') + c2 = Connection(so2, 'out1', si2, 'in1') + + self.nw.add_conns(c1, c2) + + # %% component parameters + c1.set_attr(m=1, p=1, T=25, fluid={'Air': 1}) + c2.set_attr(m=0.5, p=10, T=25, fluid={'Air': 1}) + + # %% solving + self.nw.solve('design') + + def test_volumetric_flow_reference(self): + """Test the referenced volumetric flow.""" + c1, c2 = self.nw.get_conn( + ['Some example label', 'source 2:out1_sink 2:in1'] + ) + c2.set_attr(m=None, v=Ref(c1, 1, 0)) + + self.nw.solve('design') + + # expected result: mass flow of second connection is lower by + # the fraction of the specific volumes + + m_expected = round(c1.m.val * c1.vol.val / c2.vol.val, 4) + m_is = round(c2.m.val, 4) + msg = ( + 'The mass flow of the connection 2 should be equal to ' + f'{m_expected} kg/s, but is {m_is} kg/s' + ) + assert m_is == m_expected, msg diff --git a/tests/test_errors.py b/tests/test_errors.py index f7fe16673..58a516b7d 100644 --- a/tests/test_errors.py +++ b/tests/test_errors.py @@ -129,6 +129,7 @@ def test_set_attr_errors(): # NotImplementedError set_attr_NotImplementedError(conn, Td_bp=Ref(conn, 1, 0)) + set_attr_NotImplementedError(conn, x=Ref(conn, 1, 0)) def test_get_attr_errors(): @@ -514,9 +515,8 @@ def test_component_label_duplicates(self): source = Source('label') sink = Sink('label') a = Connection(source, 'out1', sink, 'in1') - self.nw.add_conns(a) with raises(TESPyNetworkError): - self.nw.check_network() + self.nw.add_conns(a) def test_missing_offdesign_path(self): source = Source('source') diff --git a/tests/test_models/test_heat_pump_model.py b/tests/test_models/test_heat_pump_model.py index 7bc582384..58e3ebd47 100644 --- a/tests/test_models/test_heat_pump_model.py +++ b/tests/test_models/test_heat_pump_model.py @@ -38,7 +38,7 @@ def setup(self): # %% components # sources & sinks - cc_coolant = CycleCloser('coolant cycle closer') + cc_refrigerant = CycleCloser('refrigerant cycle closer') cc_consumer = CycleCloser('consumer cycle closer') amb_in = Source('source ambient') amb_out = Sink('sink ambient') @@ -73,7 +73,7 @@ def setup(self): # %% connections # consumer system - c_in_cd = Connection(cc_coolant, 'out1', cd, 'in1') + c_in_cd = Connection(cc_refrigerant, 'out1', cd, 'in1') cb_rp = Connection(cc_consumer, 'out1', rp, 'in1') rp_cd = Connection(rp, 'out1', cd, 'in2') @@ -110,7 +110,7 @@ def setup(self): # compressor-system cp1_he = Connection(cp1, 'out1', he, 'in1') he_cp2 = Connection(he, 'out1', cp2, 'in1') - cp2_c_out = Connection(cp2, 'out1', cc_coolant, 'in1') + cp2_c_out = Connection(cp2, 'out1', cc_refrigerant, 'in1') ic_in_he = Connection(ic_in, 'out1', he, 'in2') he_ic_out = Connection(he, 'out2', ic_out, 'in1') diff --git a/tests/test_networks/test_network.py b/tests/test_networks/test_network.py index ab856c3dc..cdfb519ad 100644 --- a/tests/test_networks/test_network.py +++ b/tests/test_networks/test_network.py @@ -253,6 +253,33 @@ def test_Network_missing_connection_in_design_path(self): shutil.rmtree('./tmp', ignore_errors=True) + def test_Network_get_comp_without_connections_added(self): + """Test if components are found prior to initialization.""" + self.setup_Network_tests() + pi = Pipe('pipe') + a = Connection(self.source, 'out1', pi, 'in1') + Connection(pi, 'out1', self.sink, 'in1') + self.nw.add_conns(a) + msg = ( + "A component with the label 'sink' has been created but must not " + "be part of the network as the respective connection has not " + "been added." + ) + assert self.nw.get_comp("sink") is None, msg + + def test_Network_get_comp_before_initialization(self): + """Test if components are found prior to initialization.""" + self.setup_Network_tests() + pi = Pipe('pipe') + a = Connection(self.source, 'out1', pi, 'in1') + b = Connection(pi, 'out1', self.sink, 'in1') + self.nw.add_conns(a, b) + msg = ( + "A component with the label 'pipe' is part of the network " + "and therefore must be found in the DataFrame." + ) + assert self.nw.get_comp("pipe") == pi, msg + class TestNetworkIndividualOffdesign: diff --git a/tests/test_tools/test_characteristics.py b/tests/test_tools/test_characteristics.py index a862eedc6..7bbdb3ef1 100644 --- a/tests/test_tools/test_characteristics.py +++ b/tests/test_tools/test_characteristics.py @@ -14,8 +14,8 @@ import shutil import numpy as np -from pkg_resources import resource_filename +from tespy import __datapath__ from tespy.tools.characteristics import CharLine from tespy.tools.characteristics import CharMap from tespy.tools.characteristics import load_custom_char @@ -27,7 +27,7 @@ def test_custom_CharLine_import(): """Test importing a custom characteristc lines.""" # we need to write some data to the path first, using defaults - data_path = resource_filename('tespy.data', 'char_lines.json') + data_path = __datapath__ + 'char_lines.json' path = extend_basic_path('data') tmp_path = extend_basic_path('tmp_dir_for_testing') @@ -75,7 +75,7 @@ def test_custom_CharMap_import(): """Test importing a custom characteristc map.""" # we need to write some data to the path first, using defaults - data_path = resource_filename('tespy.data', 'char_maps.json') + data_path = __datapath__ + 'char_maps.json' path = extend_basic_path('data') tmp_path = extend_basic_path('tmp_dir_for_testing') diff --git a/tox.ini b/tox.ini index 31df49f36..a4bfe0c05 100644 --- a/tox.ini +++ b/tox.ini @@ -5,16 +5,20 @@ envlist = docs, py37, py38, + py39, + py310, report [gh-actions] python = 3.7: py37 3.8: py38 + 3.9: py39 + 3.10: py310 [testenv] basepython = - docs: {env:TOXPYTHON:python3.8} + docs: {env:TOXPYTHON:python3.10} {bootstrap,clean,check,report,codecov,coveralls}: {env:TOXPYTHON:python3} setenv = PYTHONPATH={toxinidir}/tests @@ -106,3 +110,25 @@ commands = deps = {[testenv]deps} pytest-cov + +[testenv:py39] +basepython = {env:TOXPYTHON:python3.9} +setenv = + {[testenv]setenv} +usedevelop = true +commands = + {posargs:pytest --cov --cov-report=term-missing -vv} +deps = + {[testenv]deps} + pytest-cov + +[testenv:py310] +basepython = {env:TOXPYTHON:python3.10} +setenv = + {[testenv]setenv} +usedevelop = true +commands = + {posargs:pytest --cov --cov-report=term-missing -vv} +deps = + {[testenv]deps} + pytest-cov diff --git a/tutorial/advanced/optimization_example.py b/tutorial/advanced/optimization_example.py new file mode 100644 index 000000000..9c5b12689 --- /dev/null +++ b/tutorial/advanced/optimization_example.py @@ -0,0 +1,297 @@ +# %%[sec_1] +import numpy as np +import pygmo as pg + +from tespy.components import CycleCloser +from tespy.components import Sink +from tespy.components import Source +from tespy.components import Condenser +from tespy.components import Desuperheater +from tespy.components import HeatExchangerSimple +from tespy.components import Merge +from tespy.components import Splitter +from tespy.components import Valve +from tespy.components import Pump +from tespy.components import Turbine +from tespy.connections import Bus +from tespy.connections import Connection +from tespy.networks import Network + +from tespy.tools.optimization import OptimizationProblem + + +class SamplePlant: + """Class template for TESPy model usage in optimization module.""" + def __init__(self): + + self.nw = Network(fluids=["water"]) + self.nw.set_attr( + p_unit="bar", T_unit="C", h_unit="kJ / kg", iterinfo=False + ) + # components + # main cycle + sg = HeatExchangerSimple("steam generator") + cc = CycleCloser("cycle closer") + hpt = Turbine("high pressure turbine") + sp1 = Splitter("splitter 1", num_out=2) + mpt = Turbine("mid pressure turbine") + sp2 = Splitter("splitter 2", num_out=2) + lpt = Turbine("low pressure turbine") + con = Condenser("condenser") + pu1 = Pump("feed water pump") + fwh1 = Condenser("feed water preheater 1") + fwh2 = Condenser("feed water preheater 2") + dsh = Desuperheater("desuperheater") + me2 = Merge("merge2", num_in=2) + pu2 = Pump("feed water pump 2") + pu3 = Pump("feed water pump 3") + me = Merge("merge", num_in=2) + + # cooling water + cwi = Source("cooling water source") + cwo = Sink("cooling water sink") + + # connections + # main cycle + c0 = Connection(sg, "out1", cc, "in1", label="0") + c1 = Connection(cc, "out1", hpt, "in1", label="1") + c2 = Connection(hpt, "out1", sp1, "in1", label="2") + c3 = Connection(sp1, "out1", mpt, "in1", label="3", state="g") + c4 = Connection(mpt, "out1", sp2, "in1", label="4") + c5 = Connection(sp2, "out1", lpt, "in1", label="5") + c6 = Connection(lpt, "out1", con, "in1", label="6") + c7 = Connection(con, "out1", pu1, "in1", label="7", state="l") + c8 = Connection(pu1, "out1", fwh1, "in2", label="8", state="l") + c9 = Connection(fwh1, "out2", me, "in1", label="9", state="l") + c10 = Connection(me, "out1", fwh2, "in2", label="10", state="l") + c11 = Connection(fwh2, "out2", dsh, "in2", label="11", state="l") + c12 = Connection(dsh, "out2", me2, "in1", label="12", state="l") + c13 = Connection(me2, "out1", sg, "in1", label="13", state="l") + + self.nw.add_conns( + c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13 + ) + + # preheating + c21 = Connection(sp1, "out2", dsh, "in1", label="21") + c22 = Connection(dsh, "out1", fwh2, "in1", label="22") + c23 = Connection(fwh2, "out1", pu2, "in1", label="23") + c24 = Connection(pu2, "out1", me2, "in2", label="24") + + c31 = Connection(sp2, "out2", fwh1, "in1", label="31") + c32 = Connection(fwh1, "out1", pu3, "in1", label="32") + c33 = Connection(pu3, "out1", me, "in2", label="33") + + self.nw.add_conns( + c21, c22, c23, c24, + c31, c32, c33 + ) + + # cooling water + c41 = Connection(cwi, "out1", con, "in2", label="41") + c42 = Connection(con, "out2", cwo, "in1", label="42") + + self.nw.add_conns(c41, c42) + + # busses + # power bus + self.power = Bus("power") + self.power.add_comps( + {"comp": hpt, "char": -1}, {"comp": mpt, "char": -1}, + {"comp": lpt, "char": -1}, {"comp": pu1, "char": -1}, + {"comp": pu2, "char": -1}, {"comp": pu3, "char": -1} + ) + + # heating bus + self.heat = Bus("heat") + self.heat.add_comps({"comp": sg, "char": 1}) + + self.nw.add_busses(self.power, self.heat) + + # parametrization + # components + hpt.set_attr(eta_s=0.9) + mpt.set_attr(eta_s=0.9) + lpt.set_attr(eta_s=0.9) + + pu1.set_attr(eta_s=0.8) + pu2.set_attr(eta_s=0.8) + pu3.set_attr(eta_s=0.8) + + sg.set_attr(pr=0.92) + + con.set_attr(pr1=1, pr2=0.99, ttd_u=5) + fwh1.set_attr(pr1=1, pr2=0.99, ttd_u=5) + fwh2.set_attr(pr1=1, pr2=0.99, ttd_u=5) + dsh.set_attr(pr1=0.99, pr2=0.99) + + c1.set_attr(m=200, T=650, p=100, fluid={"water": 1}) + c2.set_attr(p=20) + c4.set_attr(p=3) + + c41.set_attr(T=20, p=3, fluid={"water": 1}) + c42.set_attr(T=28) + + self.nw.solve("design") + self.stable = "_stable" + self.nw.save(self.stable) + self.solved = True + + # %%[sec_2] + + def get_param(self, obj, label, parameter): + """Get the value of a parameter in the network"s unit system. + + Parameters + ---------- + obj : str + Object to get parameter for (Components/Connections). + + label : str + Label of the object in the TESPy model. + + parameter : str + Name of the parameter of the object. + + Returns + ------- + value : float + Value of the parameter. + """ + if obj == "Components": + return self.nw.get_comp(label).get_attr(parameter).val + elif obj == "Connections": + return self.nw.get_conn(label).get_attr(parameter).val + + def set_params(self, **kwargs): + + if "Connections" in kwargs: + for c, params in kwargs["Connections"].items(): + self.nw.get_conn(c).set_attr(**params) + + if "Components" in kwargs: + for c, params in kwargs["Components"].items(): + self.nw.get_comp(c).set_attr(**params) + + def solve_model(self, **kwargs): + """ + Solve the TESPy model given the the input parameters + """ + self.set_params(**kwargs) + + self.solved = False + try: + self.nw.solve("design") + if self.nw.res[-1] >= 1e-3 or self.nw.lin_dep: + self.nw.solve("design", init_only=True, init_path=self.stable) + else: + # might need more checks here! + if ( + any(self.nw.results["Condenser"]["Q"] > 0) + or any(self.nw.results["Desuperheater"]["Q"] > 0) + or any(self.nw.results["Turbine"]["P"] > 0) + or any(self.nw.results["Pump"]["P"] < 0) + ): + self.solved = False + else: + self.solved = True + except ValueError as e: + self.nw.lin_dep = True + self.nw.solve("design", init_only=True, init_path=self.stable) + + def get_objective(self, objective=None): + """ + Get the current objective function evaluation. + + Parameters + ---------- + objective : str + Name of the objective function. + + Returns + ------- + objective_value : float + Evaluation of the objective function. + """ + if self.solved: + if objective == "efficiency": + return 1 / ( + self.nw.busses["power"].P.val / + self.nw.busses["heat"].P.val + ) + else: + msg = f"Objective {objective} not implemented." + raise NotImplementedError(msg) + else: + return np.nan + + # %%[sec_3] + +plant = SamplePlant() +plant.get_objective("efficiency") +variables = { + "Connections": { + "2": {"p": {"min": 1, "max": 40}}, + "4": {"p": {"min": 1, "max": 40}} + } +} +constraints = { + "lower limits": { + "Connections": { + "2": {"p": "ref1"} + }, + }, + "ref1": ["Connections", "4", "p"] +} + +optimize = OptimizationProblem( + plant, variables, constraints, objective="efficiency" +) +# %%[sec_4] +num_ind = 10 +num_gen = 100 + +# for algorithm selection and parametrization please consider the pygmo +# documentation! The number of generations indicated in the algorithm is +# the number of evolutions we undertake within each generation defined in +# num_gen +algo = pg.algorithm(pg.ihs(gen=3, seed=42)) +# create starting population +pop = pg.population(pg.problem(optimize), size=num_ind, seed=42) + +optimize.run(algo, pop, num_ind, num_gen) +# %%[sec_5] +# To access the results +print(optimize.individuals) +# check pygmo documentation to see, what you can get from the population +pop +# plot the results +import matplotlib.pyplot as plt + + +# make text reasonably sized +plt.rc("font", **{"size": 18}) + +fig, ax = plt.subplots(1, figsize=(16, 8)) + +filter_valid_constraint = optimize.individuals["valid"].values +filter_valid_result = ~np.isnan(optimize.individuals["efficiency"].values) +data = optimize.individuals.loc[filter_valid_constraint & filter_valid_result] + +sc = ax.scatter( + data["Connections-2-p"], + data["Connections-4-p"], + c=1 / data["efficiency"] * 100, + s=100 +) +cbar = plt.colorbar(sc) +cbar.set_label("Thermal efficiency in %") + +ax.set_axisbelow(True) +ax.set_xlabel("Pressure at connection 2 in bar") +ax.set_ylabel("Pressure at connection 4 in bar") +plt.tight_layout() + +fig.savefig("pygmo_optimization.svg") +print(data.loc[data["efficiency"].values == data["efficiency"].min()]) +# %%[sec_6] diff --git a/tutorial/advanced/starting_values.py b/tutorial/advanced/starting_values.py new file mode 100644 index 000000000..da8c53de9 --- /dev/null +++ b/tutorial/advanced/starting_values.py @@ -0,0 +1,319 @@ +# %%[sec_1] +from tespy.networks import Network + +from tespy.components import ( + Condenser, Compressor, CycleCloser, HeatExchanger, + HeatExchangerSimple, Pump, Sink, Source, Valve + ) + +from tespy.connections import Connection, Bus +# %%[sec_2] +wf = "NH3" + +# network +nw = Network( + fluids=["water", wf], + T_unit="C", p_unit="bar", h_unit="kJ / kg", m_unit="kg / s" + ) + +# components +cycle_closer = CycleCloser("Refrigerant Cycle Closer") + +# heat source +heatsource_feedflow = Source("Heat Source Feed Flow") +heatsource_pump = Pump("Heat Source Recirculation Pump") +heatsource_evaporator = HeatExchanger("Heat Source Evaporator") +heatsource_backflow = Sink("Heat Source Back Flow") + +# compression +compressor = Compressor("Compressor") + +# heat sink +cons_pump = Pump("Heat Sink Recirculation Pump") +condenser = Condenser("Heat Sink Condenser") +cons_heatsink = HeatExchangerSimple("Heat Consumer") +cons_cycle_closer = CycleCloser("Consumer Feed Flow") + +# internal heat exchange +int_heatex = HeatExchanger("Internal Heat Exchanger") + +# expansion +valve = Valve("Expansion Valve") + +# connections +# main cycle +c0 = Connection(cycle_closer, "out1", heatsource_evaporator, "in2", label="0") +c1 = Connection(heatsource_evaporator, "out2", int_heatex, "in2", label="1") +c2 = Connection(int_heatex, "out2", compressor, "in1", label="2") +c3 = Connection(compressor, "out1", condenser, "in1", label="3") +c4 = Connection(condenser, "out1", int_heatex, "in1", label="4") +c5 = Connection(int_heatex, "out1", valve, "in1", label="5") +c6 = Connection(valve, "out1", cycle_closer, "in1", label="6") + +nw.add_conns( + c0, c1, c2, c3, c4, + c5, c6 + ) + +# heat source +c11 = Connection(heatsource_feedflow, "out1", heatsource_pump, "in1", label="11") +c12 = Connection(heatsource_pump, "out1", heatsource_evaporator, "in1", label="12") +c13 = Connection(heatsource_evaporator, "out1", heatsource_backflow, "in1", label="13") + +nw.add_conns(c11, c12, c13) + +# heat sink +c21 = Connection(cons_cycle_closer, "out1", cons_pump, "in1", label="21") +c22 = Connection(cons_pump, "out1", condenser, "in2", label="22") +c23 = Connection(condenser, "out2", cons_heatsink, "in1", label="23") +c24 = Connection(cons_heatsink, "out1", cons_cycle_closer, "in1", label="24") + +nw.add_conns(c21, c22, c23, c24) +# %%[sec_3] +# parametrization connections +# set feedflow and backflow temperature of heat source and consumer +T_hs_bf = 10 +T_hs_ff = 15 +T_cons_bf = 50 +T_cons_ff = 90 + +# consumer cycle +c23.set_attr(T=T_cons_ff, p=10, fluid={"water": 1, wf: 0}) +c24.set_attr(T=T_cons_bf) + +# heat source cycle +c11.set_attr(T=T_hs_ff, p=1, fluid={"water": 1, wf: 0}) +c13.set_attr(T=T_hs_bf, p=1) + +# evaporation to fully saturated gas +c1.set_attr(x=1, fluid={"water": 0, wf: 1}) +# degree of overheating after internal heat exchanger (evaporation side) +c2.set_attr(Td_bp=10) + +# parametrization components +# isentropic efficiency +cons_pump.set_attr(eta_s=0.8) +heatsource_pump.set_attr(eta_s=0.8) +compressor.set_attr(eta_s=0.85) + +# pressure ratios +condenser.set_attr(pr1=0.98, pr2=0.98) +heatsource_evaporator.set_attr(pr1=0.98, pr2=0.98) +cons_heatsink.set_attr(pr=0.99) +int_heatex.set_attr(pr1=0.98, pr2=0.98) + +# temperature differences +heatsource_evaporator.set_attr(ttd_l=5) +condenser.set_attr(ttd_u=5) + +# consumer heat demand +cons_heatsink.set_attr(Q=-1e6) + +try: + nw.solve("design") +except ValueError as e: + print(e) +# %%[sec_4] +import CoolProp.CoolProp as CP + +# evaporation point +p_eva = CP.PropsSI("P", "Q", 1, "T", T_hs_bf - 5 + 273.15, wf) * 1e-5 +c1.set_attr(p=p_eva) +heatsource_evaporator.set_attr(ttd_l=None) + +# condensation point +p_cond = CP.PropsSI("P", "Q", 0, "T", T_cons_ff + 5 + 273.15, wf) * 1e-5 +c4.set_attr(p=p_cond) +condenser.set_attr(ttd_u=None) + +# internal heat exchanger to compressor enthalpy +h_evap = CP.PropsSI("H", "Q", 1, "T", T_hs_bf - 5 + 273.15, wf) * 1e-3 +c2.set_attr(Td_bp=None, h=h_evap * 1.01) + +# solve the network again +nw.solve("design") +# %%[sec_5] +# evaporation point +c1.set_attr(p=None) +heatsource_evaporator.set_attr(ttd_l=5) + +# condensation point +c4.set_attr(p=None) +condenser.set_attr(ttd_u=5) + +# internal heat exchanger superheating +c2.set_attr(Td_bp=5, h=None) + +# solve the network again +nw.solve("design") + +# calculate the COP +cop = abs( + cons_heatsink.Q.val + / (cons_pump.P.val + heatsource_pump.P.val + compressor.P.val) +) +print(cop) +# %%[sec_6] +def generate_network_with_starting_values(wf): + # network + nw = Network( + fluids=["water", wf], + T_unit="C", p_unit="bar", h_unit="kJ / kg", m_unit="kg / s", + iterinfo=False + ) + + # components + cycle_closer = CycleCloser("Refrigerant Cycle Closer") + + # heat source + heatsource_feedflow = Source("Heat Source Feed Flow") + heatsource_pump = Pump("Heat Source Recirculation Pump") + heatsource_evaporator = HeatExchanger("Heat Source Evaporator") + heatsource_backflow = Sink("Heat Source Back Flow") + + # compression + compressor = Compressor("Compressor") + + # heat sink + cons_pump = Pump("Heat Sink Recirculation Pump") + condenser = Condenser("Heat Sink Condenser") + cons_heatsink = HeatExchangerSimple("Heat Consumer") + cons_cycle_closer = CycleCloser("Consumer Feed Flow") + + # internal heat exchange + int_heatex = HeatExchanger("Internal Heat Exchanger") + + # expansion + valve = Valve("Expansion Valve") + + # connections + # main cycle + c0 = Connection(cycle_closer, "out1", heatsource_evaporator, "in2", label="0") + c1 = Connection(heatsource_evaporator, "out2", int_heatex, "in2", label="1") + c2 = Connection(int_heatex, "out2", compressor, "in1", label="2") + c3 = Connection(compressor, "out1", condenser, "in1", label="3") + c4 = Connection(condenser, "out1", int_heatex, "in1", label="4") + c5 = Connection(int_heatex, "out1", valve, "in1", label="5") + c6 = Connection(valve, "out1", cycle_closer, "in1", label="6") + + nw.add_conns( + c0, c1, c2, c3, c4, + c5, c6 + ) + + # heat source + c11 = Connection(heatsource_feedflow, "out1", heatsource_pump, "in1", label="11") + c12 = Connection(heatsource_pump, "out1", heatsource_evaporator, "in1", label="12") + c13 = Connection(heatsource_evaporator, "out1", heatsource_backflow, "in1", label="13") + + nw.add_conns(c11, c12, c13) + + # heat sink + c21 = Connection(cons_cycle_closer, "out1", cons_pump, "in1", label="20") + c22 = Connection(cons_pump, "out1", condenser, "in2", label="21") + c23 = Connection(condenser, "out2", cons_heatsink, "in1", label="22") + c24 = Connection(cons_heatsink, "out1", cons_cycle_closer, "in1", label="23") + + nw.add_conns(c21, c22, c23, c24) + + # set feedflow and backflow temperature of heat source and consumer + T_hs_bf = 10 + T_hs_ff = 15 + T_cons_bf = 50 + T_cons_ff = 90 + + # consumer cycle + c23.set_attr(T=T_cons_ff, p=10, fluid={"water": 1, wf: 0}) + c24.set_attr(T=T_cons_bf) + + # heat source cycle + c11.set_attr(T=T_hs_ff, p=1, fluid={"water": 1, wf: 0}) + c13.set_attr(T=T_hs_bf, p=1) + + # evaporation to fully saturated gas + c1.set_attr(x=1, fluid={"water": 0, wf: 1}) + + # parametrization components + # isentropic efficiency + cons_pump.set_attr(eta_s=0.8) + heatsource_pump.set_attr(eta_s=0.8) + compressor.set_attr(eta_s=0.85) + + # pressure ratios + condenser.set_attr(pr1=0.98, pr2=0.98) + heatsource_evaporator.set_attr(pr1=0.98, pr2=0.98) + cons_heatsink.set_attr(pr=0.99) + int_heatex.set_attr(pr1=0.98, pr2=0.98) + + # evaporation point + p_eva = CP.PropsSI("P", "Q", 1, "T", T_hs_bf - 5 + 273.15, wf) * 1e-5 + c1.set_attr(p=p_eva) + + # condensation point + p_cond = CP.PropsSI("P", "Q", 0, "T", T_cons_ff + 5 + 273.15, wf) * 1e-5 + c4.set_attr(p=p_cond) + + # internal heat exchanger to compressor enthalpy + h_evap = CP.PropsSI("H", "Q", 1, "T", T_hs_bf - 5 + 273.15, wf) * 1e-3 + c2.set_attr(h=h_evap * 1.01) + + # consumer heat demand + cons_heatsink.set_attr(Q=-1e6) + + power_bus = Bus("Total power input") + heat_bus = Bus("Total heat production") + power_bus.add_comps( + {"comp": compressor, "base": "bus"}, + {"comp": cons_pump, "base": "bus"}, + {"comp": heatsource_pump, "base": "bus"}, + ) + heat_bus.add_comps({"comp": cons_heatsink}) + + nw.add_busses(power_bus, heat_bus) + + nw.solve("design") + + # evaporation point + c1.set_attr(p=None) + heatsource_evaporator.set_attr(ttd_l=5) + + # condensation point + c4.set_attr(p=None) + condenser.set_attr(ttd_u=5) + + # internal heat exchanger superheating + c2.set_attr(Td_bp=5, h=None) + + # solve the network again + nw.solve("design") + + return nw +# %%[sec_7] +import matplotlib.pyplot as plt +import pandas as pd + + +# make text reasonably sized +plt.rc("font", **{"size": 18}) + +cop = pd.DataFrame(columns=["COP"]) + +for wf in ["NH3", "R22", "R134a", "R152a", "R290", "R718"]: + nw = generate_network_with_starting_values(wf) + + power = nw.busses["Total power input"].P.val + heat = abs(nw.busses["Total heat production"].P.val) + cop.loc[wf] = heat / power + +fig, ax = plt.subplots(1, figsize=(16, 8)) + +cop.plot.bar(ax=ax, legend=False) + +ax.set_axisbelow(True) +ax.yaxis.grid(linestyle="dashed") +ax.set_xlabel("Name of working fluid") +ax.set_ylabel("Coefficicent of performance") +plt.tight_layout() + +fig.savefig("COP_by_wf.svg") +# %%[sec_8] diff --git a/tutorial/advanced/stepwise.py b/tutorial/advanced/stepwise.py new file mode 100644 index 000000000..ec64ea71b --- /dev/null +++ b/tutorial/advanced/stepwise.py @@ -0,0 +1,217 @@ +# %%[sec_1] +from tespy.networks import Network +working_fluid = "NH3" + +nw = Network( + fluids=["water", working_fluid], + T_unit="C", p_unit="bar", h_unit="kJ / kg", m_unit="kg / s" +) +# %%[sec_2] +from tespy.components import Condenser +from tespy.components import CycleCloser +from tespy.components import HeatExchangerSimple +from tespy.components import Pump +from tespy.components import Sink +from tespy.components import Source + +# sources & sinks +c_in = Source("refrigerant in") +cons_closer = CycleCloser("consumer cycle closer") +va = Sink("valve") + +# consumer system +cd = Condenser("condenser") +rp = Pump("recirculation pump") +cons = HeatExchangerSimple("consumer") +# %%[sec_3] +from tespy.connections import Connection + +c0 = Connection(c_in, "out1", cd, "in1", label="0") +c1 = Connection(cd, "out1", va, "in1", label="1") + +c20 = Connection(cons_closer, "out1", rp, "in1", label="20") +c21 = Connection(rp, "out1", cd, "in2", label="21") +c22 = Connection(cd, "out2", cons, "in1", label="22") +c23 = Connection(cons, "out1", cons_closer, "in1", label="23") + +nw.add_conns(c0, c1, c20, c21, c22, c23) +# %%[sec_4] +cd.set_attr(pr1=0.99, pr2=0.99) +rp.set_attr(eta_s=0.75) +cons.set_attr(pr=0.99) +# %%[sec_5] +from CoolProp.CoolProp import PropsSI as PSI +p_cond = PSI("P", "Q", 1, "T", 273.15 + 95, working_fluid) / 1e5 +c0.set_attr(T=170, p=p_cond, fluid={"water": 0, working_fluid: 1}) +c20.set_attr(T=60, p=2, fluid={"water": 1, working_fluid: 0}) +c22.set_attr(T=90) + +# key design paramter +cons.set_attr(Q=-230e3) +# %%[sec_6] +nw.solve("design") +nw.print_results() +# %%[sec_7] +from tespy.components import Valve, Drum, HeatExchanger + +# ambient heat source +amb_in = Source("source ambient") +amb_out = Sink("sink ambient") + +# evaporator system +va = Valve("valve") +dr = Drum("drum") +ev = HeatExchanger("evaporator") +su = HeatExchanger("superheater") + +# virtual source +cp1 = Sink("compressor 1") +# %%[sec_8] +nw.del_conns(c1) + +# evaporator system +c1 = Connection(cd, "out1", va, "in1", label="1") +c2 = Connection(va, "out1", dr, "in1", label="2") +c3 = Connection(dr, "out1", ev, "in2", label="3") +c4 = Connection(ev, "out2", dr, "in2", label="4") +c5 = Connection(dr, "out2", su, "in2", label="5") +c6 = Connection(su, "out2", cp1, "in1", label="6") + +nw.add_conns(c1, c2, c3, c4, c5, c6) + +c17 = Connection(amb_in, "out1", su, "in1", label="17") +c18 = Connection(su, "out1", ev, "in1", label="18") +c19 = Connection(ev, "out1", amb_out, "in1", label="19") + +nw.add_conns(c17, c18, c19) +# %%[sec_9] +ev.set_attr(pr1=0.99) +su.set_attr(pr1=0.99, pr2=0.99) +# %%[sec_10] +# evaporator system cold side +p_evap = PSI("P", "Q", 1, "T", 273.15 + 5, working_fluid) / 1e5 +c4.set_attr(x=0.9, p=p_evap) + +h_sat = PSI("H", "Q", 1, "T", 273.15 + 15, working_fluid) / 1e3 +c6.set_attr(h=h_sat) + +# evaporator system hot side +c17.set_attr(T=15, fluid={"water": 1, working_fluid: 0}) +c19.set_attr(T=9, p=1.013) +# %%[sec_11] +nw.solve("design") +nw.print_results() +# %%[sec_12] +from tespy.components import Compressor, Splitter, Merge + +cp1 = Compressor("compressor 1") +cp2 = Compressor("compressor 2") + +ic = HeatExchanger("intermittent cooling") +hsp = Pump("heat source pump") + +sp = Splitter("splitter") +me = Merge("merge") +cv = Valve("control valve") + +hs = Source("ambient intake") +cc = CycleCloser("heat pump cycle closer") +# %%[sec_13] +nw.del_conns(c0, c6, c17) + +c6 = Connection(su, "out2", cp1, "in1", label="6") +c7 = Connection(cp1, "out1", ic, "in1", label="7") +c8 = Connection(ic, "out1", cp2, "in1", label="8") +c9 = Connection(cp2, "out1", cc, "in1", label="9") +c0 = Connection(cc, "out1", cd, "in1", label="0") + +c11 = Connection(hs, "out1", hsp, "in1", label="11") +c12 = Connection(hsp, "out1", sp, "in1", label="12") +c13 = Connection(sp, "out1", ic, "in2", label="13") +c14 = Connection(ic, "out2", me, "in1", label="14") +c15 = Connection(sp, "out2", cv, "in1", label="15") +c16 = Connection(cv, "out1", me, "in2", label="16") +c17 = Connection(me, "out1", su, "in1", label="17") + +nw.add_conns(c6, c7, c8, c9, c0, c11, c12, c13, c14, c15, c16, c17) +# %%[sec_14] +pr = (c1.p.val / c5.p.val) ** 0.5 +cp1.set_attr(pr=pr) +ic.set_attr(pr1=0.99, pr2=0.98) +hsp.set_attr(eta_s=0.75) +# %%[sec_15] +c0.set_attr(p=p_cond, fluid={"water": 0, working_fluid: 1}) + +c6.set_attr(h=c5.h.val + 10) +c8.set_attr(h=c5.h.val + 10) + +c7.set_attr(h=c5.h.val * 1.2) +c9.set_attr(h=c5.h.val * 1.2) + +c11.set_attr(p=1.013, T=15, fluid={"water": 1, working_fluid: 0}) +c14.set_attr(T=30) +# %% [sec_16] +nw.solve("design") + +c0.set_attr(p=None) +cd.set_attr(ttd_u=5) + +c4.set_attr(p=None) +ev.set_attr(ttd_l=5) + +c6.set_attr(h=None) +su.set_attr(ttd_u=5) + +c7.set_attr(h=None) +cp1.set_attr(eta_s=0.8) + +c9.set_attr(h=None) +cp2.set_attr(eta_s=0.8) + +c8.set_attr(h=None, Td_bp=4) +nw.solve("design") +nw.save("system_design") +# %% [sec_17] +cp1.set_attr(design=["eta_s"], offdesign=["eta_s_char"]) +cp2.set_attr(design=["eta_s"], offdesign=["eta_s_char"]) +rp.set_attr(design=["eta_s"], offdesign=["eta_s_char"]) +hsp.set_attr(design=["eta_s"], offdesign=["eta_s_char"]) + +cons.set_attr(design=["pr"], offdesign=["zeta"]) + +cd.set_attr( + design=["pr2", "ttd_u"], offdesign=["zeta2", "kA_char"] +) + +from tespy.tools.characteristics import CharLine +from tespy.tools.characteristics import load_default_char as ldc + +kA_char1 = ldc("heat exchanger", "kA_char1", "DEFAULT", CharLine) +kA_char2 = ldc("heat exchanger", "kA_char2", "EVAPORATING FLUID", CharLine) +ev.set_attr( + kA_char1=kA_char1, kA_char2=kA_char2, + design=["pr1", "ttd_l"], offdesign=["zeta1", "kA_char"] +) + +su.set_attr( + design=["pr1", "pr2", "ttd_u"], offdesign=["zeta1", "zeta2", "kA_char"] +) + +ic.set_attr( + design=["pr1", "pr2"], offdesign=["zeta1", "zeta2", "kA_char"] +) +c14.set_attr(design=["T"]) +nw.solve("offdesign", design_path="system_design") +nw.print_results() +# %% [sec_18] +import numpy as np +nw.set_attr(iterinfo=False) + +for Q in np.linspace(1, 0.6, 5) * cons.Q.val: + cons.set_attr(Q=Q) + nw.solve("offdesign", design_path="system_design") + print( + "COP:", + abs(cons.Q.val) / (cp1.P.val + cp2.P.val + hsp.P.val + rp.P.val) + ) +# %% [sec_19] diff --git a/tutorial/basics/district_heating.py b/tutorial/basics/district_heating.py new file mode 100755 index 000000000..5f34c2d77 --- /dev/null +++ b/tutorial/basics/district_heating.py @@ -0,0 +1,147 @@ +# %%[sec_1] +from tespy.components.basics.cycle_closer import CycleCloser +from tespy.networks import Network +from tespy.components import ( + CycleCloser, Pipe, Pump, Valve, HeatExchangerSimple +) +from tespy.connections import Connection + +fluid_list = ['water'] +nw = Network(fluids=fluid_list) +nw.set_attr(T_unit='C', p_unit='bar', h_unit='kJ / kg') + +# central heating plant +hs = HeatExchangerSimple('heat source') +cc = CycleCloser('cycle closer') +pu = Pump('feed pump') + +# consumer +cons = HeatExchangerSimple('consumer') +val = Valve('control valve') + +# pipes +pipe_feed = Pipe('feed pipe') +pipe_return = Pipe('return pipe') + +# connections +c0 = Connection(cc, "out1", hs, "in1", label="0") +c1 = Connection(hs, "out1", pu, "in1", label="1") +c2 = Connection(pu, "out1", pipe_feed, "in1", label="2") +c3 = Connection(pipe_feed, "out1", cons, "in1", label="3") +c4 = Connection(cons, "out1", val, "in1", label="4") +c5 = Connection(val, "out1", pipe_return, "in1", label="5") +c6 = Connection(pipe_return, "out1", cc, "in1", label="6") +nw.add_conns(c0, c1, c2, c3, c4, c5, c6) +# %%[sec_2] +cons.set_attr(Q=-10000, pr=0.98) +hs.set_attr(pr=1) +pu.set_attr(eta_s=0.75) +pipe_feed.set_attr(Q=-250, pr=0.98) +pipe_return.set_attr(Q=-200, pr=0.98) + +c1.set_attr(T=90, p=10, fluid={'water': 1}) +c2.set_attr(p=13) +c4.set_attr(T=65) + +nw.solve(mode="design") +nw.print_results() +# %%[sec_3] +pipe_feed.set_attr( + ks=0.0005, # pipe's roughness in meters + L=100, # length in m + D="var", # diameter in m +) +pipe_return.set_attr( + ks=0.0005, # pipe's roughness in meters + L=100, # length in m + D="var", # diameter in m +) +nw.solve(mode="design") +nw.print_results() +# %%[sec_4] +pipe_feed.set_attr(D=pipe_feed.D.val, pr=None) +pipe_return.set_attr(D=pipe_return.D.val, pr=None) +pipe_feed.set_attr( + Tamb=0, # ambient temperature level in network's temperature unit + kA="var" # area independent heat transfer coefficient +) +pipe_return.set_attr( + Tamb=0, # ambient temperature level in network's temperature unit + kA="var" # area independent heat transfer coefficient +) +nw.solve(mode="design") +nw.print_results() +# %%[sec_5] +nw.set_attr(iterinfo=False) +pipe_feed.set_attr(Tamb=0, kA=pipe_feed.kA.val, Q=None) +pipe_return.set_attr(Tamb=0, kA=pipe_return.kA.val, Q=None) + +import matplotlib.pyplot as plt +import numpy as np + +# make text reasonably sized +plt.rc('font', **{'size': 18}) + +data = { + 'T_ambient': np.linspace(-10, 20, 7), + 'heat_load': np.linspace(3, 12, 10), + 'T_level': np.linspace(90, 60, 7) +} +eta = { + 'T_ambient': [], + 'heat_load': [], + 'T_level': [] +} +heat_loss = { + 'T_ambient': [], + 'heat_load': [], + 'T_level': [] +} + +for T in data['T_ambient']: + pipe_feed.set_attr(Tamb=T) + pipe_return.set_attr(Tamb=T) + nw.solve('design') + eta['T_ambient'] += [abs(cons.Q.val) / hs.Q.val * 100] + heat_loss['T_ambient'] += [abs(pipe_feed.Q.val + pipe_return.Q.val)] + +# reset to base temperature +pipe_feed.set_attr(Tamb=0) +pipe_return.set_attr(Tamb=0) + +for Q in data['heat_load']: + cons.set_attr(Q=-1e3 * Q) + nw.solve('design') + eta['heat_load'] += [abs(cons.Q.val) / hs.Q.val * 100] + heat_loss['heat_load'] += [abs(pipe_feed.Q.val + pipe_return.Q.val)] + +# reset to base temperature +cons.set_attr(Q=-10e3) + +for T in data['T_level']: + c1.set_attr(T=T) + c4.set_attr(T=T - 20) # return flow temperature assumed 20 °C lower than feed + nw.solve('design') + eta['T_level'] += [abs(cons.Q.val) / hs.Q.val * 100] + heat_loss['T_level'] += [abs(pipe_feed.Q.val + pipe_return.Q.val)] + +fig, ax = plt.subplots(2, 3, figsize=(16, 8), sharex='col', sharey='row') + +ax = ax.flatten() +[a.grid() for a in ax] + +i = 0 +for key in data: + ax[i].scatter(data[key], eta[key], s=100, color="#1f567d") + ax[i + 3].scatter(data[key], heat_loss[key], s=100, color="#18a999") + i += 1 + +ax[0].set_ylabel('Efficiency in %') +ax[3].set_ylabel('Heat losses in W') +ax[3].set_xlabel('Ambient temperature in °C') +ax[4].set_xlabel('Consumer heat load in kW') +ax[5].set_xlabel('District heating temperature level in °C') +plt.tight_layout() +fig.savefig('district_heating_partload.svg') +plt.close() +# %%[sec_6] diff --git a/tutorial/basics/gas_turbine.py b/tutorial/basics/gas_turbine.py new file mode 100755 index 000000000..4c64224e2 --- /dev/null +++ b/tutorial/basics/gas_turbine.py @@ -0,0 +1,212 @@ +# %%[sec_1] +from tespy.networks import Network +from tespy.components import ( + DiabaticCombustionChamber, Turbine, Source, Sink, Compressor +) +from tespy.connections import Connection, Ref, Bus + +# define full fluid list for the network"s variable space +fluid_list = ["Ar", "N2", "O2", "CO2", "CH4", "H2O", "H2"] +nw = Network(fluids=fluid_list, p_unit="bar", T_unit="C") + +cp = Compressor("Compressor") +cc = DiabaticCombustionChamber("combustion chamber") +tu = Turbine("turbine") +air = Source("air source") +fuel = Source("fuel source") +fg = Sink("flue gas sink") +# %%[sec_2] +c2 = Connection(air, "out1", cc, "in1", label="2") +c3 = Connection(cc, "out1", fg, "in1", label="3") +c5 = Connection(fuel, "out1", cc, "in2", label="5") +nw.add_conns(c2, c3, c5) +# %%[sec_3] +cc.set_attr(pr=1, eta=1, lamb=1.5, ti=10e6) + +c2.set_attr( + p=1, T=20, + fluid={ + "Ar": 0.0129, "N2": 0.7553, "H2O": 0, + "CH4": 0, "CO2": 0.0004, "O2": 0.2314, "H2": 0 + } +) +c5.set_attr( + p=1, T=20, + fluid={ + "CO2": 0.04, "Ar": 0, "N2": 0, "O2": 0, + "H2O": 0, "CH4": 0.96, "H2": 0 + } +) + +nw.solve(mode="design") +nw.print_results() +# %%[sec_4] +cc.set_attr(ti=None) +c5.set_attr(m=1) +nw.solve(mode="design") +# %%[sec_5] +cc.set_attr(lamb=None) +c3.set_attr(T=1400) +nw.solve(mode="design") +# %%[sec_6] +c5.set_attr( + fluid={ + "CO2": 0.03, "Ar": 0, "N2": 0, "O2": 0, + "H2O": 0, "CH4": 0.92, "H2": 0.05 + } +) +nw.solve(mode="design") +# %%[sec_7] +print(nw.results["Connection"]) +# %%[sec_8] +nw.del_conns(c2, c3) +c1 = Connection(air, "out1", cp, "in1", label="1") +c2 = Connection(cp, "out1", cc, "in1", label="2") +c3 = Connection(cc, "out1", tu, "in1", label="3") +c4 = Connection(tu, "out1", fg, "in1", label="4") +nw.add_conns(c1, c2, c3, c4) + +generator = Bus("generator") +generator.add_comps( + {"comp": tu, "char": 0.98, "base": "component"}, + {"comp": cp, "char": 0.98, "base": "bus"}, +) +nw.add_busses(generator) +# %%[sec_9] +cp.set_attr(eta_s=0.85, pr=15) +tu.set_attr(eta_s=0.90) +c1.set_attr( + p=1, T=20, + fluid={ + "Ar": 0.0129, "N2": 0.7553, "H2O": 0, + "CH4": 0, "CO2": 0.0004, "O2": 0.2314, "H2": 0 + } +) +c3.set_attr(T=1200) +c4.set_attr(p=Ref(c1, 1, 0)) +nw.solve("design") +nw.print_results() +# %%[sec_10] +# unset the value, impose Referenced value instead +c5.set_attr(p=None) +c5.set_attr(p=Ref(c2, 1.05, 0)) +nw.solve("design") +# %%[sec_11] +cc.set_attr(pr=0.97, eta=0.98) +nw.set_attr(iterinfo=False) +import matplotlib.pyplot as plt +import numpy as np + +# make text reasonably sized +plt.rc('font', **{'size': 18}) + +data = { + 'T_3': np.linspace(900, 1400, 11), + 'pr': np.linspace(10, 30, 11) +} +power = { + 'T_3': [], + 'pr': [] +} +eta = { + 'T_3': [], + 'pr': [] +} + +for T in data['T_3']: + c3.set_attr(T=T) + nw.solve('design') + power['T_3'] += [abs(generator.P.val) / 1e6] + eta['T_3'] += [abs(generator.P.val) / cc.ti.val * 100] + +# reset to base value +c3.set_attr(T=1200) + +for pr in data['pr']: + cp.set_attr(pr=pr) + nw.solve('design') + power['pr'] += [abs(generator.P.val) / 1e6] + eta['pr'] += [abs(generator.P.val) / cc.ti.val * 100] + +# reset to base value +cp.set_attr(pr=15) + +fig, ax = plt.subplots(2, 2, figsize=(16, 8), sharex='col', sharey='row') + +ax = ax.flatten() +[a.grid() for a in ax] + +i = 0 +for key in data: + ax[i].scatter(data[key], eta[key], s=100, color="#1f567d") + ax[i + 2].scatter(data[key], power[key], s=100, color="#18a999") + i += 1 + +ax[0].set_ylabel('Efficiency in %') +ax[2].set_ylabel('Power in MW') +ax[2].set_xlabel('Turbine inlet temperature °C') +ax[3].set_xlabel('Compressure pressure ratio') + +plt.tight_layout() +fig.savefig('gas_turbine_parametric.svg') +plt.close() +# %%[sec_12] +c3.set_attr(T=None) + + +data = np.linspace(0.025, 0.15, 6) + +T3 = [] + +for oxy in data[::-1]: + c3.set_attr(fluid={"O2": oxy}) + nw.solve('design') + T3 += [c3.T.val] + +# reset to base value +c3.fluid.val_set["O2"] = False +c3.set_attr(T=1200) + +fig, ax = plt.subplots(1, figsize=(16, 8)) + +ax.scatter(data * 100, T3, s=100, color="#1f567d") +ax.grid() + +ax.set_ylabel('Turbine inlet temperature in °C') +ax.set_xlabel('Oxygen mass fraction in flue gas in %') + +plt.tight_layout() +fig.savefig('gas_turbine_oxygen.svg') +plt.close() +# %%[sec_13] +# retain starting values for CH4 and H2 with this variant +c5.fluid.val_set["CH4"] = False +c5.fluid.val_set["H2"] = False +c5.set_attr(fluid_balance=True) + +data = np.linspace(50, 60, 11) + +CH4 = [] +H2 = [] + +for ti in data: + cc.set_attr(ti=ti * 1e6) + nw.solve('design') + CH4 += [c5.fluid.val["CH4"] * 100] + H2 += [c5.fluid.val["H2"] * 100] + +fig, ax = plt.subplots(1, figsize=(16, 8)) + +ax.scatter(data, CH4, s=100, color="#1f567d", label="CH4 mass fraction") +ax.scatter(data, H2, s=100, color="#18a999", label="H2 mass fraction") +ax.grid() +ax.legend() + +ax.set_ylabel('Mass fraction of the fuel in %') +ax.set_xlabel('Thermal input in MW') +ax.set_ybound([0, 100]) + +plt.tight_layout() +fig.savefig('gas_turbine_fuel_composition.svg') +plt.close() +# %%[sec_14] diff --git a/tutorial/basics/heat_pump.py b/tutorial/basics/heat_pump.py new file mode 100644 index 000000000..462275893 --- /dev/null +++ b/tutorial/basics/heat_pump.py @@ -0,0 +1,134 @@ +# %%[sec_1] +from tespy.networks import Network + +# create a network object with R134a as fluid +fluid_list = ['R134a'] +my_plant = Network(fluids=fluid_list) +# %%[sec_2] +# set the unitsystem for temperatures to °C and for pressure to bar +my_plant.set_attr(T_unit='C', p_unit='bar', h_unit='kJ / kg') +# %%[sec_3] +from tespy.components import ( + CycleCloser, Compressor, Valve, HeatExchangerSimple +) + +cc = CycleCloser('cycle closer') + +# heat sink +co = HeatExchangerSimple('condenser') +# heat source +ev = HeatExchangerSimple('evaporator') + +va = Valve('expansion valve') +cp = Compressor('compressor') +# %%[sec_4] +from tespy.connections import Connection + +# connections of heat pump +c1 = Connection(cc, 'out1', ev, 'in1', label='1') +c2 = Connection(ev, 'out1', cp, 'in1', label='2') +c3 = Connection(cp, 'out1', co, 'in1', label='3') +c4 = Connection(co, 'out1', va, 'in1', label='4') +c0 = Connection(va, 'out1', cc, 'in1', label='0') + +# this line is crutial: you have to add all connections to your network +my_plant.add_conns(c1, c2, c3, c4, c0) +# %%[sec_5] +co.set_attr(pr=0.98, Q=-1e6) +ev.set_attr(pr=0.98) +cp.set_attr(eta_s=0.85) + +c2.set_attr(T=20, x=1, fluid={'R134a': 1}) +c4.set_attr(T=80, x=0) +# %%[sec_6] +my_plant.solve(mode='design') +my_plant.print_results() + +print(f'COP = {abs(co.Q.val) / cp.P.val}') +# %%[sec_7] +co.set_attr(Q=None) +c1.set_attr(m=5) + +my_plant.solve('design') +my_plant.print_results() +# %%[sec_8] +cp.set_attr(pr=4) +c4.set_attr(T=None) + +my_plant.solve('design') +my_plant.print_results() +# %%[sec_9] +cp.set_attr(pr=None, eta_s=None) +c3.set_attr(T=97.3) +c4.set_attr(T=80) + +my_plant.solve('design') +my_plant.print_results() +# %%[sec_10] +# first go back to the original state of the specifications +co.set_attr(Q=-1e6) +cp.set_attr(pr=None, eta_s=0.85) +c1.set_attr(m=None) +c3.set_attr(T=None) +c4.set_attr(T=80) + +import matplotlib.pyplot as plt +import numpy as np + +# make text reasonably sized +plt.rc('font', **{'size': 18}) + + +data = { + 'T_source': np.linspace(0, 40, 11), + 'T_sink': np.linspace(60, 100, 11), + 'eta_s': np.linspace(0.75, 0.95, 11) * 100 +} +COP = { + 'T_source': [], + 'T_sink': [], + 'eta_s': [] +} +description = { + 'T_source': 'Evaporation temperature in °C', + 'T_sink': 'Condensation temperature in °C', + 'eta_s': 'Isentropic efficiency in %' +} + +for T in data['T_source']: + c2.set_attr(T=T) + my_plant.solve('design') + COP['T_source'] += [abs(co.Q.val) / cp.P.val] + +# reset to base temperature +c2.set_attr(T=20) + +for T in data['T_sink']: + c4.set_attr(T=T) + my_plant.solve('design') + COP['T_sink'] += [abs(co.Q.val) / cp.P.val] + +# reset to base temperature +c4.set_attr(T=80) + +for eta_s in data['eta_s']: + cp.set_attr(eta_s=eta_s / 100) + my_plant.solve('design') + COP['eta_s'] += [abs(co.Q.val) / cp.P.val] + +fig, ax = plt.subplots(1, 3, sharey=True, figsize=(16, 8)) + +[a.grid() for a in ax] + +i = 0 +for key in data: + ax[i].scatter(data[key], COP[key], s=100, color="#1f567d") + ax[i].set_xlabel(description[key]) + i += 1 + +ax[0].set_ylabel('COP of the heat pump') + +plt.tight_layout() + +fig.savefig('heat_pump_parametric.svg') +# %%[sec_11] diff --git a/tutorial/basics/rankine.py b/tutorial/basics/rankine.py new file mode 100755 index 000000000..0e9cb137c --- /dev/null +++ b/tutorial/basics/rankine.py @@ -0,0 +1,178 @@ +# %%[sec_1] +from tespy.networks import Network + +# create a network object with R134a as fluid +fluid_list = ['water'] +my_plant = Network(fluids=fluid_list) +my_plant.set_attr(T_unit='C', p_unit='bar', h_unit='kJ / kg') +# %%[sec_2] +from tespy.components import ( + CycleCloser, Pump, Condenser, Turbine, HeatExchangerSimple, Source, Sink +) + +cc = CycleCloser('cycle closer') +sg = HeatExchangerSimple('steam generator') +mc = Condenser('main condenser') +tu = Turbine('steam turbine') +fp = Pump('feed pump') + +cwso = Source('cooling water source') +cwsi = Sink('cooling water sink') + +from tespy.connections import Connection + +c1 = Connection(cc, 'out1', tu, 'in1', label='1') +c2 = Connection(tu, 'out1', mc, 'in1', label='2') +c3 = Connection(mc, 'out1', fp, 'in1', label='3') +c4 = Connection(fp, 'out1', sg, 'in1', label='4') +c0 = Connection(sg, 'out1', cc, 'in1', label='0') + +my_plant.add_conns(c1, c2, c3, c4, c0) + +c11 = Connection(cwso, 'out1', mc, 'in2', label='11') +c12 = Connection(mc, 'out2', cwsi, 'in1', label='12') + +my_plant.add_conns(c11, c12) +# %%[sec_3] +mc.set_attr(pr1=1, pr2=0.98) +sg.set_attr(pr=0.9) +tu.set_attr(eta_s=0.9) +fp.set_attr(eta_s=0.75) + +c11.set_attr(T=20, p=1.2, fluid={'water': 1}) +c12.set_attr(T=30) +c1.set_attr(T=600, p=150, m=10, fluid={'water': 1}) +c2.set_attr(p=0.1) + +my_plant.solve(mode='design') +my_plant.print_results() +# %%[sec_4] +mc.set_attr(ttd_u=4) +c2.set_attr(p=None) + +my_plant.solve(mode='design') +my_plant.print_results() +# %%[sec_5] +from tespy.connections import Bus + +powergen = Bus("electrical power output") + +powergen.add_comps( + {"comp": tu, "char": 0.97, "base": "component"}, + {"comp": fp, "char": 0.97, "base": "bus"}, +) + +my_plant.add_busses(powergen) + +my_plant.solve(mode='design') +my_plant.print_results() +# %%[sec_6] +powergen.set_attr(P=-10e6) +c1.set_attr(m=None) + +my_plant.solve(mode='design') +my_plant.print_results() +# %%[sec_7] +my_plant.set_attr(iterinfo=False) +c1.set_attr(m=20) +powergen.set_attr(P=None) +import matplotlib.pyplot as plt +import numpy as np + +# make text reasonably sized +plt.rc('font', **{'size': 18}) + +data = { + 'T_livesteam': np.linspace(450, 750, 7), + 'T_cooling': np.linspace(15, 45, 7), + 'p_livesteam': np.linspace(75, 225, 7) +} +eta = { + 'T_livesteam': [], + 'T_cooling': [], + 'p_livesteam': [] +} +power = { + 'T_livesteam': [], + 'T_cooling': [], + 'p_livesteam': [] +} + +for T in data['T_livesteam']: + c1.set_attr(T=T) + my_plant.solve('design') + eta['T_livesteam'] += [abs(powergen.P.val) / sg.Q.val * 100] + power['T_livesteam'] += [abs(powergen.P.val) / 1e6] + +# reset to base temperature +c1.set_attr(T=600) + +for T in data['T_cooling']: + c12.set_attr(T=T) + c11.set_attr(T=T - 10) + my_plant.solve('design') + eta['T_cooling'] += [abs(powergen.P.val) / sg.Q.val * 100] + power['T_cooling'] += [abs(powergen.P.val) / 1e6] + +# reset to base temperature +c12.set_attr(T=30) +c11.set_attr(T=20) + +for p in data['p_livesteam']: + c1.set_attr(p=p) + my_plant.solve('design') + eta['p_livesteam'] += [abs(powergen.P.val) / sg.Q.val * 100] + power['p_livesteam'] += [abs(powergen.P.val) / 1e6] + +# reset to base pressure +c1.set_attr(p=150) + + +fig, ax = plt.subplots(2, 3, figsize=(16, 8), sharex='col', sharey='row') + +ax = ax.flatten() +[a.grid() for a in ax] + +i = 0 +for key in data: + ax[i].scatter(data[key], eta[key], s=100, color="#1f567d") + ax[i + 3].scatter(data[key], power[key], s=100, color="#18a999") + i += 1 + +ax[0].set_ylabel('Efficiency in %') +ax[3].set_ylabel('Power in MW') +ax[3].set_xlabel('Live steam temperature in °C') +ax[4].set_xlabel('Feed water temperature in °C') +ax[5].set_xlabel('Live steam pressure in bar') +plt.tight_layout() +fig.savefig('rankine_parametric.svg') +plt.close() +# %%[sec_8] +mc.set_attr(design=["ttd_u"], offdesign=["kA"]) +c11.set_attr(offdesign=["v"]) +c12.set_attr(design=["T"]) +c1.set_attr(design=["p"]) +tu.set_attr(offdesign=["cone"]) +# %%[sec_9] +my_plant.solve("design") +my_plant.save("rankine_design") +# %%[sec_10] +partload_efficiency = [] +partload_m_range = np.linspace(20, 10, 11) + +for m in partload_m_range: + c1.set_attr(m=m) + my_plant.solve("offdesign", design_path="rankine_design") + partload_efficiency += [abs(powergen.P.val) / sg.Q.val * 100] + + +fig, ax = plt.subplots(1, figsize=(16, 8)) +ax.grid() +ax.scatter(partload_m_range, partload_efficiency, s=100, color="#1f567d") +ax.set_xlabel("Mass flow in kg/s") +ax.set_ylabel("Plant electrical efficiency in %") + +plt.tight_layout() +fig.savefig('rankine_partload.svg') +plt.close() +# %%[sec_11] diff --git a/tutorial/NH3.py b/tutorial/heat_pump_exergy/NH3.py similarity index 100% rename from tutorial/NH3.py rename to tutorial/heat_pump_exergy/NH3.py diff --git a/tutorial/NH3_calculations.py b/tutorial/heat_pump_exergy/NH3_calculations.py similarity index 100% rename from tutorial/NH3_calculations.py rename to tutorial/heat_pump_exergy/NH3_calculations.py diff --git a/tutorial/R410A.py b/tutorial/heat_pump_exergy/R410A.py similarity index 100% rename from tutorial/R410A.py rename to tutorial/heat_pump_exergy/R410A.py diff --git a/tutorial/R410A_calculations.py b/tutorial/heat_pump_exergy/R410A_calculations.py similarity index 100% rename from tutorial/R410A_calculations.py rename to tutorial/heat_pump_exergy/R410A_calculations.py diff --git a/tutorial/plots.py b/tutorial/heat_pump_exergy/plots.py similarity index 99% rename from tutorial/plots.py rename to tutorial/heat_pump_exergy/plots.py index e2ac8d9d6..b380d0287 100644 --- a/tutorial/plots.py +++ b/tutorial/heat_pump_exergy/plots.py @@ -75,8 +75,8 @@ fig.suptitle('Component Exergy Destruction', fontsize=14) fig.legend(bbox_to_anchor=(0.08, 0, 0.9, .0), loc='center', ncol=3, borderaxespad=0.) -plt.show() fig.savefig('diagram_E_D.svg', bbox_inches='tight') +plt.close() # %% figure 2: epsilon depending on ambient Temperature Tamb @@ -118,6 +118,7 @@ fig.suptitle('Exergetic Efficency depending on Temperature', fontsize=14) fig.savefig('diagram_eps_Tamb_Tgeo.svg', bbox_inches='tight') +plt.close() # %% figure 3: epsilon and COP depending on mean geothermal temperature Tgeo @@ -166,6 +167,7 @@ 'COP and $\epsilon$ depending heating and geothermal mean temperature', fontsize=12) fig.savefig('diagram_cop_eps_Tgeo_Ths.svg', bbox_inches='tight') +plt.close() # %% figure 4: epsilon and COP depending on mean geothermal temperature Tgeo @@ -217,3 +219,4 @@ 'COP and $\epsilon$ depending on load and geothermal mean temperature', fontsize=12) fig.savefig('diagram_cop_eps_Tgeo_Q.svg', bbox_inches='tight') +plt.close() diff --git a/tutorial/step_1.py b/tutorial/step_1.py deleted file mode 100644 index 0b8a79c6e..000000000 --- a/tutorial/step_1.py +++ /dev/null @@ -1,77 +0,0 @@ -# -*- coding: utf-8 -*- - -from tespy.components import Condenser -from tespy.components import CycleCloser -from tespy.components import HeatExchangerSimple -from tespy.components import Pump -from tespy.components import Sink -from tespy.components import Source -from tespy.connections import Connection -from tespy.networks import Network - -# %% network - -nw = Network(fluids=['water', 'NH3'], T_unit='C', p_unit='bar', - h_unit='kJ / kg', m_unit='kg / s') - -# %% components - -# sources & sinks - -c_in = Source('coolant in') -cons_closer = CycleCloser('consumer cycle closer') - -va = Sink('valve') - -# consumer system - -cd = Condenser('condenser') -rp = Pump('recirculation pump') -cons = HeatExchangerSimple('consumer') - -# %% connections - -# consumer system - -c_in_cd = Connection(c_in, 'out1', cd, 'in1') - -close_rp = Connection(cons_closer, 'out1', rp, 'in1') -rp_cd = Connection(rp, 'out1', cd, 'in2') -cd_cons = Connection(cd, 'out2', cons, 'in1') -cons_close = Connection(cons, 'out1', cons_closer, 'in1') - -nw.add_conns(c_in_cd, close_rp, rp_cd, cd_cons, cons_close) - -# connection condenser - evaporator system - -cd_va = Connection(cd, 'out1', va, 'in1') - -nw.add_conns(cd_va) - -# %% component parametrization - -cd.set_attr(pr1=0.99, pr2=0.99, ttd_u=5, design=['pr2', 'ttd_u'], - offdesign=['zeta2', 'kA_char']) -rp.set_attr(eta_s=0.8, design=['eta_s'], offdesign=['eta_s_char']) -cons.set_attr(pr=0.99, design=['pr'], offdesign=['zeta']) - -# %% connection parametrization - -c_in_cd.set_attr(T=170, fluid={'water': 0, 'NH3': 1}) -close_rp.set_attr(T=60, p=10, fluid={'water': 1, 'NH3': 0}) -cd_cons.set_attr(T=90) - -# %% key paramter - -cons.set_attr(Q=-230e3) - -# %% Calculation - -nw.solve('design') -nw.print_results() -nw.save('condenser') - -cons.set_attr(Q=-200e3) - -nw.solve('offdesign', design_path='condenser') -nw.print_results() diff --git a/tutorial/step_2.py b/tutorial/step_2.py deleted file mode 100644 index c23a166a1..000000000 --- a/tutorial/step_2.py +++ /dev/null @@ -1,142 +0,0 @@ -# -*- coding: utf-8 -*- - -from tespy.components import Condenser -from tespy.components import CycleCloser -from tespy.components import Drum -from tespy.components import HeatExchanger -from tespy.components import HeatExchangerSimple -from tespy.components import Pump -from tespy.components import Sink -from tespy.components import Source -from tespy.components import Valve -from tespy.connections import Connection -from tespy.connections import Ref -from tespy.networks import Network -from tespy.tools.characteristics import CharLine -from tespy.tools.characteristics import load_default_char as ldc - -# %% network - -nw = Network(fluids=['water', 'NH3'], T_unit='C', p_unit='bar', - h_unit='kJ / kg', m_unit='kg / s') - -# %% components - -# sources & sinks - -c_in = Source('coolant in') -cons_closer = CycleCloser('consumer cycle closer') - -amb_in = Source('source ambient') -amb_out = Sink('sink ambient') - -# consumer system - -cd = Condenser('condenser') -rp = Pump('recirculation pump') -cons = HeatExchangerSimple('consumer') - -# evaporator system - -va = Valve('valve') -dr = Drum('drum') -ev = HeatExchanger('evaporator') -su = HeatExchanger('superheater') -pu = Pump('pump evaporator') - -cp1 = Sink('compressor 1') - -# %% connections - -# consumer system - -c_in_cd = Connection(c_in, 'out1', cd, 'in1') - -close_rp = Connection(cons_closer, 'out1', rp, 'in1') -rp_cd = Connection(rp, 'out1', cd, 'in2') -cd_cons = Connection(cd, 'out2', cons, 'in1') -cons_close = Connection(cons, 'out1', cons_closer, 'in1') - -nw.add_conns(c_in_cd, close_rp, rp_cd, cd_cons, cons_close) - -# connection condenser - evaporator system - -cd_va = Connection(cd, 'out1', va, 'in1') - -nw.add_conns(cd_va) - -# evaporator system - -va_dr = Connection(va, 'out1', dr, 'in1') -dr_pu = Connection(dr, 'out1', pu, 'in1') -pu_ev = Connection(pu, 'out1', ev, 'in2') -ev_dr = Connection(ev, 'out2', dr, 'in2') -dr_su = Connection(dr, 'out2', su, 'in2') - -nw.add_conns(va_dr, dr_pu, pu_ev, ev_dr, dr_su) - -amb_in_su = Connection(amb_in, 'out1', su, 'in1') -su_ev = Connection(su, 'out1', ev, 'in1') -ev_amb_out = Connection(ev, 'out1', amb_out, 'in1') - -nw.add_conns(amb_in_su, su_ev, ev_amb_out) - -# connection evaporator system - compressor system - -su_cp1 = Connection(su, 'out2', cp1, 'in1') - -nw.add_conns(su_cp1) - -# %% component parametrization - -# condenser system - -cd.set_attr(pr1=0.99, pr2=0.99, ttd_u=5, design=['pr2', 'ttd_u'], - offdesign=['zeta2', 'kA_char']) -rp.set_attr(eta_s=0.8, design=['eta_s'], offdesign=['eta_s_char']) -cons.set_attr(pr=0.99, design=['pr'], offdesign=['zeta']) - -# evaporator system - -kA_char1 = ldc('heat exchanger', 'kA_char1', 'DEFAULT', CharLine) -kA_char2 = ldc('heat exchanger', 'kA_char2', 'EVAPORATING FLUID', CharLine) - -ev.set_attr(pr1=0.99, pr2=0.99, ttd_l=5, - kA_char1=kA_char1, kA_char2=kA_char2, - design=['pr1', 'ttd_l'], offdesign=['zeta1', 'kA_char']) -su.set_attr(pr1=0.99, pr2=0.99, ttd_u=2, design=['pr1', 'pr2', 'ttd_u'], - offdesign=['zeta1', 'zeta2', 'kA_char']) -pu.set_attr(eta_s=0.8, design=['eta_s'], offdesign=['eta_s_char']) - -# %% connection parametrization - -# condenser system - -c_in_cd.set_attr(T=170, fluid={'water': 0, 'NH3': 1}) -close_rp.set_attr(T=60, p=10, fluid={'water': 1, 'NH3': 0}) -cd_cons.set_attr(T=90) - -# evaporator system cold side - -pu_ev.set_attr(m=Ref(va_dr, 0.75, 0)) -su_cp1.set_attr(state='g') - -# evaporator system hot side - -amb_in_su.set_attr(T=12, p=1, fluid={'water': 1, 'NH3': 0}) -ev_amb_out.set_attr(T=9) - -# %% key paramter - -cons.set_attr(Q=-230e3) - -# %% Calculation - -nw.solve('design') -nw.print_results() -nw.save('condenser_eva') - -cons.set_attr(Q=-200e3) - -nw.solve('offdesign', design_path='condenser_eva') -nw.print_results() diff --git a/tutorial/step_3.py b/tutorial/step_3.py deleted file mode 100644 index 6aba803b4..000000000 --- a/tutorial/step_3.py +++ /dev/null @@ -1,174 +0,0 @@ -# -*- coding: utf-8 -*- - -from tespy.components import Compressor -from tespy.components import Condenser -from tespy.components import CycleCloser -from tespy.components import Drum -from tespy.components import HeatExchanger -from tespy.components import HeatExchangerSimple -from tespy.components import Pump -from tespy.components import Sink -from tespy.components import Source -from tespy.components import Valve -from tespy.connections import Connection -from tespy.connections import Ref -from tespy.networks import Network -from tespy.tools.characteristics import CharLine -from tespy.tools.characteristics import load_default_char as ldc - -# %% network - -nw = Network(fluids=['water', 'NH3'], T_unit='C', p_unit='bar', - h_unit='kJ / kg', m_unit='kg / s') - -# %% components - -# sources & sinks - -cool_closer = CycleCloser('coolant cycle closer') -cons_closer = CycleCloser('consumer cycle closer') - -amb_in = Source('source ambient') -amb_out = Sink('sink ambient') - -ic_in = Source('source intercool') -ic_out = Sink('sink intercool') - -# consumer system - -cd = Condenser('condenser') -rp = Pump('recirculation pump') -cons = HeatExchangerSimple('consumer') - -# evaporator system - -va = Valve('valve') -dr = Drum('drum') -ev = HeatExchanger('evaporator') -su = HeatExchanger('superheater') -pu = Pump('pump evaporator') - -# compressor-system - -cp1 = Compressor('compressor 1') -cp2 = Compressor('compressor 2') -he = HeatExchanger('intercooler') - -# %% connections - -# consumer system - -c_in_cd = Connection(cool_closer, 'out1', cd, 'in1') -close_rp = Connection(cons_closer, 'out1', rp, 'in1') -rp_cd = Connection(rp, 'out1', cd, 'in2') -cd_cons = Connection(cd, 'out2', cons, 'in1') -cons_close = Connection(cons, 'out1', cons_closer, 'in1') - -nw.add_conns(c_in_cd, close_rp, rp_cd, cd_cons, cons_close) - -# connection condenser - evaporator system - -cd_va = Connection(cd, 'out1', va, 'in1') - -nw.add_conns(cd_va) - -# evaporator system - -va_dr = Connection(va, 'out1', dr, 'in1') -dr_pu = Connection(dr, 'out1', pu, 'in1') -pu_ev = Connection(pu, 'out1', ev, 'in2') -ev_dr = Connection(ev, 'out2', dr, 'in2') -dr_su = Connection(dr, 'out2', su, 'in2') - -nw.add_conns(va_dr, dr_pu, pu_ev, ev_dr, dr_su) - -amb_in_su = Connection(amb_in, 'out1', su, 'in1') -su_ev = Connection(su, 'out1', ev, 'in1') -ev_amb_out = Connection(ev, 'out1', amb_out, 'in1') - -nw.add_conns(amb_in_su, su_ev, ev_amb_out) - -# connection evaporator system - compressor system - -su_cp1 = Connection(su, 'out2', cp1, 'in1') - -nw.add_conns(su_cp1) - -# compressor-system - -cp1_he = Connection(cp1, 'out1', he, 'in1') -he_cp2 = Connection(he, 'out1', cp2, 'in1') -cp2_close = Connection(cp2, 'out1', cool_closer, 'in1') - -ic_in_he = Connection(ic_in, 'out1', he, 'in2') -he_ic_out = Connection(he, 'out2', ic_out, 'in1') - -nw.add_conns(cp1_he, he_cp2, ic_in_he, he_ic_out, cp2_close) - -# %% component parametrization - -# condenser system - -cd.set_attr(pr1=0.99, pr2=0.99, ttd_u=5, design=['pr2', 'ttd_u'], - offdesign=['zeta2', 'kA_char']) -rp.set_attr(eta_s=0.8, design=['eta_s'], offdesign=['eta_s_char']) -cons.set_attr(pr=0.99, design=['pr'], offdesign=['zeta']) - -# evaporator system - -kA_char1 = ldc('heat exchanger', 'kA_char1', 'DEFAULT', CharLine) -kA_char2 = ldc('heat exchanger', 'kA_char2', 'EVAPORATING FLUID', CharLine) - -ev.set_attr(pr1=0.99, pr2=0.99, ttd_l=5, - kA_char1=kA_char1, kA_char2=kA_char2, - design=['pr1', 'ttd_l'], offdesign=['zeta1', 'kA_char']) -su.set_attr(pr1=0.99, pr2=0.99, ttd_u=2, design=['pr1', 'pr2', 'ttd_u'], - offdesign=['zeta1', 'zeta2', 'kA_char']) -pu.set_attr(eta_s=0.8, design=['eta_s'], offdesign=['eta_s_char']) - -# compressor system - -cp1.set_attr(eta_s=0.8, design=['eta_s'], offdesign=['eta_s_char']) -cp2.set_attr(eta_s=0.8, pr=5, design=['eta_s'], offdesign=['eta_s_char']) - -he.set_attr(pr1=0.98, pr2=0.98, design=['pr1', 'pr2'], - offdesign=['zeta1', 'zeta2', 'kA_char']) - -# %% connection parametrization - -# condenser system - -c_in_cd.set_attr(fluid={'water': 0, 'NH3': 1}) -close_rp.set_attr(T=60, p=10, fluid={'water': 1, 'NH3': 0}) -cd_cons.set_attr(T=90) - -# evaporator system cold side - -pu_ev.set_attr(m=Ref(va_dr, 0.75, 0)) -su_cp1.set_attr(state='g') - -# evaporator system hot side - -amb_in_su.set_attr(T=12, p=1, fluid={'water': 1, 'NH3': 0}) -ev_amb_out.set_attr(T=9) - -he_cp2.set_attr(T=40, p0=10) -ic_in_he.set_attr(p=5, T=20, fluid={'water': 1, 'NH3': 0}) -he_ic_out.set_attr(T=30, design=['T']) - -# %% key paramter - -cons.set_attr(Q=-230e3) - -# %% Calculation - -nw.solve('design') -# alternatively use: -nw.solve('design', init_path='condenser_eva') -nw.print_results() -nw.save('heat_pump') - -cons.set_attr(Q=-200e3) - -nw.solve('offdesign', design_path='heat_pump') -nw.print_results()