├── .editorconfig ├── .github └── workflows │ ├── packaging.yml │ ├── tox_checks.yml │ └── tox_pytest.yml ├── .gitignore ├── .pep8speaks.yml ├── .readthedocs.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── PULL_REQUEST_TEMPLATE.md ├── README.rst ├── docs ├── _static │ ├── css │ │ └── custom.css │ ├── images │ │ ├── advanced │ │ │ └── exergy │ │ │ │ ├── flowsheet.svg │ │ │ │ ├── flowsheet_darkmode.svg │ │ │ │ └── sankey.svg │ │ ├── basics │ │ │ ├── district_heating.svg │ │ │ ├── district_heating_darkmode.svg │ │ │ ├── district_heating_partload.svg │ │ │ ├── district_heating_partload_darkmode.svg │ │ │ ├── gas_turbine.svg │ │ │ ├── gas_turbine_darkmode.svg │ │ │ ├── gas_turbine_fuel_composition.svg │ │ │ ├── gas_turbine_fuel_composition_darkmode.svg │ │ │ ├── gas_turbine_oxygen.svg │ │ │ ├── gas_turbine_oxygen_darkmode.svg │ │ │ ├── gas_turbine_parametric.svg │ │ │ ├── gas_turbine_parametric_darkmode.svg │ │ │ ├── heat_pump.svg │ │ │ ├── heat_pump_darkmode.svg │ │ │ ├── heat_pump_parametric.svg │ │ │ ├── heat_pump_parametric_darkmode.svg │ │ │ ├── modeling_concept.svg │ │ │ ├── rankine_cycle.svg │ │ │ ├── rankine_cycle_darkmode.svg │ │ │ ├── rankine_parametric.svg │ │ │ ├── rankine_parametric_darkmode.svg │ │ │ ├── rankine_partload.svg │ │ │ ├── rankine_partload_darkmode.svg │ │ │ ├── rankine_ts_diagram.svg │ │ │ └── rankine_ts_diagram_darkmode.svg │ │ ├── examples │ │ │ ├── GRC_flowsheet.svg │ │ │ ├── GRC_flowsheet_darkmode.svg │ │ │ ├── ORC_parametric_flowsheet.svg │ │ │ ├── ORC_parametric_flowsheet_darkmode.svg │ │ │ ├── PM_CAES_graphical-abstract.svg │ │ │ ├── PM_CAES_graphical-abstract_darkmode.svg │ │ │ ├── heatpumps.png │ │ │ └── heatpumps_darkmode.png │ │ ├── logo_tespy_big.svg │ │ ├── logo_tespy_big_darkmode.svg │ │ ├── logo_tespy_big_editable_font.svg │ │ ├── logo_tespy_mid.svg │ │ ├── logo_tespy_mid_christmas.svg │ │ ├── logo_tespy_mid_darkmode.svg │ │ ├── logo_tespy_mid_darkmode_christmas.svg │ │ ├── logo_tespy_mid_editable_font.svg │ │ ├── logo_tespy_mini.svg │ │ ├── logo_tespy_small.svg │ │ ├── modules │ │ │ ├── Ts_diagram_states.svg │ │ │ ├── characteristics.svg │ │ │ ├── characteristics_darkmode.svg │ │ │ ├── connections.svg │ │ │ ├── connections_darkmode.svg │ │ │ ├── fluid_properties.svg │ │ │ ├── fluid_properties_darkmode.svg │ │ │ ├── logph_diagram_states.svg │ │ │ ├── subsystem_waste_heat_generator.svg │ │ │ ├── subsystem_waste_heat_generator_darkmode.svg │ │ │ ├── ude.svg │ │ │ └── ude_darkmode.svg │ │ └── tutorials │ │ │ ├── district_heating_system │ │ │ ├── dhs.svg │ │ │ ├── dhs_closed.svg │ │ │ ├── dhs_forks.svg │ │ │ └── dhs_open.svg │ │ │ ├── heat_pump_exergy │ │ │ ├── NH3_logph.svg │ │ │ ├── NH3_sankey.svg │ │ │ ├── diagram_E_D.svg │ │ │ ├── diagram_E_D_darkmode.svg │ │ │ ├── diagram_cop_eps_Tgeo_Q.svg │ │ │ ├── diagram_cop_eps_Tgeo_Q_darkmode.svg │ │ │ ├── diagram_cop_eps_Tgeo_Ths.svg │ │ │ ├── diagram_cop_eps_Tgeo_Ths_darkmode.svg │ │ │ ├── diagram_eps_Tamb_Tgeo.svg │ │ │ ├── diagram_eps_Tamb_Tgeo_darkmode.svg │ │ │ ├── flowsheet.svg │ │ │ └── flowsheet_darkmode.svg │ │ │ ├── heat_pump_starting_values │ │ │ ├── COP_by_wf.svg │ │ │ ├── COP_by_wf_darkmode.svg │ │ │ ├── flowsheet.svg │ │ │ ├── flowsheet_darkmode.svg │ │ │ └── logph.svg │ │ │ ├── heat_pump_stepwise │ │ │ ├── flowsheet.svg │ │ │ ├── flowsheet_darkmode.svg │ │ │ ├── flowsheet_p1.svg │ │ │ ├── flowsheet_p1_darkmode.svg │ │ │ ├── flowsheet_p2.svg │ │ │ └── flowsheet_p2_darkmode.svg │ │ │ ├── osmses-2023.svg │ │ │ ├── osmses-2023_darkmode.svg │ │ │ └── pygmo_optimization │ │ │ ├── flowsheet.svg │ │ │ ├── flowsheet_darkmode.svg │ │ │ ├── pygmo_optimization.svg │ │ │ └── pygmo_optimization_darkmode.svg │ └── js │ │ └── custom.js ├── _templates │ └── index.html ├── advanced │ ├── exergy.rst │ └── optimization.rst ├── api.rst ├── api │ ├── _images │ │ ├── CombustionChamber.svg │ │ ├── CombustionChamber_darkmode.svg │ │ ├── CombustionEngine.svg │ │ ├── CombustionEngine_darkmode.svg │ │ ├── Compressor.svg │ │ ├── Compressor_darkmode.svg │ │ ├── Condenser.svg │ │ ├── Condenser_darkmode.svg │ │ ├── DropletSeparator.svg │ │ ├── DropletSeparator_darkmode.svg │ │ ├── Drum.svg │ │ ├── Drum_darkmode.svg │ │ ├── FuelCell.svg │ │ ├── FuelCell_darkmode.svg │ │ ├── HeatExchanger.svg │ │ ├── HeatExchanger_darkmode.svg │ │ ├── Merge.svg │ │ ├── Merge_darkmode.svg │ │ ├── ORCEvaporator.svg │ │ ├── ParabolicTrough.svg │ │ ├── ParabolicTrough_darkmode.svg │ │ ├── Pipe.svg │ │ ├── Pipe_darkmode.svg │ │ ├── Pump.svg │ │ ├── Pump_darkmode.svg │ │ ├── SolarCollector.svg │ │ ├── SolarCollector_darkmode.svg │ │ ├── Splitter.svg │ │ ├── Splitter_darkmode.svg │ │ ├── SubsystemInterface.svg │ │ ├── SubsystemInterface_darkmode.svg │ │ ├── Turbine.svg │ │ ├── Turbine_darkmode.svg │ │ ├── Valve.svg │ │ ├── Valve_darkmode.svg │ │ ├── WaterElectrolyzer.svg │ │ ├── WaterElectrolyzer_darkmode.svg │ │ ├── combustion_engine_Q1_char_DEFAULT.svg │ │ ├── combustion_engine_Q2_char_DEFAULT.svg │ │ ├── combustion_engine_Qloss_char_DEFAULT.svg │ │ ├── combustion_engine_tiP_char_DEFAULT.svg │ │ ├── compressor_char_map_eta_s_DEFAULT.svg │ │ ├── compressor_char_map_pr_DEFAULT.svg │ │ ├── compressor_eta_s_char_DEFAULT.svg │ │ ├── condenser_kA_char1_DEFAULT.svg │ │ ├── condenser_kA_char2_DEFAULT.svg │ │ ├── desuperheater_kA_char1_DEFAULT.svg │ │ ├── desuperheater_kA_char2_DEFAULT.svg │ │ ├── heat_exchanger_kA_char1_CONDENSING_FLUID.svg │ │ ├── heat_exchanger_kA_char1_DEFAULT.svg │ │ ├── heat_exchanger_kA_char2_DEFAULT.svg │ │ ├── heat_exchanger_kA_char2_EVAPORATING_FLUID.svg │ │ ├── heat_exchanger_simple_kA_char_DEFAULT.svg │ │ ├── pipe_kA_char_DEFAULT.svg │ │ ├── pump_eta_s_char_DEFAULT.svg │ │ ├── turbine_eta_s_char_DEFAULT.svg │ │ ├── turbine_eta_s_char_TRAUPEL.svg │ │ └── water_electrolyzer_eta_char_DEFAULT.svg │ ├── components.rst │ ├── connections.rst │ ├── data.rst │ ├── networks.rst │ └── tools.rst ├── basics.rst ├── basics │ ├── district_heating.rst │ ├── gas_turbine.rst │ ├── heat_pump.rst │ ├── intro.rst │ └── rankine_cycle.rst ├── benchmarks.rst ├── conf.py ├── development │ ├── how.rst │ └── what.rst ├── examples.rst ├── index.rst ├── installation.rst ├── introduction.rst ├── modules.rst ├── modules │ ├── characteristics.rst │ ├── components.rst │ ├── connections.rst │ ├── fluid_properties.rst │ ├── networks.rst │ └── ude.rst ├── references.bib ├── regular_meeting.rst ├── scripts │ └── generate_tespy_data_module.py ├── tutorials.rst ├── tutorials │ ├── district_heating.rst │ ├── heat_pump_exergy.rst │ ├── heat_pump_steps.rst │ ├── pygmo_optimization.rst │ └── starting_values.rst ├── whats_new.rst ├── whats_new │ ├── v0-0-1.rst │ ├── v0-0-2.rst │ ├── v0-0-3.rst │ ├── v0-0-4.rst │ ├── v0-0-5.rst │ ├── v0-1-0.rst │ ├── v0-1-1.rst │ ├── v0-1-2.rst │ ├── v0-1-3.rst │ ├── v0-1-4.rst │ ├── v0-2-0.rst │ ├── v0-2-1.rst │ ├── v0-2-2.rst │ ├── v0-3-0.rst │ ├── v0-3-1.rst │ ├── v0-3-2.rst │ ├── v0-3-3.rst │ ├── v0-3-4.rst │ ├── v0-4-0.rst │ ├── v0-4-1.rst │ ├── v0-4-2.rst │ ├── v0-4-3-001.rst │ ├── v0-4-3-003.rst │ ├── v0-4-3.rst │ ├── v0-4-4.rst │ ├── v0-5-0.rst │ ├── v0-5-1.rst │ ├── v0-6-0.rst │ ├── v0-6-1.rst │ ├── v0-6-2.rst │ ├── v0-6-3.rst │ ├── v0-7-0.rst │ ├── v0-7-1.rst │ ├── v0-7-2.rst │ ├── v0-7-3.rst │ ├── v0-7-4.rst │ ├── v0-7-5.rst │ ├── v0-7-6-001.rst │ ├── v0-7-6.rst │ ├── v0-7-7.rst │ ├── v0-7-8-001.rst │ ├── v0-7-8-002.rst │ ├── v0-7-8.rst │ ├── v0-7-9.rst │ ├── v0-8-0-001.rst │ ├── v0-8-0.rst │ ├── v0-8-1.rst │ └── v0-8-2.rst └── zliterature.rst ├── paper.bib ├── paper.md ├── pyproject.toml ├── src └── tespy │ ├── __init__.py │ ├── components │ ├── __init__.py │ ├── basics │ │ ├── __init__.py │ │ ├── cycle_closer.py │ │ ├── sink.py │ │ ├── source.py │ │ └── subsystem_interface.py │ ├── combustion │ │ ├── __init__.py │ │ ├── base.py │ │ ├── diabatic.py │ │ └── engine.py │ ├── component.py │ ├── customs │ │ └── __init__.py │ ├── heat_exchangers │ │ ├── __init__.py │ │ ├── base.py │ │ ├── condenser.py │ │ ├── desuperheater.py │ │ ├── movingboundary.py │ │ ├── parabolic_trough.py │ │ ├── simple.py │ │ └── solar_collector.py │ ├── nodes │ │ ├── __init__.py │ │ ├── base.py │ │ ├── droplet_separator.py │ │ ├── drum.py │ │ ├── merge.py │ │ ├── separator.py │ │ └── splitter.py │ ├── piping │ │ ├── __init__.py │ │ ├── pipe.py │ │ └── valve.py │ ├── reactors │ │ ├── __init__.py │ │ ├── fuel_cell.py │ │ └── water_electrolyzer.py │ ├── subsystem.py │ └── turbomachinery │ │ ├── __init__.py │ │ ├── base.py │ │ ├── compressor.py │ │ ├── pump.py │ │ ├── steam_turbine.py │ │ └── turbine.py │ ├── connections │ ├── __init__.py │ ├── bus.py │ └── connection.py │ ├── data │ ├── ChemEx │ │ ├── Ahrendts.json │ │ ├── Szargut1988.json │ │ └── Szargut2007.json │ ├── char_lines.json │ └── char_maps.json │ ├── networks │ ├── __init__.py │ ├── network.py │ └── network_reader.py │ └── tools │ ├── __init__.py │ ├── analyses.py │ ├── characteristics.py │ ├── data_containers.py │ ├── document_models.py │ ├── fluid_properties │ ├── __init__.py │ ├── functions.py │ ├── helpers.py │ ├── mixtures.py │ └── wrappers.py │ ├── global_vars.py │ ├── helpers.py │ ├── logger.py │ └── optimization.py ├── tests ├── test_advanced_tutorials.py ├── test_analyses │ ├── test_entropy_analysis.py │ └── test_exergy_analysis.py ├── test_basic_tutorials.py ├── test_busses.py ├── test_components │ ├── test_combustion.py │ ├── test_customs.py │ ├── test_drum.py │ ├── test_heat_exchangers.py │ ├── test_merge.py │ ├── test_piping.py │ ├── test_reactors.py │ └── test_turbomachinery.py ├── test_connections.py ├── test_errors.py ├── test_heat_pump_exergy.py ├── test_models │ ├── cgam-ebsilon-results.csv │ ├── test_CGAM_model.py │ ├── test_heat_pump_model.py │ └── test_solar_energy_generating_system.py ├── test_networks │ ├── design_state │ │ ├── busses.json │ │ ├── components │ │ │ ├── CombustionChamber.csv │ │ │ ├── Compressor.csv │ │ │ ├── SimpleHeatExchanger.csv │ │ │ ├── Sink.csv │ │ │ ├── Source.csv │ │ │ └── Turbine.csv │ │ └── connections.csv │ ├── exported_nwk │ │ ├── busses.json │ │ ├── components │ │ │ ├── CombustionChamber.json │ │ │ ├── Compressor.json │ │ │ ├── SimpleHeatExchanger.json │ │ │ ├── Sink.json │ │ │ ├── Source.json │ │ │ └── Turbine.json │ │ ├── connections.json │ │ └── network.json │ ├── test_binary_incompressible.py │ ├── test_bypassing.py │ ├── test_mixing_rules.py │ └── test_network.py └── test_tools │ ├── test_characteristics.py │ ├── test_fluid_properties │ ├── test_coolprop.py │ ├── test_iapws.py │ └── test_pyromat.py │ └── test_helpers.py ├── tox.ini └── tutorial ├── README.rst ├── advanced ├── optimization_example.py ├── starting_values.py └── stepwise.py ├── basics ├── district_heating.py ├── gas_turbine.py ├── heat_pump.py └── rankine.py └── heat_pump_exergy ├── NH3.py ├── NH3_calculations.py ├── R410A.py ├── R410A_calculations.py └── plots.py /.editorconfig: -------------------------------------------------------------------------------- 1 | # see https://editorconfig.org/ 2 | root = true 3 | 4 | [*] 5 | end_of_line = lf 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | indent_style = space 9 | indent_size = 4 10 | charset = utf-8 11 | 12 | [*.{bat,cmd,ps1}] 13 | end_of_line = crlf 14 | 15 | [*.{yml,yaml}] 16 | indent_size = 2 17 | -------------------------------------------------------------------------------- /.github/workflows/packaging.yml: -------------------------------------------------------------------------------- 1 | name: packaging 2 | 3 | on: 4 | # Make sure packaging process is not broken 5 | push: 6 | branches: [main, dev] 7 | pull_request: 8 | # Make a package for release 9 | release: 10 | types: [published] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | strategy: 17 | max-parallel: 4 18 | matrix: 19 | python-version: ["3.11"] 20 | 21 | steps: 22 | - uses: actions/checkout@v1 23 | - name: Set up Python ${{ matrix.python-version }} 24 | uses: actions/setup-python@v5 25 | with: 26 | python-version: ${{ matrix.python-version }} 27 | - name: Install dependencies 28 | run: | 29 | python -m pip install --upgrade pip twine build flit 30 | - name: Create packages 31 | run: python -m build . 32 | - name: Run twine check 33 | run: twine check dist/* 34 | - uses: actions/upload-artifact@v4 35 | with: 36 | name: tox-gh-actions-dist 37 | path: dist 38 | -------------------------------------------------------------------------------- /.github/workflows/tox_checks.yml: -------------------------------------------------------------------------------- 1 | # NB: this name is used in the status badge 2 | name: tox checks 3 | 4 | on: 5 | push: 6 | branches: 7 | - main 8 | - dev 9 | pull_request: 10 | branches: 11 | - main 12 | - dev 13 | workflow_dispatch: 14 | schedule: 15 | - cron: "0 5 * * 6" # 5:00 UTC every Saturday 16 | 17 | jobs: 18 | lint: 19 | name: ${{ matrix.toxenv }} 20 | runs-on: ubuntu-latest 21 | 22 | strategy: 23 | matrix: 24 | toxenv: 25 | - check 26 | - docs 27 | 28 | steps: 29 | - name: Git clone 30 | uses: actions/checkout@v2 31 | 32 | - name: Set up Python ${{ env.default_python || '3.11' }} 33 | uses: actions/setup-python@v5 34 | with: 35 | python-version: "${{ env.default_python || '3.11' }}" 36 | 37 | - name: Pip cache 38 | uses: actions/cache@v4 39 | with: 40 | path: ~/.cache/pip 41 | key: ${{ runner.os }}-pip-${{ matrix.toxenv }}-${{ hashFiles('tox.ini', 'pyproject.toml') }} 42 | restore-keys: | 43 | ${{ runner.os }}-pip-${{ matrix.toxenv }}- 44 | ${{ runner.os }}-pip- 45 | - name: Install dependencies 46 | run: | 47 | python -m pip install -U pip 48 | python -m pip install -U tox 49 | - name: Run ${{ matrix.toxenv }} 50 | run: python -m tox -e ${{ matrix.toxenv }} 51 | -------------------------------------------------------------------------------- /.github/workflows/tox_pytest.yml: -------------------------------------------------------------------------------- 1 | name: tox pytests 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - dev 8 | pull_request: 9 | branches: 10 | - main 11 | - dev 12 | workflow_dispatch: 13 | schedule: 14 | - cron: "0 5 * * 6" # 5:00 UTC every Saturday 15 | 16 | jobs: 17 | pytest: 18 | runs-on: ubuntu-latest 19 | strategy: 20 | matrix: 21 | python-version: ["3.9", "3.10", "3.11"] 22 | 23 | steps: 24 | - uses: actions/checkout@v1 25 | - name: Set up Python ${{ matrix.python-version }} 26 | uses: actions/setup-python@v5 27 | with: 28 | python-version: ${{ matrix.python-version }} 29 | - name: Install dependencies 30 | run: | 31 | python -m pip install --upgrade pip 32 | pip install tox tox-gh-actions coverage coveralls 33 | - name: Test with tox 34 | run: tox 35 | 36 | - name: Check test coverage 37 | run: coverage report -m --fail-under=${{ matrix.vcs == 'bzr' && 84 || 85 }} 38 | 39 | - name: Report to coveralls 40 | run: coveralls 41 | env: 42 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 43 | COVERALLS_SERVICE_NAME: github 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | __pycache__ 3 | 4 | # C extensions 5 | *.so 6 | 7 | # Packages 8 | *.egg 9 | *.egg-info 10 | dist 11 | build 12 | eggs 13 | .eggs 14 | parts 15 | bin 16 | var 17 | sdist 18 | wheelhouse 19 | develop-eggs 20 | .installed.cfg 21 | lib 22 | lib64 23 | venv*/ 24 | pyvenv*/ 25 | pip-wheel-metadata/ 26 | 27 | # Installer logs 28 | pip-log.txt 29 | 30 | # Unit test / coverage reports 31 | .coverage 32 | .tox 33 | .coverage.* 34 | .pytest_cache/ 35 | nosetests.xml 36 | coverage.xml 37 | htmlcov 38 | 39 | # Translations 40 | *.mo 41 | 42 | # VS code 43 | .vscode 44 | 45 | # Sphinx 46 | docs/_build 47 | 48 | .DS_Store 49 | *~ 50 | .*.sw[po] 51 | .build 52 | .ve 53 | .env 54 | .cache 55 | .pytest 56 | .benchmarks 57 | .bootstrap 58 | .appveyor.token 59 | *.bak 60 | -------------------------------------------------------------------------------- /.pep8speaks.yml: -------------------------------------------------------------------------------- 1 | scanner: 2 | diff_only: True # If False, the entire file touched by the Pull Request is scanned for errors. If True, only the diff is scanned. 3 | linter: pycodestyle # Alternative option - flake8 4 | 5 | pycodestyle: # Valid if scanner.linter is pycodestyle 6 | max-line-length: 79 7 | ignore: [] # Errors and warnings to ignore 8 | exclude: [] # File path patterns to exclude 9 | count: False 10 | first: False 11 | show-pep8: False 12 | show-source: False 13 | statistics: False 14 | hang-closing: False 15 | filename: [] 16 | select: [] 17 | 18 | flake8: # Valid if scanner.linter is flake8 19 | max-line-length: 79 20 | ignore: [] 21 | exclude: [] 22 | count: False 23 | show-source: False 24 | statistics: False 25 | hang-closing: False 26 | filename: [] 27 | select: [] 28 | 29 | no_blank_comment: True # If True, no comment is made on PR without any errors. 30 | descending_issues_order: False # If True, PEP 8 issues in message will be displayed in descending order of line numbers in the file 31 | only_mention_files_with_errors: True # If False, a separate status section for each file is made in the comment. 32 | 33 | message: # Customize the comment made by the bot 34 | opened: # Messages when a new PR is submitted 35 | header: "" 36 | footer: "" 37 | updated: # Messages when a PR is updated 38 | header: "" 39 | footer: "" 40 | no_errors: "There are currently no PEP 8 issues detected in this Pull Request. Cheers! :beers: " 41 | 42 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 2 | version: 2 3 | sphinx: 4 | configuration: docs/conf.py 5 | # formats: all ## none appart from html required here 6 | python: 7 | install: 8 | - method: pip 9 | path: . 10 | extra_requirements: 11 | - dev 12 | build: 13 | os: ubuntu-22.04 14 | tools: 15 | python: "3.10" 16 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the [project team](https://oemof.org/contact/). The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | The developer rules can be found in the 2 | [online documentation](https://tespy.readthedocs.io/). 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Francesco Witte 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **General** 2 | 3 | Describe your pull request as transparent as possible: 4 | 5 | * What functionality does it implement? 6 | * Where is it located? 7 | * How does the API look? 8 | * Which bugs are fixed 9 | * Are there related issues? 10 | 11 | **Documentation** 12 | 13 | Please document all changes and/or new features: 14 | 15 | * Update the API documentation 16 | * Update the corresponding sections in the online documentation 17 | * Add inline comments to your code, if required 18 | * Update the corresponding What's New file 19 | 20 | **Testing** 21 | 22 | * Adapt the software tests (including doc-tests), if the PR does affect existing tests 23 | * Add new tests for new features 24 | 25 | **Questions and Comments** 26 | 27 | You are welcome to ask for help or start a discussion on a feature. We very much appreciate your contribution. 28 | -------------------------------------------------------------------------------- /docs/_static/css/custom.css: -------------------------------------------------------------------------------- 1 | .tight-table td { 2 | white-space: normal !important; 3 | } 4 | 5 | article p { 6 | text-align: justify; 7 | } 8 | 9 | figure figcaption p { 10 | text-align: center; 11 | font-weight: bold; 12 | } 13 | -------------------------------------------------------------------------------- /docs/_static/images/examples/heatpumps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oemof/tespy/4884e4db70c3c3bc26be31b9c3fb22534c0d7789/docs/_static/images/examples/heatpumps.png -------------------------------------------------------------------------------- /docs/_static/images/examples/heatpumps_darkmode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oemof/tespy/4884e4db70c3c3bc26be31b9c3fb22534c0d7789/docs/_static/images/examples/heatpumps_darkmode.png -------------------------------------------------------------------------------- /docs/_static/js/custom.js: -------------------------------------------------------------------------------- 1 | function removeAnnouncementBanner() { 2 | var banner = document.getElementsByClassName("announcement") 3 | banner[0].remove() 4 | }; 5 | 6 | 7 | window.addEventListener('load', async () => { 8 | const elmnt = document.querySelector('div[oemof-announcement]') 9 | const response = await fetch(elmnt.getAttribute('oemof-announcement')) 10 | if (response.status === 200) { 11 | elmnt.innerHTML = ( 12 | await response.text() 13 | ) 14 | if (elmnt.innerHTML.length === 0) { 15 | removeAnnouncementBanner() 16 | } 17 | } else if (response.status === 404) { 18 | removeAnnouncementBanner() 19 | } 20 | }) -------------------------------------------------------------------------------- /docs/_templates/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oemof/tespy/4884e4db70c3c3bc26be31b9c3fb22534c0d7789/docs/_templates/index.html -------------------------------------------------------------------------------- /docs/advanced/optimization.rst: -------------------------------------------------------------------------------- 1 | .. _tespy_advanced_optimization_label: 2 | 3 | Optimization with pygmo 4 | ======================= 5 | -------------------------------------------------------------------------------- /docs/api.rst: -------------------------------------------------------------------------------- 1 | ~~~~~~~~~~~~~~~~~ 2 | API Documentation 3 | ~~~~~~~~~~~~~~~~~ 4 | 5 | All component and connection property equations derive from balance equations 6 | for fluid composition, mass flow and energy in regarding thermal as well as 7 | hydraulic state and thermodynamic fluid property equations respectively. 8 | Standard literature is for example :cite:`Baehr2016,Epple2012,Bswirth2012` 9 | (German) :cite:`Epple2017` (English). Equations and properties from other 10 | sources are cited individually. 11 | 12 | .. toctree:: 13 | :maxdepth: 1 14 | :glob: 15 | 16 | api/* 17 | -------------------------------------------------------------------------------- /docs/api/connections.rst: -------------------------------------------------------------------------------- 1 | tespy.connections module 2 | ======================== 3 | 4 | .. automodule:: tespy.connections 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | 9 | tespy.connections.bus module 10 | ---------------------------- 11 | 12 | .. automodule:: tespy.connections.bus 13 | :members: 14 | :undoc-members: 15 | :show-inheritance: 16 | 17 | tespy.connections.connection module 18 | ----------------------------------- 19 | 20 | .. automodule:: tespy.connections.connection 21 | :members: 22 | :undoc-members: 23 | :show-inheritance: 24 | -------------------------------------------------------------------------------- /docs/api/networks.rst: -------------------------------------------------------------------------------- 1 | tespy.networks module 2 | ===================== 3 | 4 | .. automodule:: tespy.networks 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | 9 | tespy.networks.network module 10 | ----------------------------- 11 | 12 | .. automodule:: tespy.networks.network 13 | :members: 14 | :undoc-members: 15 | :show-inheritance: 16 | 17 | tespy.networks.network_reader module 18 | ------------------------------------ 19 | 20 | .. automodule:: tespy.networks.network_reader 21 | :members: 22 | :undoc-members: 23 | :show-inheritance: 24 | -------------------------------------------------------------------------------- /docs/api/tools.rst: -------------------------------------------------------------------------------- 1 | tespy.tools module 2 | ================== 3 | 4 | .. automodule:: tespy.tools 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | 9 | tespy.tools.analyses module 10 | --------------------------- 11 | 12 | .. automodule:: tespy.tools.analyses 13 | :members: 14 | :undoc-members: 15 | :show-inheritance: 16 | 17 | tespy.tools.characteristics module 18 | ---------------------------------- 19 | 20 | .. automodule:: tespy.tools.characteristics 21 | :members: 22 | :undoc-members: 23 | :show-inheritance: 24 | 25 | tespy.tools.data_containers module 26 | ---------------------------------- 27 | 28 | .. automodule:: tespy.tools.data_containers 29 | :members: 30 | :undoc-members: 31 | :show-inheritance: 32 | 33 | tespy.tools.document_models module 34 | ---------------------------------- 35 | 36 | .. automodule:: tespy.tools.document_models 37 | :members: 38 | :undoc-members: 39 | :show-inheritance: 40 | 41 | tespy.tools.fluid_properties.functions module 42 | --------------------------------------------- 43 | 44 | .. automodule:: tespy.tools.fluid_properties.functions 45 | :members: 46 | :undoc-members: 47 | :show-inheritance: 48 | 49 | tespy.tools.fluid_properties.helpers module 50 | ------------------------------------------- 51 | 52 | .. automodule:: tespy.tools.fluid_properties.helpers 53 | :members: 54 | :undoc-members: 55 | :show-inheritance: 56 | 57 | tespy.tools.fluid_properties.mixtures module 58 | -------------------------------------------- 59 | 60 | .. automodule:: tespy.tools.fluid_properties.mixtures 61 | :members: 62 | :undoc-members: 63 | :show-inheritance: 64 | 65 | tespy.tools.fluid_properties.wrappers module 66 | -------------------------------------------- 67 | 68 | .. automodule:: tespy.tools.fluid_properties.wrappers 69 | :members: 70 | :undoc-members: 71 | :show-inheritance: 72 | 73 | tespy.tools.helpers module 74 | -------------------------- 75 | 76 | .. automodule:: tespy.tools.helpers 77 | :members: 78 | :undoc-members: 79 | :show-inheritance: 80 | 81 | tespy.tools.logger module 82 | ------------------------- 83 | 84 | .. automodule:: tespy.tools.logger 85 | :members: 86 | :undoc-members: 87 | :show-inheritance: 88 | 89 | tespy.tools.optimization module 90 | ------------------------------- 91 | 92 | .. automodule:: tespy.tools.optimization 93 | :members: 94 | :undoc-members: 95 | :show-inheritance: 96 | -------------------------------------------------------------------------------- /docs/basics.rst: -------------------------------------------------------------------------------- 1 | .. _tespy_basics_label: 2 | 3 | Modeling Basic Systems 4 | ~~~~~~~~~~~~~~~~~~~~~~ 5 | 6 | In this section we will introduce how to create your first simple TESPy models. 7 | In the intro part you learn about the modeling concept of TESPy. The other 8 | subsections are step by step walkthroughs for well-known thermodynamic 9 | applications. 10 | 11 | If you want to learn more about the details of the different parts of the 12 | software, you should also have a look at the 13 | :ref:`Documentation section ` after the first steps. If 14 | you have any questions please reach out to the 15 | :ref:`TESPy community `. There are regular online 16 | meetings as well as a discussion forum on GitHub. 17 | 18 | .. toctree:: 19 | :maxdepth: 1 20 | :hidden: 21 | 22 | basics/intro.rst 23 | basics/heat_pump.rst 24 | basics/rankine_cycle.rst 25 | basics/gas_turbine.rst 26 | basics/district_heating.rst 27 | 28 | 29 | .. card:: Introduction: Learn the basic modeling concept of TESPy 30 | :link: tespy_basics_intro_label 31 | :link-type: ref 32 | 33 | .. figure:: /_static/images/basics/modeling_concept.svg 34 | :align: center 35 | :alt: TESPy's modeling concept 36 | 37 | .. grid:: 2 38 | :gutter: 1 39 | 40 | .. grid-item-card:: Heat Pump 41 | :link: tespy_basics_heat_pump_label 42 | :link-type: ref 43 | 44 | .. image:: /_static/images/basics/heat_pump.svg 45 | :class: only-light 46 | 47 | .. image:: /_static/images/basics/heat_pump_darkmode.svg 48 | :class: only-dark 49 | 50 | .. grid-item-card:: Clausius Rankine Cycle 51 | :link: tespy_basics_rankine_cycle_label 52 | :link-type: ref 53 | 54 | .. image:: /_static/images/basics/rankine_cycle.svg 55 | :class: only-light 56 | 57 | .. image:: /_static/images/basics/rankine_cycle_darkmode.svg 58 | :class: only-dark 59 | 60 | .. grid:: 2 61 | :gutter: 1 62 | 63 | .. grid-item-card:: Gas Turbine 64 | :link: tespy_basics_gas_turbine_label 65 | :link-type: ref 66 | 67 | .. image:: /_static/images/basics/gas_turbine.svg 68 | :class: only-light 69 | 70 | .. image:: /_static/images/basics/gas_turbine_darkmode.svg 71 | :class: only-dark 72 | 73 | .. grid-item-card:: District Heating System 74 | :link: tespy_basics_district_heating_label 75 | :link-type: ref 76 | 77 | .. image:: /_static/images/basics/district_heating.svg 78 | :class: only-light 79 | 80 | .. image:: /_static/images/basics/district_heating_darkmode.svg 81 | :class: only-dark 82 | -------------------------------------------------------------------------------- /docs/benchmarks.rst: -------------------------------------------------------------------------------- 1 | Benchmarks 2 | ========== 3 | To ensure credibility as well as reproducibility for the software, several 4 | measures are taken. The most important information is listed below: 5 | 6 | Model Validation 7 | ---------------- 8 | TESPy has been used to model several research and engineering applications. In 9 | the paper on integration of generic exergy analysis in TESPy 10 | :cite:`Witte2022` three models have been built from literature sources: A 11 | solar thermal power plant, a supercritical CO2 Brayton cycle as well as a 12 | refrigeration machine using air as working fluid. 13 | 14 | For the solar thermal power plant we have created a full model of the plant 15 | using a standard industry software in parallel. **The comparison showed** 16 | **identical results**. For the other two applications we have compared the 17 | results of the TESPy model with the data published in the respective research 18 | paper and found very well matching results. Differences can be explained by 19 | different implementations of the fluid property back end. 20 | 21 | Finally, in the extension of the exergy analysis to chemical exergy 22 | :cite:`Hofmann2022` we have also compared results of the CGAM process 23 | :cite:`Valero1994` modeled in TESPy with a full model using industry software 24 | and with the data provided from literature as well :cite:`Bejan1996`. 25 | 26 | The code for the full models is accessible open source on GitHub: 27 | 28 | - `So called "Solar Energy Generating System" `__ 29 | - `Supercritical CO2 power cycle `__ 30 | - `Air refrigeration machine `__ 31 | - `CGAM process `__ 32 | 33 | 34 | Unit testing 35 | ------------ 36 | On top of the full model validation, the software includes full unit testing. 37 | Here, single features of the software are tested by comparing the result the 38 | software provides with the result we would expect when manually modeling that 39 | feature. For example, we set up a turbine and check, whether the isentropic 40 | efficiency specification in the TESPy component matches the results that is 41 | expected doing the same process manually. This is done for all modules of the 42 | software. 43 | 44 | Continuous Integration 45 | ---------------------- 46 | TESPy has a 47 | `Continuous Integration `__ 48 | pipeline. The unit tests and the full model tests are automatically run 49 | whenever changes to the source code of the software are made. By this we can 50 | ensure, that changes in the code do not break with existing features or 51 | invalidate results of the existing models. 52 | 53 | For more information on how to run the tests please see the 54 | :ref:`how to develop ` section. 55 | -------------------------------------------------------------------------------- /docs/development/what.rst: -------------------------------------------------------------------------------- 1 | .. _tespy_development_what_label: 2 | 3 | What can I contribute? 4 | ====================== 5 | TESPy has been developed mainly by Francesco Witte at the University of Applied 6 | Sciences Flensburg - and since 2021 with a lot of free time. The goal is, that 7 | many people can make use of this project and that it will be a community driven 8 | project in the future, as users might demand special components or flexible 9 | implementations of characteristics, custom equations, basically what ever you 10 | can think of. 11 | 12 | Therefore, I would like to invite you to contribute in this process, share your 13 | ideas and experience and maybe start developing the software. Your solutions 14 | may help other users as well. Contributing to the development of TESPy is easy 15 | and will help the development team and all other users of the software. If you 16 | start to develop features it may also improve the quality of your code as it 17 | will be reviewed by other developers. 18 | 19 | There are a variety of different ways you can contribute to the development, 20 | amongst others, these may be: 21 | 22 | Contribute to the documentation 23 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 24 | The easiest way of joining the developing process is by improving the 25 | documentation. If you spot mistakes or think, the documentation could be more 26 | precise or clear in some sections, feel free to fix it and create a pull 27 | request on the GitHub repository. 28 | 29 | If you come across typos or grammatical mistakes or want to improve 30 | comprehensibility of the documentation, make your adjustments or suggestions 31 | and create a pull request for the dev branch. We appreciate your contribution! 32 | 33 | Share your projects 34 | ^^^^^^^^^^^^^^^^^^^ 35 | You have used the software in your research paper or project, maybe even in a 36 | real world application? We would love to feature your project on our 37 | :ref:`Example Applications ` page. Please reach out to 38 | us by opening a new issue on our GitHub page. 39 | 40 | Add new component equations 41 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 42 | The components equations represent the behavior of each component. Do you miss 43 | equations? Open a discussion on the GitHub discussions page or add them to your 44 | fork of TESPy and create a pull request on the dev branch. 45 | 46 | Sponsor the development 47 | ^^^^^^^^^^^^^^^^^^^^^^^ 48 | As mentioned above, I maintain and develop this project in my free time. If you 49 | would like to support me by sponsoring a coffee for late night sessions or need 50 | direct support for your projects using TESPy, you sponsor me on GitHub 51 | https://github.com/fwitte or reach out to me via e-mail. 52 | 53 | Add component characteristics 54 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 55 | Another highly appreciated way for you to contribute is the provision of new 56 | and/or improved characteristics for single components, such as compressor 57 | efficiency maps, characteristics for turbine efficiency or heat transfer 58 | coefficients etc.. 59 | 60 | The component characteristics represent large added value for your calculation. 61 | If you have detailed information on components offdesign behavior - even for 62 | specific cases - it will improve the results. Every user can benefit from this 63 | knowledge, and thus we are very happy to discuss the implementation of new 64 | characteristics. 65 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. _tespy_label: 2 | 3 | .. include:: introduction.rst 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :hidden: 8 | 9 | introduction 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | :caption: User Guide 14 | :hidden: 15 | 16 | installation 17 | basics 18 | tutorials 19 | examples 20 | regular_meeting 21 | 22 | .. toctree:: 23 | :maxdepth: 2 24 | :caption: Documentation 25 | :hidden: 26 | 27 | modules 28 | benchmarks 29 | api 30 | whats_new 31 | zliterature 32 | 33 | .. toctree:: 34 | :maxdepth: 2 35 | :caption: Advanced Features 36 | :hidden: 37 | 38 | advanced/exergy 39 | 40 | .. toctree:: 41 | :maxdepth: 2 42 | :caption: Contribute to TESPy 43 | :hidden: 44 | 45 | development/what 46 | development/how 47 | -------------------------------------------------------------------------------- /docs/installation.rst: -------------------------------------------------------------------------------- 1 | .. _installation_and_setup_label: 2 | 3 | ###################### 4 | Installation and setup 5 | ###################### 6 | 7 | Following you find guidelines for the installation process for linux and 8 | windows. TESPy is a Python package, thus it requires you to have Python 3 9 | installed. 10 | 11 | .. tab-set:: 12 | 13 | .. tab-item:: Linux 14 | 15 | **Installing Python 3** 16 | 17 | Most Linux distributions will have Python 3 in their repository. Use the 18 | specific software management to install it, if it is not yet installed. If 19 | you are using Ubuntu/Debian try executing the following code in your 20 | terminal: 21 | 22 | .. code:: console 23 | 24 | sudo apt-get install python3 25 | 26 | You can also download different versions of Python via 27 | https://www.python.org/downloads/. 28 | 29 | **Having Python 3 installed** 30 | 31 | We recommend installing TESPy within a virtual Python environment and not 32 | into the base, system-wide Python installation. On Linux you can use 33 | virtualenv to do so. 34 | 35 | 1. Install virtualenv using the package management of your Linux distribution, 36 | pip install or install it from source 37 | (`see virtualenv documentation `_) 38 | 2. Open terminal to create and activate a virtual environment by typing: 39 | 40 | .. code-block:: console 41 | 42 | virtualenv -p /usr/bin/python3 your_env_name 43 | source your_env_name/bin/activate 44 | 45 | 3. In terminal type: :code:`pip install tespy` 46 | 47 | Warning: If you have an older version of virtualenv you should update pip 48 | :code:`pip install --upgrade pip`. 49 | 50 | **Using Conda** 51 | 52 | Alternatively you can use conda for environment and package management. You 53 | can follow the installation instructions for windows users. 54 | 55 | .. tab-item:: Windows 56 | 57 | For windows we recommend using conda as package manager. You can download a 58 | lightweight open source variant of conda: "miniforge3". 59 | 60 | 1. Download latest `miniforge3 `__ 61 | for Python 3.x (64 or 32 bit). 62 | 2. Install miniforge3 63 | 3. Open "miniforge prompt" to manage your virtual environments. You can 64 | create a new environment and acivate it by 65 | 66 | .. code-block:: console 67 | 68 | conda create -n tespy-env python=3.9 69 | activate tespy-env 70 | 71 | 4. In the active prompt type: :code:`pip install tespy` 72 | 73 | .. tab-item:: Developer Version 74 | 75 | If you would like to get access to not yet released features or features 76 | under development you can install the developer version. The steps are 77 | similar to the steps here, but INSTEAD of installing TESPy using 78 | 79 | .. code-block:: console 80 | 81 | pip install tespy 82 | 83 | follow the instructions on :ref:`this page `. 84 | -------------------------------------------------------------------------------- /docs/introduction.rst: -------------------------------------------------------------------------------- 1 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 | Thermal Engineering Systems in Python 3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 | 5 | TESPy stands for "Thermal Engineering Systems in Python" and provides a 6 | powerful simulation toolkit for thermal engineering plants such as various 7 | types of power plants (including organic rankine cycles), heat pumps or 8 | refrigeration machines. Due to its flexibility it is actually possible to 9 | model any kind of thermal energy conversion process, this also includes energy 10 | balancing of industrial processes, district heating or HVAC systems. It is 11 | part of the Open Energy Modelling Framework `oemof `_ and 12 | can be used as a standalone package. 13 | 14 | .. image:: /_static/images/logo_tespy_big.svg 15 | :align: center 16 | :class: only-light 17 | 18 | 19 | .. image:: /_static/images/logo_tespy_big_darkmode.svg 20 | :align: center 21 | :class: only-dark 22 | 23 | With the TESPy package you are able to calculate stationary operation in order 24 | to design the process of your plant. From that point it is possible to 25 | predict the offdesign behavior of your plant using underlying characteristics 26 | for each of the plants components. For now, the package includes basic 27 | components, such as turbines, pumps, compressors, heat exchangers, pipes, 28 | mixers and splitters as well as some advanced components 29 | (derivatives of heat exchangers, drum). 30 | 31 | Everybody is welcome to use and/or develop TESPy. Contribution is already 32 | possible on a low level by simply fixing typos in TESPy's documentation or 33 | rephrasing sections which are unclear. If you want to support us that way 34 | please fork the `TESPy repository `_ to your 35 | own GitHub account and make changes as described in the GitHub guidelines: 36 | https://guides.github.com/activities/hello-world/ 37 | 38 | Key Features 39 | ============ 40 | * **Open** Source 41 | * **Generic** thermal engineering applications 42 | * **Extendable** framework for the implementation of custom components, fluid 43 | property formulations and equations 44 | * **Integration** of optimization capabilities through an API to pygmo 45 | * **Postprocessing** features like exergy analysis and fluid property plotting 46 | 47 | Quick installation 48 | ================== 49 | 50 | If you have a working Python3 environment, use pypi to install the latest 51 | tespy version. 52 | 53 | .. code:: bash 54 | 55 | pip install tespy 56 | 57 | We provide more detailed 58 | :ref:`installation instructions `, too. 59 | 60 | If you want to use the latest features, you might want to install the 61 | **developer version**. See 62 | :ref:`this section ` for more information. 63 | 64 | Getting into TESPy 65 | ================== 66 | 67 | For a good start on how TESPy works and how you can use it, we provide some 68 | :ref:`basic ` and :ref:`advanced ` 69 | tutorials in the User Guide section. The 70 | :ref:`modules ` section provides you with in depth 71 | information on the different modules of TESPy. 72 | 73 | Citation 74 | ======== 75 | 76 | The scope and functionalities of TESPy have been documented in a paper 77 | published in the Journal of Open Source Software with an Open-Access license. 78 | Download the paper from https://doi.org/10.21105/joss.02178 :cite:`Witte2020`. 79 | As TESPy is a free software, we kindly ask that you add a reference to TESPy 80 | if you use the software for your scientific work. Please cite the article with 81 | the BibTeX citation below. 82 | 83 | BibTeX citation 84 | 85 | .. code:: 86 | 87 | @article{Witte2020, 88 | doi = {10.21105/joss.02178}, 89 | year = {2020}, 90 | publisher = {The Open Journal}, 91 | volume = {5}, 92 | number = {49}, 93 | pages = {2178}, 94 | author = {Francesco Witte and Ilja Tuschy}, 95 | title = {{TESPy}: {T}hermal {E}ngineering {S}ystems in {P}ython}, 96 | journal = {Journal of Open Source Software} 97 | } 98 | 99 | Additionally, you have the possibility to cite a specific version of TESPy to 100 | make your work reproducible. The source code of every version is published on 101 | zenodo. Find your version here: https://doi.org/10.5281/zenodo.2555866. 102 | 103 | License 104 | ======= 105 | 106 | .. include:: ../LICENSE 107 | -------------------------------------------------------------------------------- /docs/modules.rst: -------------------------------------------------------------------------------- 1 | .. _tespy_modules_label: 2 | 3 | ~~~~~~~~~~~~~ 4 | TESPy modules 5 | ~~~~~~~~~~~~~ 6 | 7 | The following sections give a detailed overview on the modules of TESPy. This 8 | includes all important settings of networks, components and connections as well 9 | as the underlying functionalities of the software. 10 | 11 | .. toctree:: 12 | :maxdepth: 1 13 | :glob: 14 | :hidden: 15 | 16 | modules/networks.rst 17 | modules/components.rst 18 | modules/connections.rst 19 | modules/characteristics.rst 20 | modules/fluid_properties.rst 21 | modules/ude.rst 22 | 23 | 24 | .. grid:: 2 25 | :gutter: 1 26 | 27 | .. grid-item-card:: Network 28 | :link: tespy_modules_networks_label 29 | :link-type: ref 30 | 31 | .. image:: /_static/images/basics/modeling_concept.svg 32 | 33 | .. grid-item-card:: Components and Component Groups 34 | :link: tespy_modules_components_label 35 | :link-type: ref 36 | 37 | .. image:: /_static/images/modules/subsystem_waste_heat_generator.svg 38 | :class: only-light 39 | 40 | .. image:: /_static/images/modules/subsystem_waste_heat_generator_darkmode.svg 41 | :class: only-dark 42 | 43 | .. grid:: 2 44 | :gutter: 1 45 | 46 | .. grid-item-card:: Connections 47 | :link: tespy_modules_connections_label 48 | :link-type: ref 49 | 50 | .. image:: /_static/images/modules/connections.svg 51 | :class: only-light 52 | 53 | .. image:: /_static/images/modules/connections_darkmode.svg 54 | :class: only-dark 55 | 56 | .. grid-item-card:: Characteristics 57 | :link: tespy_modules_characteristics_label 58 | :link-type: ref 59 | 60 | .. image:: /_static/images/modules/characteristics.svg 61 | :class: only-light 62 | 63 | .. image:: /_static/images/modules/characteristics_darkmode.svg 64 | :class: only-dark 65 | 66 | 67 | .. grid:: 2 68 | :gutter: 1 69 | 70 | .. grid-item-card:: Fluid Properties 71 | :link: tespy_fluid_properties_label 72 | :link-type: ref 73 | 74 | .. image:: /_static/images/modules/fluid_properties.svg 75 | :class: only-light 76 | 77 | .. image:: /_static/images/modules/fluid_properties_darkmode.svg 78 | :class: only-dark 79 | 80 | .. grid-item-card:: User Defined Equations 81 | :link: tespy_ude_label 82 | :link-type: ref 83 | 84 | .. image:: /_static/images/modules/ude.svg 85 | :class: only-light 86 | 87 | .. image:: /_static/images/modules/ude_darkmode.svg 88 | :class: only-dark 89 | -------------------------------------------------------------------------------- /docs/regular_meeting.rst: -------------------------------------------------------------------------------- 1 | .. _tespy_community_label: 2 | 3 | ############### 4 | TESPy community 5 | ############### 6 | 7 | Online "Stammtisch" 8 | =================== 9 | We have decided to start a reoccurring "Stammtisch" meeting for all interested 10 | TESPy users and (potential) developers. You are invited to join us on every 3rd 11 | Monday of a month at 17:00 CE(S)T for a casual get together. The intent of this 12 | meeting is to establish a more active and well connected network of TESPy users 13 | and developers. 14 | 15 | If you are interested, you can simply join the meeting at 16 | https://meet.jit.si/tespy_user_meeting. We are looking forward to seeing you! 17 | 18 | User forum 19 | ========== 20 | We have implemented a 21 | `discussion room on GitHub `__ as 22 | user forum. If you have issues with setting up your model or any other question 23 | about using the software, you are invited to start a discussion there. 24 | -------------------------------------------------------------------------------- /docs/scripts/generate_tespy_data_module.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import json 4 | 5 | from matplotlib import pyplot as plt 6 | from pkg_resources import resource_filename 7 | 8 | import tespy 9 | 10 | 11 | def get_char_data(filename): 12 | path = resource_filename('tespy.data', filename + '.json') 13 | 14 | with open(path) as f: 15 | data = json.load(f) 16 | 17 | return data 18 | 19 | 20 | def plot_line(component, parameter, name, data): 21 | 22 | char = tespy.tools.characteristics.CharLine(x=data['x'], y=data['y']) 23 | 24 | title = ('Characteristic line "' + name + '" for parameter "' + 25 | parameter + '".') 26 | xlabel = '$X$' 27 | ylabel = r'$f\left(X\right)$' 28 | 29 | path = component + '_' + parameter + '_' + name + '.svg' 30 | char.plot(path.replace(' ', '_'), title, xlabel, ylabel) 31 | 32 | 33 | def plot_map(component, parameter, name, data): 34 | 35 | char = tespy.tools.characteristics.CharMap( 36 | x=data['x'], y=data['y'], z=data['z']) 37 | 38 | title = ('Characteristic line "' + name + '" for parameter "' + 39 | parameter + '".') 40 | xlabel = '$Y$' 41 | ylabel = r'$f\left(X,Y\right)$' 42 | 43 | path = component + '_' + parameter + '_' + name + '.svg' 44 | char.plot(path.replace(' ', '_'), title, xlabel, ylabel) 45 | 46 | 47 | def generate_api_doc(component, parameter, name, char_type, ref): 48 | path = '_images/' + component + '_' + parameter + '_' + name + '.svg' 49 | rst = ( 50 | '.. figure:: ' + path.replace(' ', '_') + '\n' 51 | ' :alt: Characteristic ' + char_type + ' "' + name + 52 | '" for parameter "' + parameter + '".\n' 53 | ' :align: center\n\n' 54 | ) 55 | if ref: 56 | rst += ' Reference: :cite:`' + ref + '`.\n\n' 57 | else: 58 | rst += ' Reference: Generic data.\n\n' 59 | 60 | return rst 61 | 62 | 63 | rst = ( 64 | 'tespy.data module\n' 65 | '=================\n\n' 66 | ) 67 | 68 | rst += ( 69 | 'Module contents\n' 70 | '---------------\n\n' 71 | '.. automodule:: tespy.data\n' 72 | ' :members:\n' 73 | ' :undoc-members:\n' 74 | ' :show-inheritance:\n\n' 75 | 'Default characteristics\n' 76 | '-----------------------\n\n' 77 | ) 78 | 79 | rst += ( 80 | 'Characteristic lines\n' 81 | '^^^^^^^^^^^^^^^^^^^^\n' 82 | ) 83 | 84 | for component, params in get_char_data('char_lines').items(): 85 | rst += '**' + component + '**\n\n' 86 | for param, lines in params.items(): 87 | for line, data in lines.items(): 88 | plot_line(component, param, line, data) 89 | rst += generate_api_doc( 90 | component, param, line, 'line', data['ref']) 91 | 92 | rst += ( 93 | 'Characteristic maps\n' 94 | '^^^^^^^^^^^^^^^^^^^\n\n' 95 | ) 96 | 97 | for component, params in get_char_data('char_maps').items(): 98 | rst += '**' + component + '**\n\n' 99 | for param, chars in params.items(): 100 | for char, data in chars.items(): 101 | plot_map(component, param, char, data) 102 | rst += generate_api_doc(component, param, char, 'map', data['ref']) 103 | 104 | with open('tespy.data.rst', 'w') as f: 105 | f.write(rst) 106 | f.close() 107 | -------------------------------------------------------------------------------- /docs/tutorials.rst: -------------------------------------------------------------------------------- 1 | .. _tespy_tutorial_label: 2 | 3 | ~~~~~~~~~~~~~~~~~~ 4 | Advanced Tutorials 5 | ~~~~~~~~~~~~~~~~~~ 6 | We provide more advanced tutorials for you to better understand how to work 7 | with more complex systems in TESPy. 8 | 9 | At the example of different heat pump topologies, you will learn to 10 | 11 | - create a more complex model *step by step* and get the idea of designing a 12 | plant and calculating the offdesign behavior. 13 | - set up a code structure, which allows you to generate stable starting values 14 | flexibly, helping you to build reliable setups faster. 15 | - use the inbuilt exergy analysis method in a simple geothermal heat pump 16 | setting. 17 | 18 | Furthermore, we introduce the coupling of TESPy with pygmo in order to create 19 | an optimization problem, which optimizes thermal efficiency of a Clausius 20 | Rankine power plant. Also, there is a tutorial on the implementation of an air 21 | source heat pump in an energy system dispatch optimization problem using 22 | `oemof-solph `__. For that tutorial an air 23 | source heat pump is implemented in various details of modeling complexity and 24 | the results are transferred to the energy system optimization problem. 25 | 26 | If you have any questions, ideas for other tutorials or feedback, please reach 27 | out to us. We are looking forward to hearing from you! 28 | 29 | .. grid:: 2 30 | :gutter: 1 31 | 32 | .. grid-item-card:: Build complex systems step by step 33 | :link: tespy_tutorial_heat_pump_label 34 | :link-type: ref 35 | 36 | .. image:: /_static/images/tutorials/heat_pump_stepwise/flowsheet.svg 37 | :class: only-light 38 | 39 | .. image:: /_static/images/tutorials/heat_pump_stepwise/flowsheet_darkmode.svg 40 | :class: only-dark 41 | 42 | .. grid-item-card:: Generate stable starting values 43 | :link: tespy_tutorial_starting_values_label 44 | :link-type: ref 45 | 46 | .. image:: /_static/images/tutorials/heat_pump_starting_values/COP_by_wf.svg 47 | :class: only-light 48 | 49 | .. image:: /_static/images/tutorials/heat_pump_starting_values/COP_by_wf_darkmode.svg 50 | :class: only-dark 51 | 52 | .. grid:: 2 53 | :gutter: 1 54 | 55 | .. grid-item-card:: Exergy analysis of a heat pump 56 | :link: tespy_tutorial_heat_pump_exergy_label 57 | :link-type: ref 58 | 59 | .. image:: /_static/images/tutorials/heat_pump_exergy/diagram_E_D.svg 60 | :class: only-light 61 | 62 | .. image:: /_static/images/tutorials/heat_pump_exergy/diagram_E_D_darkmode.svg 63 | :class: only-dark 64 | 65 | .. grid-item-card:: Integration of an air source heat pump in energy system optimization 66 | :link: https://oemof.github.io/heat-pump-tutorial/ 67 | 68 | .. image:: /_static/images/tutorials/osmses-2023.svg 69 | :class: only-light 70 | 71 | .. image:: /_static/images/tutorials/osmses-2023_darkmode.svg 72 | :class: only-dark 73 | 74 | 75 | .. grid:: 2 76 | :gutter: 1 77 | 78 | .. grid-item-card:: Optimization of a thermal power plant 79 | :link: tespy_tutorial_pygmo_optimization_label 80 | :link-type: ref 81 | 82 | .. image:: /_static/images/tutorials/pygmo_optimization/pygmo_optimization.svg 83 | :class: only-light 84 | 85 | .. image:: /_static/images/tutorials/pygmo_optimization/pygmo_optimization_darkmode.svg 86 | :class: only-dark 87 | 88 | .. grid-item-card:: Gas Turbine with Heat Recovery Steam Generator 89 | 90 | Coming soon! 91 | 92 | 93 | .. toctree:: 94 | :maxdepth: 1 95 | :glob: 96 | :hidden: 97 | 98 | tutorials/heat_pump_steps.rst 99 | tutorials/starting_values.rst 100 | tutorials/heat_pump_exergy.rst 101 | tutorials/pygmo_optimization.rst 102 | -------------------------------------------------------------------------------- /docs/tutorials/district_heating.rst: -------------------------------------------------------------------------------- 1 | .. _tespy_tutorial_district_heating_label: 2 | 3 | District heating system 4 | ----------------------- 5 | 6 | The district heating system is a great example for the usage of flexible 7 | user-defined subsystems. The example system and data are based on the district 8 | heating system Hamburg Wilhelmsburg :cite:`Lorenzen2014`. The source code for 9 | this example can be found 10 | `here `__. 11 | Although the structure of the system (see the Figure below) does not seem very 12 | complex, it has more than 120 components. But we can easily determine repeating 13 | structures for the consumers and this is, where the subsystems come in place. 14 | 15 | .. figure:: /_static/images/tutorials/district_heating_system/dhs.svg 16 | :align: center 17 | 18 | Figure: Topology of the heating system. 19 | 20 | The single consumers are connected to the main grid with a control valve at 21 | the outlet and each fork is connected with a pipe to the next fork. Also, the 22 | main grid may have a dead end (e.g. in the housing areas, see subsystem 23 | closed) or is open to connect to another part of the grid (industrial area, 24 | see subsystem open). Additionally, each branch of the main grid is connected to 25 | the upstream part with the fork subsystem (Ki, see subsystem fork). 26 | 27 | .. figure:: /_static/images/tutorials/district_heating_system/dhs_closed.svg 28 | :align: center 29 | 30 | Figure: Generic topology of the dead end subsystem. 31 | 32 | .. figure:: /_static/images/tutorials/district_heating_system/dhs_open.svg 33 | :align: center 34 | 35 | Figure: Generic topology of the open subsystem. 36 | 37 | .. figure:: /_static/images/tutorials/district_heating_system/dhs_forks.svg 38 | :align: center 39 | 40 | Figure: Generic topology of the forks (variable number of branches). 41 | 42 | After the system has been set up, we designed the pipes' insulation in a way, 43 | that the feed flow the temperature gradient is at 1 K / 100 m and the back flow 44 | gradient is at 0.5 K / 100 m. Having designed the system, heat losses at 45 | different ambient temperatures can be calculated, as the heat transfer 46 | coefficient for the pipes has been calculated in the design case. By this way, 47 | it is for example possible to apply load profiles for the consumers as well as 48 | a profile for the ambient temperature to investigate the network heat losses 49 | over a specific period of time. 50 | -------------------------------------------------------------------------------- /docs/whats_new.rst: -------------------------------------------------------------------------------- 1 | What's New 2 | ~~~~~~~~~~ 3 | 4 | Discover notable new features and improvements in each release 5 | 6 | .. include:: whats_new/v0-8-2.rst 7 | .. include:: whats_new/v0-8-1.rst 8 | .. include:: whats_new/v0-8-0-001.rst 9 | .. include:: whats_new/v0-8-0.rst 10 | .. include:: whats_new/v0-7-9.rst 11 | .. include:: whats_new/v0-7-8-002.rst 12 | .. include:: whats_new/v0-7-8-001.rst 13 | .. include:: whats_new/v0-7-8.rst 14 | .. include:: whats_new/v0-7-7.rst 15 | .. include:: whats_new/v0-7-6-001.rst 16 | .. include:: whats_new/v0-7-6.rst 17 | .. include:: whats_new/v0-7-5.rst 18 | .. include:: whats_new/v0-7-4.rst 19 | .. include:: whats_new/v0-7-3.rst 20 | .. include:: whats_new/v0-7-2.rst 21 | .. include:: whats_new/v0-7-1.rst 22 | .. include:: whats_new/v0-7-0.rst 23 | .. include:: whats_new/v0-6-3.rst 24 | .. include:: whats_new/v0-6-2.rst 25 | .. include:: whats_new/v0-6-1.rst 26 | .. include:: whats_new/v0-6-0.rst 27 | .. include:: whats_new/v0-5-1.rst 28 | .. include:: whats_new/v0-5-0.rst 29 | .. include:: whats_new/v0-4-4.rst 30 | .. include:: whats_new/v0-4-3-003.rst 31 | .. include:: whats_new/v0-4-3-001.rst 32 | .. include:: whats_new/v0-4-3.rst 33 | .. include:: whats_new/v0-4-2.rst 34 | .. include:: whats_new/v0-4-1.rst 35 | .. include:: whats_new/v0-4-0.rst 36 | .. include:: whats_new/v0-3-4.rst 37 | .. include:: whats_new/v0-3-3.rst 38 | .. include:: whats_new/v0-3-2.rst 39 | .. include:: whats_new/v0-3-1.rst 40 | .. include:: whats_new/v0-3-0.rst 41 | .. include:: whats_new/v0-2-2.rst 42 | .. include:: whats_new/v0-2-1.rst 43 | .. include:: whats_new/v0-2-0.rst 44 | .. include:: whats_new/v0-1-4.rst 45 | .. include:: whats_new/v0-1-3.rst 46 | .. include:: whats_new/v0-1-2.rst 47 | .. include:: whats_new/v0-1-1.rst 48 | .. include:: whats_new/v0-1-0.rst 49 | .. include:: whats_new/v0-0-5.rst 50 | .. include:: whats_new/v0-0-4.rst 51 | .. include:: whats_new/v0-0-3.rst 52 | .. include:: whats_new/v0-0-2.rst 53 | .. include:: whats_new/v0-0-1.rst 54 | -------------------------------------------------------------------------------- /docs/whats_new/v0-0-1.rst: -------------------------------------------------------------------------------- 1 | v0.0.1 (March 08, 2018) 2 | +++++++++++++++++++++++ 3 | 4 | First release. 5 | 6 | Contributors 7 | ############ 8 | 9 | - Francesco Witte 10 | 11 | Thanks to 12 | - Paul-Jonas Hansen and 13 | - Malte Fritz 14 | for adding the tutorial and a lot of testing and trouble-shooting! 15 | -------------------------------------------------------------------------------- /docs/whats_new/v0-0-2.rst: -------------------------------------------------------------------------------- 1 | v0.0.2 (April 07, 2018) 2 | +++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - Changed architecture of the variables and component parameters. Every parameter is now a data container, giving the user more flexibility (e.g. specifiying a unit) and facilitating future development. 7 | - Changed architecture of fluid property function calls to make custom fluids or custom fluid property functions available. 8 | - Added custom fluid class to generate fluid properties from given fluid mixture. 9 | - Added generic component characteristics for turbine isentropic efficiency and cone law as well as for the heat exchangers heat transfer coefficient. 10 | On top, the user may use own values for the characteristic lines. 11 | - Added val_SI to data container for component properties for future development. 12 | 13 | Documentation 14 | ############# 15 | - Added documentation on how to handle data containers for variables and parameters. 16 | - Added an example for combustion chamber usage. 17 | 18 | Testing 19 | ####### 20 | 21 | Bug fixes 22 | ######### 23 | - Adjusted the generic pump characteristics to cause less instabilities and adjusted function parameters according to `KSB `_. 24 | - Fixed bug in combustion chamber's thermal input equation. 25 | - Fixed parameters for numerical calculation of derivatives. 26 | - Fixed starting relaxation parameter. 27 | 28 | Other changes 29 | ############# 30 | - Improved convergence stability for combustion chamber and heat exchanger. 31 | 32 | Contributors 33 | ############ 34 | 35 | - Francesco Witte 36 | -------------------------------------------------------------------------------- /docs/whats_new/v0-0-3.rst: -------------------------------------------------------------------------------- 1 | v0.0.3 (July 05, 2018) 2 | ++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - added new component: stoichiometric combustion chamber (`0989493 `_, `1e84386 `_, `460dd9f `_, `6d10d2d `_). 7 | - added custom fluid databases, mainly for usage in stoichiometric combustion chamber (`45e19ae `_, `c3da785 `_, `7cb1144 `_). 8 | - added val_SI-attribute to datacontainers for setting ambient temperatures at simple heat exchangers (`c4ba349 `_, `3c7d94e `_). 9 | - added entropy balance for components (`5944eae `_, `b0aed98 `_, `e0839ab `_). 10 | - added pressure rise vs. flow rate characteristics for component pump (`e79a191 `_, `e3409bf `_, `8fe6976 `_). 11 | - added hazen-williams equation for pipe pressure loss calculation (`bf0b865 `_, `25c32bc `_, `cee8cee `_). 12 | - added TESPy network import/export (`7fefc59 `_, `70ae908 `_, `13ef1ad `_, `40e906c `_). 13 | - added data container for grouped component properties (`83c9ff4 `_). 14 | 15 | Documentation 16 | ############# 17 | - internal adjustments for links in the documentation and API. 18 | - added a tutorial for the combustion chamber and moved tutorials to the :ref:`appropriate section ` (`8c0034d `_, `fd7a8e7 `_, `e887478 `_). 19 | - added installation guide for :ref:`windows ` windows (`ca5eaa1 `_). 20 | 21 | Testing 22 | ####### 23 | 24 | Bug fixes 25 | ######### 26 | - convergence stability improvements for combustion chamber, fixes in the equations and derivatives (`2c396f0 `_, `59e3879 `_, `10b2887 `_). 27 | - fixes/improvements for the convergence control (`6e8ea60 `_, `43e8ee1 `_). 28 | - fixed vapour quality specification (`ec3865d `_). 29 | - added missing get_attr method for class characteristics (`13cf730 `_). 30 | - added bus functions to every component (`41e9f2b `_, `7fefc59 `_). 31 | 32 | Other changes 33 | ############# 34 | 35 | Contributors 36 | ############ 37 | 38 | - Francesco Witte 39 | - Shuang Chen 40 | 41 | Thanks to Shuang and Haibing from the UFZ for implementing the hazen-williams equation! 42 | -------------------------------------------------------------------------------- /docs/whats_new/v0-0-4.rst: -------------------------------------------------------------------------------- 1 | v0.0.4 (September, 2018) 2 | ++++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - added new component: solar collector (`b5990e1 `_). 7 | - added a printlevel property for the network and improved the printouts in the calculation process (`44d9f30 `_). 8 | - improved convergence speed (`9cc1d8f `_) 9 | - improved fluid initialisation (`20ae7b3 `_) 10 | 11 | 12 | Documentation 13 | ############# 14 | - improved the online-documentation with new structure and new examples (`fa5e7ca `_, `6ef4d99 `_). 15 | You will find the new examples in :ref:`this section `. 16 | - fixed some typos in different modules and the online-documentation 17 | 18 | Testing 19 | ####### 20 | 21 | Bug fixes 22 | ######### 23 | - fixed bugs in subsystem logic (initialisation, set_attr, set_conns, `321308f `_) 24 | - fixed bugs in bus.set_attr (`2294261 `_), 25 | h_mix_pQ (`eac08cc `_), 26 | starting values for fluid composition (`e3b2a77 `_, `8f92821 `_), 27 | given heat flow of heat exchangers (`4b24651 `_) 28 | 29 | Other changes 30 | ############# 31 | 32 | Contributors 33 | ############ 34 | 35 | - Francesco Witte 36 | -------------------------------------------------------------------------------- /docs/whats_new/v0-0-5.rst: -------------------------------------------------------------------------------- 1 | v0.0.5 (October, 25, 2018) 2 | ++++++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - added new component: motoric cogeneration unit (`79a1177 `_). 7 | An example is provided `here `__. 8 | - improved fluid property checks (`8adc76c `_). 9 | - added bus characteristics for modeling variable efficiencys (e.g. for generator, motor, boiler) (`79a1177 `_). 10 | - isentropic efficiency characteristic for compressor linked to pressure ratio (`85d317d `_). 11 | - added volumetric flow specification (`63db64d `_). 12 | 13 | Documentation 14 | ############# 15 | - adapted documentation and (`example code `_) 16 | in regard of new features. 17 | - fixed some typos in documentation. 18 | 19 | Parameter renaming 20 | ################## 21 | 22 | **compressor** 23 | - vigv -> igva (inlet guide vane angle) 24 | 25 | **simple heat exchanger** 26 | - t_a -> Tamb (ambient temperature) 27 | 28 | **solar collector** 29 | - t_a -> Tamb (ambient temperature) 30 | 31 | Testing 32 | ####### 33 | 34 | Bug fixes 35 | ######### 36 | - fixed a bug in the function v_mix_ph (specific volume for gas mixtures) (`d487381 `_). 37 | - fixed compressor derivatives for usage with custom variables (`71cae48 `_). 38 | - adjusted error messages (`cccd89c `_). 39 | - removed unecessary loop (`187505b `_). 40 | - fixed attribute handling in subsystem: condenser with subcooler (`2c926bb `_). 41 | 42 | Other changes 43 | ############# 44 | - remodeled the characteristic map for compressors: if not specified, igva is assumed to be 0° (`2425a77 `_). 45 | - redesigned the printouts for component parameters (`9465be6 `_, 46 | `b2c0897 `_, 47 | `cbbc1a1 `_, 48 | `1e55e36 `_, 49 | `2e795c2 `_) 50 | - custom variables are available for (`977a5be `_): 51 | - turbomachines, 52 | - vessels, 53 | - simple heat exchangers (as well as pipes and solar collctors) and 54 | - cogeneration unit. 55 | 56 | Contributors 57 | ############ 58 | 59 | - Francesco Witte 60 | - Paul Hansen 61 | -------------------------------------------------------------------------------- /docs/whats_new/v0-1-0.rst: -------------------------------------------------------------------------------- 1 | v0.1.0 (February, 2, 2019) 2 | ++++++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - Added new component node and modified equations for simple heat exchangers to work with negative mass flows. The node component is able to switch between merge and splitter equations according to the directions of the mass flows. 7 | Please beware, that the amount of the equations of a splitter and a merge is not the same, thus the number of equations provided by the node depend on the flow direction and may change within the calculation process. In order to make use of the node, 8 | a network should always contain more than one node, so that a different node can compensate a possible change in flow direction (`PR #43 `_). 9 | - Added examples for components, busses, connections etc. in the docstrings. You will find the examples in either your editors help pane or the online documentation of the API (`PR #45 `_). 10 | - Added an interface attribute for sinks and sources changing the component type from sink/source to subsys_interface when exporting the network, if you specify :code:`interface=True` for these type of components. This way, you can reimport the saved network and connect it to a different network. Also imported components, connections and busses are easily accessible by their label (components/busses) or their target with target id (connections). For an example, see the module documentation :py:mod:`tespy.network_reader`. (`PR #46 `_). 11 | - Added logging (console and log-file), :ref:`see how to use it` (`PR #51 `_). 12 | 13 | Documentation 14 | ############# 15 | - Adapted documentation and examples in regard of new features. Examples have been moved to the `oemof-examples repository `_. 16 | - Improved consistency in documentation of all modules (`PR #45 `_). 17 | - Registered a DOI for TESPy version 0.1.0. 18 | 19 | .. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.2555866.svg 20 | :target: https://doi.org/10.5281/zenodo.2555866 21 | 22 | Parameter renaming 23 | ################## 24 | 25 | **networks** 26 | 27 | - init_file -> init_path 28 | - design_file -> design_path 29 | - structure -> deprecated: Providing :code:`structure=True` on saving the network is not required anymore, the network structure is exported automatically. 30 | 31 | .. note:: 32 | 33 | The initialisation method and handling of design and offdesign calculations has been adjusted. 34 | In future, please specify the path to the folder, where your results have been saved, e.g.: 35 | 36 | .. code:: 37 | 38 | mynetwork.save('path/to/folder') 39 | mynetwork.solve('offdesign', design_path='path/to/folder', init_path='path/to/folder') 40 | 41 | 42 | Testing 43 | ####### 44 | - The examples in the docstrings are used as doctests. 45 | - Component tests have been implemented. 46 | - General tests for errors, printouts and fluid properties have been implemented. 47 | - Benchmark test for a heat pump model (still to be improved, see inline comments). 48 | - Testcoverage will be checked for every PR in the future! 49 | 50 | See `PR #52 `_. 51 | 52 | Bug fixes 53 | ######### 54 | - Adjusted network export and network import to work for grouped component properties and characteristic maps (`PR #46 `_). 55 | - Redesigned pre- and postprocessing of component properties as some errors occoured before. Design parameters are now always gathered from the component .csv-file containing the design point information (saved design state of the network) (`PR #50 `_). 56 | 57 | Other changes 58 | ############# 59 | - Improved calculation speed by swapping the CoolProp.CoolProp.PropsSI-calls with CoolProp.AbstractState calls (`PR #49 `_). 60 | 61 | Contributors 62 | ############ 63 | 64 | - Francesco Witte 65 | -------------------------------------------------------------------------------- /docs/whats_new/v0-1-1.rst: -------------------------------------------------------------------------------- 1 | v0.1.1 (May, 14, 2019) 2 | ++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - Specifcation of temperature below or above boiling point temperature with :code:`Td_bp` keyword on connections (`PR #64 `_). 7 | - Path specifications for the :code:`init_path` and :code:`design_path` in the networks module as well as :code:`path` in the network_reader module now work with relative and absolute paths. The feature has been tested on windows and linux machines (`PR #66 `_). 8 | 9 | Documentation 10 | ############# 11 | - Updated "Using TESPy" according to the new features, you can find an Example for the usage of the :code:`Td_bp` and the :code:`state` keyword at the bottom of this release message. 12 | 13 | Parameter renaming 14 | ################## 15 | 16 | Testing 17 | ####### 18 | - Tests and doctests have been adjusted and updated to test the new features. 19 | - Added software tests for OS X (`PR #68 `_), windows tests to follow. 20 | 21 | Bug fixes 22 | ######### 23 | - Fixed naming-error on windows when creating tespy_fluids (`PR #60 `_). 24 | - Added missing grouped component parameter import in network reader (`731b9f `_). 25 | 26 | Other changes 27 | ############# 28 | - Modified printouts of connection properties for :code:`network.print_results()`-function (`668ca6 `_) 29 | - 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 `_). 30 | - 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). 31 | The convergence check manipulates the enthalpy values at this connection in order to meet the phase specification (`PR #64 `_). 32 | 33 | Example 34 | ####### 35 | 36 | .. code-block:: python 37 | 38 | from tespy import cmp, con, nwk 39 | import numpy as np 40 | 41 | # network 42 | fluid_list = ['NH3', 'water'] 43 | nw = nwk.network(fluids=fluid_list, T_unit='C', p_unit='bar', h_unit='kJ / kg') 44 | 45 | # components 46 | tesin = cmp.sink('TES in') 47 | tesout = cmp.source('TES out') 48 | hsin = cmp.sink('HS in') 49 | hsout = cmp.source('HS out') 50 | he = cmp.heat_exchanger('heat exchanger') 51 | 52 | # connection 53 | tes_he = con.connection(tesout, 'out1', he, 'in2') 54 | he_tes = con.connection(he, 'out2', tesin, 'in1') 55 | hs_he = con.connection(hsout, 'out1', he, 'in1') 56 | he_hs = con.connection(he, 'out1', hsin, 'in1') 57 | nw.add_conns(tes_he, he_tes, hs_he, he_hs) 58 | 59 | # heat exchanger parameters 60 | he.set_attr(pr1=0.98, pr2=0.98, ttd_u=42, Q=-90e3) 61 | 62 | # hot side parameters 63 | hs_he.set_attr(T=70, p=9.4, fluid={'NH3': 1, 'water': 0}) 64 | he_hs.set_attr(T=35) 65 | 66 | # cold side inlet 67 | tes_he.set_attr(T=18, p=5, fluid={'NH3': 0, 'water': 1}) 68 | 69 | # solve 70 | nw.solve('design') 71 | 72 | fill = '############################################################' 73 | 74 | print(fill) 75 | print('See, the calculation did not work: The temperature value for the ' 76 | 'hot side outlet is near to the two phase region. A singularity ' 77 | 'appears in the solution process, as the temperature equation\'s ' 78 | 'derivative towards enthalpy will be zero in this region.') 79 | print(fill) 80 | 81 | ## let's retry with state keyword (state should be gaseous) 82 | he_hs.set_attr(state='g') 83 | 84 | nw.solve('design') 85 | nw.print_results() 86 | 87 | print(fill) 88 | print('The state keyword prevents the fluids state at the hot side outlet ' 89 | 'from going into two phase region, a solution is found.') 90 | print(fill) 91 | 92 | # so how does the superheating or subcooling work? 93 | # remove state and temperature specification, add superheating specification 94 | # temperature difference to boiling point = 10 K 95 | he_hs.set_attr(state=np.nan, T=np.nan, Td_bp=10) 96 | nw.solve('design') 97 | nw.print_results() 98 | 99 | print(fill) 100 | print('The temperature at hot side outlet is 10 K above the (prior) unkown ' 101 | 'boiling point temperature at that point.') 102 | print(fill) 103 | 104 | 105 | Contributors 106 | ############ 107 | 108 | - Francesco Witte 109 | - Shuang Chen 110 | -------------------------------------------------------------------------------- /docs/whats_new/v0-1-2.rst: -------------------------------------------------------------------------------- 1 | v0.1.2 (August, 6, 2019) 2 | ++++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - The water electrolyzer is available as new component of TESPy (`PR #73 `_). 7 | - The components :py:class:`combustion chamber ` and :py:class:`cogeneration unit ` 8 | now work with fuel mixtures, too. Specification of the component's fuel is not required anymore, the software automatically detects, 9 | which fuels are connected to the component's inlets. Available fuels are: methane, ethane, propane, butane and hydrogen (`PR #79 `_). 10 | - Add busses to the :py:meth:`network's result printout `. 11 | 12 | Documentation 13 | ############# 14 | - Fix some typos in the docstrings and improvements of default values (`PR #69 `_ and `PR #71 `_). 15 | - Update combustion chamber tutorial (`PR #79 `_). 16 | - Improve API documentation of the solar collector: Handling of optical losses (`PR #83 `_). 17 | 18 | Parameter renaming 19 | ################## 20 | 21 | Testing 22 | ####### 23 | 24 | Bug fixes 25 | ######### 26 | - Fix convergence check for negative minimum enthalpy values (`PR #71 `_). 27 | - Add an error message if the user did not add any connections to the network (`PR #79 `_). 28 | - Fix loading bus information from design-case .csv-file. Components can be attached to multiple busses now (`PR #79 `_). 29 | - Fix solar collector energy balance equation and adjust documentation (`PR #83 `_). 30 | 31 | Other changes 32 | ############# 33 | - Add method to calculate and export vapour mass fraction values of pure fluids in the post processing (`PR #74 `_). 34 | - Only allow label and P as parameters for busses to avoid misleading parameter specification (`PR #78 `_). 35 | 36 | Water Electrolyzer Example 37 | ########################## 38 | 39 | .. code-block:: python 40 | 41 | from tespy import cmp, con, nwk 42 | 43 | fluid_list = ['O2', 'H2O', 'H2'] 44 | nw = nwk.network(fluids=fluid_list, T_unit='C', p_unit='bar') 45 | 46 | # sinks and sources 47 | fw = cmp.source('feed water') 48 | oxy = cmp.sink('oxygen sink') 49 | hydro = cmp.sink('hydrogen sink') 50 | cw = cmp.source('cooling water') 51 | cw_hot = cmp.sink('cooling water out') 52 | 53 | # specification of electrolysis efficiency 54 | el = cmp.water_electrolyzer('electrolyzer 1', eta=0.8, design=['eta'], offdesign=['eta_char']) 55 | 56 | # hydrogen compression 57 | comp = cmp.compressor('compressor', eta_s=0.9) 58 | 59 | # specify the feed water mass flow 60 | # the fluid composition at the feed water inlet and the oxygen as well as 61 | # hydrogen outlets are not required. These parameters are set automatically. 62 | fw_el = con.connection(fw, 'out1', el, 'in2', m=0.1, p=10, T=15) 63 | el_o = con.connection(el, 'out2', oxy, 'in1') 64 | el_cmp = con.connection(el, 'out3', comp, 'in1', T=50) 65 | cmp_h = con.connection(comp, 'out1', hydro, 'in1', p=50) 66 | 67 | # cooling water specifications 68 | cw_el = con.connection(cw, 'out1', el, 'in1', fluid={'H2O': 1, 'H2': 0, 'O2': 0}, p=5, T=15) 69 | el_cw = con.connection(el, 'out1', cw_hot, 'in1', T=45, p=4.9) 70 | nw.add_conns(fw_el, el_o, el_cmp, cmp_h, cw_el, el_cw) 71 | 72 | # solve design case 73 | nw.solve('design') 74 | nw.save('tmp') 75 | # test offdesign case 76 | nw.solve('offdesign', design_path='tmp') 77 | 78 | # change feed water flow and recalculate operation 79 | fw_el.set_attr(m=0.05) 80 | nw.solve('offdesign', design_path='tmp') 81 | 82 | Contributors 83 | ############ 84 | 85 | - Francesco Witte 86 | - Tim Hoener, Nils Stolze, Markus Brandt 87 | -------------------------------------------------------------------------------- /docs/whats_new/v0-1-3.rst: -------------------------------------------------------------------------------- 1 | v0.1.3 (November, 6, 2019) 2 | ++++++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - Individual design path specification is available: Specify the design_path individually for single connections or a components in your network, if 7 | you want the individual design parameters be loaded from a different design case than the network's design case given in the network's 8 | design path (`PR #84 `_). 9 | - 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, 10 | e.g. when designing an extraction turbine, where the district heating condenser is designed for maximum extraction and the backpressure turbine is designed 11 | for minimum extraction (`PR #92 `_). 12 | - 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 13 | by data containers (read more at :ref:`component parameter specification `), (`PR #85 `_). 14 | 15 | Documentation 16 | ############# 17 | - Change license from GPLv3 to MIT (`PR #93 `_). 18 | - Fix unit error in component documentation for the zeta-value (`PR #93 `_). 19 | - Improve documentation of the functions :func:`tespy.components.components.component.zeta_func` and :func:`tespy.components.components.component.zeta2_func` 20 | (`4291bd `_). 21 | 22 | Parameter renaming 23 | ################## 24 | 25 | Testing 26 | ####### 27 | - Added tests for the new design path feature (`PR #84 `_). 28 | - Implemented additional network and component tests, (`PR #86 `_). 29 | 30 | Bug fixes 31 | ######### 32 | - Offdesign values for connections are specified from the design case files (`PR #84 `_). Before, the offdesign values 33 | were the actual values of the fluid property in the last calculation (which is not necessarily the design case). 34 | - Add debug logging message, if the enthalpy is adjusted on connections with the keyword :code:`state` specified (`PR #85 `_). 35 | 36 | Other changes 37 | ############# 38 | - Improved calculation speed for fluid mixture properties with the parameter T0 as starting value for root finding (`PR #84 `_). 39 | 40 | Contributors 41 | ############ 42 | 43 | - Francesco Witte 44 | -------------------------------------------------------------------------------- /docs/whats_new/v0-1-4.rst: -------------------------------------------------------------------------------- 1 | v0.1.4 (December, 12, 2019) 2 | +++++++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - Implemented difference pressure vs mass flow characteristic line for valve (`c4eec6d `_). 7 | 8 | Documentation 9 | ############# 10 | - Fix typos in docstrings in components module (`PR #102 `_). 11 | 12 | Parameter renaming 13 | ################## 14 | 15 | Testing 16 | ####### 17 | 18 | Bug fixes 19 | ######### 20 | 21 | Other changes 22 | ############# 23 | - This is the last release before version 0.2.0. 24 | 25 | Contributors 26 | ############ 27 | 28 | - Francesco Witte 29 | -------------------------------------------------------------------------------- /docs/whats_new/v0-2-1.rst: -------------------------------------------------------------------------------- 1 | v0.2.1 - Fourier's Fable (February, 7 2020) 2 | +++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - Back end modifications in order to improve calculation speed. For the results 7 | see (`PR #147 `_). 8 | 9 | Documentation 10 | ############# 11 | - Fixes in code and docstrings to meet PEP8 guidelines 12 | (`PR #143 `_). 13 | - Update the class documentations of component and connection classes 14 | (`PR #146 `_). 15 | 16 | Parameter renaming 17 | ################## 18 | 19 | Testing 20 | ####### 21 | - Improve the heat pump test 22 | (`PR #150 `_). 23 | 24 | Bug fixes 25 | ######### 26 | - Prevent pandas 1.0.0 installation due to bug in the :code:`to_csv()` method 27 | (bug will be fixed in 28 | `PR #31513 `_ of pandas). 29 | Additionally,the version requirements of third party packages have been 30 | updated to prevent future bugs resulting from possible API changes 31 | (`PR #146 `_). 32 | - There was a bug in the heat exchanger kA-functions ( 33 | :py:meth:`tespy.components.heat_exchangers.simple.kA_func`, 34 | :py:meth:`tespy.components.heat_exchangers.base.kA_func` and 35 | :py:meth:`tespy.components.heat_exchangers.condenser.kA_func`). The factors 36 | for the heat transfer coefficient should not simultaneously amplify the 37 | value but instead with their inverse. 38 | 39 | .. math:: 40 | 41 | f_{kA} = \frac{2}{\frac{1}{f_{kA,1}} + \frac{1}{f_{kA,2}}} 42 | 43 | For simple heat exchangers, :math:`f_{kA,2}` will be equal to 1 44 | (`PR #150 `_). 45 | 46 | Other changes 47 | ############# 48 | - Replacing some of the characteristic lines by generic ones. The simulation 49 | results using the default lines might slightly differ from the results using 50 | the original defaults (`PR #149 `_). 51 | 52 | Contributors 53 | ############ 54 | 55 | - Francesco Witte (@fwitte) 56 | - @maltefritz 57 | -------------------------------------------------------------------------------- /docs/whats_new/v0-2-2.rst: -------------------------------------------------------------------------------- 1 | v0.2.2 - Rankine's Realm (March, 6, 2020) 2 | +++++++++++++++++++++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - Allow initialisation for the primary variables from previous calculation. 7 | Until now, the user needed to save the network's state and reload that state 8 | for his next simulation. This feature is enabled as default. If you want to 9 | disable this feature, you need to state 10 | :code:`mynetwork.solve(..., init_previous=False)` 11 | (`PR #156 `_). 12 | - Extrapolation for characteristic lines is available. In default state, the 13 | upper or lower value range limit is used when a characteristic line is 14 | evaluated outside of the available x-value range. The :code:`extrapolate` 15 | parameter allows linear extrapolation, for an example see the corresponding 16 | sections in the online documentation: 17 | :ref:`component characteristics `, 18 | :ref:`tespy characteristics ` 19 | (`PR #159 `_). 20 | - Add a new component evaporator for geothermal organic rankine cycle. The 21 | component has inlets for geothermal steam brine. On the cold side, the orc 22 | working fluid is evaporated. Read more about this component in the API 23 | documentation: :py:class:`tespy.components.customs.orc_evaporator` 24 | (`PR #148 `_). 25 | 26 | Documentation 27 | ############# 28 | - Add method for automatic citations and references 29 | (`PR #163 `_). 30 | 31 | Parameter renaming 32 | ################## 33 | 34 | Testing 35 | ####### 36 | - Add convergence checks for all component tests. Some tests did not fail, even 37 | if the calculation did not converge 38 | (`PR #153 `_). 39 | - Improve coverage of the networks module 40 | (`PR #153 `_). 41 | - Add tests for characteristic line and map evaluation 42 | (`PR #159 `_). 43 | 44 | Bug fixes 45 | ######### 46 | - Fix the bugged tests for compressor characteristic maps 47 | (:py:meth:`tespy.components.turbomachinery.compressor.char_map_func`). The 48 | pressure ratio factor of the lowest speedline available in the default data 49 | ranges from about 0.2 to 0.5. Therefore the design pressure ratio should be 50 | higher than 5 (`PR #156 `_). 51 | 52 | Other changes 53 | ############# 54 | - Use the method :py:meth:`tespy.components.components.component.fluid_deriv` 55 | for all components, that do not change composition between an inlet and the 56 | respective outlet (`PR #153 `_). 57 | - Adjust the method :py:meth:`tespy.components.components.component.zeta_func` 58 | to work with all zeta value specifications 59 | (`PR #153 `_). 60 | 61 | Contributors 62 | ############ 63 | - Francesco Witte (`@fwitte `_) 64 | - `@maltefritz `_ 65 | - `@ChaofanChen `_ 66 | -------------------------------------------------------------------------------- /docs/whats_new/v0-3-1.rst: -------------------------------------------------------------------------------- 1 | v0.3.1 - Fix for Mayer's Merit (May, 29, 2020) 2 | ++++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | Bug fixes 5 | ######### 6 | - Remove a debugging printout in the kA_func of the 7 | :py:class:`tespy.components.heat_exchangers.simple` class. 8 | 9 | Contributors 10 | ############ 11 | - Francesco Witte (`@fwitte `_) 12 | -------------------------------------------------------------------------------- /docs/whats_new/v0-3-2.rst: -------------------------------------------------------------------------------- 1 | v0.3.2 - Carnot's Colors (June, 10, 2020) 2 | +++++++++++++++++++++++++++++++++++++++++ 3 | 4 | New features 5 | ############ 6 | - Colored printouts are available in the :code:`print_results()` method of the 7 | network class. There are three different color codes available with default 8 | settings: 9 | 10 | - user specified parameters (:code:`'set'`, blue) 11 | - component parameters specified as variables (:code:`'var'`, green) 12 | - faulty parameters (:code:`'err'`, red) 13 | 14 | In order to change the colors, simply import :code:`coloring` from the 15 | :py:mod:`tespy.tools.global_vars` module and adjust the escape codes. For 16 | example, to reset all colors to white text: 17 | 18 | .. code-block:: python 19 | 20 | from tespy.tools.global_vars import coloring 21 | coloring['set'] = '\033[0m' 22 | coloring['err'] = '\033[0m' 23 | coloring['var'] = '\033[0m' 24 | 25 | See `here `__ for a 26 | list of available codes 27 | (`PR #205 `_). 28 | 29 | Bug fixes 30 | ######### 31 | - Readd method for :code:`T_mix_ps` calculation for pure fluids: In case the 32 | fluid propagation did not go through (e.g. due to availability of good 33 | starting values) the fluid composition at a turbomachine's inlet and outlet 34 | may not be equal (`PR #207 `_). 35 | - Fix the calculation of mixture density: The density is calculated as sum of 36 | the densities of the mixture components at their respective partial pressure 37 | and the mixture temperature 38 | (`PR #207 `_). With the old method, 39 | the specific volume was calculated according to Amagat's law, which produced 40 | incorrect values if one or more components of the mixture were liquid at the 41 | mixture's temperature and pressure. See discussion about humid air propreties 42 | here: `Issue #206 `_. 43 | 44 | Contributors 45 | ############ 46 | - Francesco Witte (`@fwitte `_) 47 | - `@jbueck `_ 48 | -------------------------------------------------------------------------------- /docs/whats_new/v0-3-3.rst: -------------------------------------------------------------------------------- 1 | v0.3.3 - Maxwell’s Memory (July, 21, 2020) 2 | ++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - In some cases - especially large networks and many simulation runs within a 7 | a single script - the fluid property memorisation added a lot of calculation 8 | time for searching through the lookup tables of previously calculated fluid 9 | property values. It is now possible to manually specify whether or not the 10 | fluid property memorisation is performed. 11 | 12 | The memorisation benefits 13 | 14 | - networks using gaseous mixtures and 15 | - smaller networks using the HEOS back end. 16 | 17 | The memorisation slows down 18 | 19 | - very large networks and 20 | - usage of tabular back ends (BICUBIC or TTSE). 21 | 22 | In order to deactivate memorisation, add 23 | :code:`memorise_fluid_properties=False` on network creation, for example: 24 | 25 | .. code-block:: python 26 | 27 | from tespy.networks import network 28 | 29 | mynetwork = network( 30 | fluids=['BICUBIC::water'], memorise_fluid_properties=False) 31 | 32 | (`PR #211 `_). 33 | 34 | Other Changes 35 | ############# 36 | - Reorder network initialisation process for improved maintenance and faster 37 | performance (`PR #204 `_). 38 | 39 | Contributors 40 | ############ 41 | - Francesco Witte (`@fwitte `_) 42 | -------------------------------------------------------------------------------- /docs/whats_new/v0-3-4.rst: -------------------------------------------------------------------------------- 1 | v0.3.4 - Darwin's Delight (October, 13, 2020) 2 | +++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | Documentation 5 | ############# 6 | - Replace enthalpy starting value with :code:`state` keyword in the 7 | :ref:`heat pump tutorial ` and the examples from the 8 | oemof_examples repository 9 | (`PR #214 `_, 10 | `743bfeb `_). 11 | - Add a new tutorial for efficiency optimization of a thermal power plant using 12 | TESPy and PyGMO (`PR #220 `_). 13 | - Fix some typos in the BibTeX data for the TESPy JOSS paper 14 | (`PR #220 `_). 15 | 16 | Bug Fixes 17 | ######### 18 | - Update the dictionary of busses, components and connections before every 19 | calculation. If a parameter is updated by user specification using the 20 | dictionary access method and the network object is copied, the dictionaries 21 | of the busses, components and connections point to a different object in some 22 | cases (`d2537ca `_). 23 | 24 | Other Changes 25 | ############# 26 | - Add network check at the end of 27 | :py:func:`tespy.networks.network_reader.load_network` function 28 | (`PR #212 `_). 29 | 30 | Contributors 31 | ############ 32 | - Francesco Witte (`@fwitte `_) 33 | - Markus Brandt (`@MarBrandt `_) 34 | -------------------------------------------------------------------------------- /docs/whats_new/v0-4-1.rst: -------------------------------------------------------------------------------- 1 | v0.4.1 - User's Universe (February, 7, 2021) 2 | ++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - Add functionalities for user defined equations. The user can define 7 | individual functions that can be applied on connection parameters. E.g. in 8 | order to couple mass flow values at some point of the network to temperature 9 | values at a different point. Generic equations can be applied: There are no 10 | restrictions as long as the partial derivatives are provided correctly. For 11 | extensive examples have a look at the API documentation of class 12 | :py:class:`tespy.tools.helpers.UserDefinedEquation` or in the respective 13 | section in the online :ref:`documentation ` 14 | (`PR #245 `_). 15 | 16 | Documentation 17 | ############# 18 | 19 | Bug Fixes 20 | ######### 21 | - Fix RuntimeError in CombustionChamberStoich class 22 | (`PR #244 `_). 23 | 24 | Other Changes 25 | ############# 26 | 27 | Contributors 28 | ############ 29 | - Francesco Witte (`@fwitte `_) 30 | - `@govind-menon110 `_ 31 | -------------------------------------------------------------------------------- /docs/whats_new/v0-4-2.rst: -------------------------------------------------------------------------------- 1 | v0.4.2 - Fixes for User's Universe (February, 11, 2021) 2 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | API Fixes/Changes 5 | ################# 6 | - Due to a bug/double structure in the network properties of a model, 7 | specification of component or connection parameters when the component or 8 | connection instance was accessed via its label within the network, the wrong 9 | copy of the instance was accessed when using PyGMO in some cases. 10 | The method off accessing components and connections via label has therefore 11 | changed in the following way. 12 | 13 | **Old method:** 14 | 15 | .. code-block:: python 16 | 17 | conn = mynetwork.connections['connection label'] 18 | comp = mynetwork.components['component label'] 19 | 20 | **New method:** 21 | 22 | .. code-block:: python 23 | 24 | conn = mynetwork.get_conn('connection label') 25 | comp = mynetwork.get_comp('component label') 26 | 27 | To iterate through all components or connections of the network use something 28 | like: 29 | 30 | .. code-block:: python 31 | 32 | for conn in mynetwork.conns['object']: 33 | print(conn.label) 34 | 35 | for comp in mynetwork.comps['object']: 36 | print(comp.label) 37 | 38 | **Accessing busses remains untouched** 39 | (`PR #247 `_) 40 | 41 | Bug Fixes 42 | ######### 43 | - Saving data of characteristics and reloading from the .csv file structure 44 | was broken if more than one component of the same class was part of the 45 | network (`PR #246 `_). 46 | 47 | Contributors 48 | ############ 49 | - Francesco Witte (`@fwitte `_) 50 | -------------------------------------------------------------------------------- /docs/whats_new/v0-4-3-001.rst: -------------------------------------------------------------------------------- 1 | v0.4.3-001 - Grassmann's Graph (May, 12, 2021) 2 | ++++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | Documentation 5 | ############# 6 | - Some minor changes in documentation. 7 | 8 | Other Changes 9 | ############# 10 | - Check for :code:`key in dictionary` instead of 11 | :code:`key in dictionary.keys()` in boolean operations 12 | (`PR #264 `_). 13 | - Rename GitHub branches: master to main 14 | (`Issue #266 `_). 15 | 16 | Contributors 17 | ############ 18 | - Francesco Witte (`@fwitte `_) 19 | -------------------------------------------------------------------------------- /docs/whats_new/v0-4-3-003.rst: -------------------------------------------------------------------------------- 1 | v0.4.3-003 - Grassmann's Graph (May, 17, 2021) 2 | ++++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | Documentation 5 | ############# 6 | - Fix typos in the HeatExchanger classes API docs. 7 | - Add two more examples for exergy analysis setups. 8 | 9 | Other Changes 10 | ############# 11 | - Remove Python3.6 support. 12 | - Make it possible to include results in automatic model report, for more 13 | information see the corresponding section in the documentation: 14 | :ref:`TESPy Networks Postprocessing ` 15 | (`PR #267 `_). 16 | 17 | Contributors 18 | ############ 19 | - Francesco Witte (`@fwitte `_) 20 | -------------------------------------------------------------------------------- /docs/whats_new/v0-4-3.rst: -------------------------------------------------------------------------------- 1 | v0.4.3 - Grassmann's Graph (April, 29, 2021) 2 | ++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - Automatic provision of input data for the sankey diagram class of the 7 | `plotly library `_ to generate 8 | exergy sankey diagrams. For example, the diagram of the solar thermal power 9 | plant presented in the thermodynamic analyses section 10 | 11 | .. figure:: /_static/images/advanced/exergy/sankey.svg 12 | :align: center 13 | :alt: Example of the sankey diagram 14 | 15 | (`PR #251 `_). 16 | - The results of your simulation are much more easy to bulk access: The 17 | :py:class:`tespy.networks.network.Network` class provides you with a 18 | results dictionary containing DataFrames with all data necessary. The keys 19 | of the dictionary are: 20 | 21 | - :code:`'Connection'` 22 | - the class names of the different components used, e.g. :code:`'Turbine'` or 23 | :code:`'HeatExchanger'` 24 | - the labels of the busses, e.g. :code:`'input power'` 25 | 26 | The pandas DataFrame provides you with the SI-values for components and 27 | busses as well as all fluid property data of the connections in respective 28 | specified unit. For example: 29 | 30 | .. code-block:: python 31 | 32 | mynetwork.results['Connection'] 33 | mynetwork.results['Turbine'] 34 | 35 | (`PR #255 `_). 36 | 37 | Documentation 38 | ############# 39 | - An own chapter for the 40 | :ref:`exergy analysis toolbox ` has been added 41 | (`PR #251 `_). 42 | - Fix some typos in the code of heat pump tutorial 43 | (`PR #260 `_). 44 | - Update component parameter data type specifications according to 0.4.x API 45 | in docs and add missing parameters in HeatExchanger classes 46 | (`PR #260 `_). 47 | - Fix broken links to characteristic map functions of class 48 | :py:class:`tespy.components.turbomachinery.compressor.Compressor` 49 | (`PR #263 `_). 50 | 51 | Bug Fixes 52 | ######### 53 | - Add missing exergy balance method of class Drum 54 | (`#1eb92e3 `_). 55 | - Add missing specified values of temperature difference to boiling point to 56 | connection report 57 | (`PR #250 `_). 58 | - Fix Reynolds value ranges for Hanakov and Blasius equations in calculation of 59 | Darcy friction factor 60 | (`#ce6bef9 `_). 61 | 62 | Other Changes 63 | ############# 64 | 65 | - Add a timestamp for the automatic model documentation feature 66 | (`PR #248 `_). 67 | - Move from travis to GitHub actions 68 | (`PR #249 `_). 69 | - Specified Bus values are now colored in the 70 | :py:meth:`tespy.networks.network.Network.print_results` method 71 | (`PR #255 `_). 72 | - Remove building figures for characteristics from docs generation 73 | (`PR #251 `_). 74 | 75 | Contributors 76 | ############ 77 | - Francesco Witte (`@fwitte `_) 78 | - `@juliusmeier `_ 79 | - `@jfreissmann `_ 80 | - `@anmartens `_ 81 | -------------------------------------------------------------------------------- /docs/whats_new/v0-4-4.rst: -------------------------------------------------------------------------------- 1 | v0.4.4 - Reynolds' Reminiscence (July, 14, 2021) 2 | ++++++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | Documentation 5 | ############# 6 | - Fix some typos here and there. 7 | 8 | Bug Fixes 9 | ######### 10 | - Fix pandas version 1.3.0 dependencies 11 | (`PR #277 `_). 12 | - Add missing results for some components in the results DataFrame of the 13 | network (`PR #277 `_). 14 | - Fix exergy balance equation of class merge 15 | :py:class:`tespy.components.nodes.merge.Merge.exergy_balance` 16 | (`PR #280 `_). 17 | - Fix a lot of DeprecationWarnings in pandas 18 | (`PR #280 `_). 19 | 20 | Other Changes 21 | ############# 22 | - Add warning logs for missing fluid composition data in the initialisation 23 | process of the network 24 | (`PR #278 `_). 25 | - Add Dodecane to the available fuels for combustion 26 | (`PR #273 `_). 27 | - Add tests for the solar energy generating system 28 | (`PR #280 `_). 29 | 30 | Contributors 31 | ############ 32 | - Francesco Witte (`@fwitte `_) 33 | -------------------------------------------------------------------------------- /docs/whats_new/v0-5-0.rst: -------------------------------------------------------------------------------- 1 | v0.5.0 - Davis' Domain (September, 29, 2021) 2 | ++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | Documentation 5 | ############# 6 | - Add a tutorial for the exergy analysis of a ground-coupled heat pump (GHCP). 7 | You can find it on the Tutorials and Examples pages 8 | (`PR #282 `_). 9 | 10 | Bug Fixes 11 | ######### 12 | - Add :code:`is_result` flag to logarithmic temperature difference of heat 13 | exchangers. 14 | - Lift pandas requirement to :code:`pandas>=1.3.0` 15 | (`PR #285 `_). 16 | 17 | Other Changes 18 | ############# 19 | - LaTeX model report can now be compiled by default 20 | (`PR #286 `_). 21 | 22 | Contributors 23 | ############ 24 | - Francesco Witte (`@fwitte `_) 25 | - `@anmartens `_ 26 | -------------------------------------------------------------------------------- /docs/whats_new/v0-5-1.rst: -------------------------------------------------------------------------------- 1 | v0.5.1 - Exciting Exergy (January, 14, 2022) 2 | ++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | Documentation 5 | ############# 6 | - Improvements on the description of the exergy analysis results data. 7 | Additional dataframe added, that contains the aggregated component exergy 8 | analysis results (component and respective bus exergy data) 9 | (`PR #293 `_). 10 | 11 | Bug Fixes 12 | ######### 13 | - In the first offdesign calculation the connection parameter specifications 14 | in the LaTeX report were still reported in design mode 15 | (`PR #290 `_). 16 | - Labels of string representations of numeric labels in components, connections 17 | and busses have been misinterpreted as numeric values by the network_reader 18 | (`PR #298 `_). 19 | 20 | Other Changes 21 | ############# 22 | 23 | Contributors 24 | ############ 25 | - Francesco Witte (`@fwitte `_) 26 | -------------------------------------------------------------------------------- /docs/whats_new/v0-6-0.rst: -------------------------------------------------------------------------------- 1 | v0.6.0 - Colored Chemicals (May, 15, 2022) 2 | ++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | We have created a place for users of TESPy to exchange ideas and share their 5 | models and experience. Everyone is invited to get in touch and tune in on our 6 | `GitHub discussions page `__. 7 | 8 | New Features 9 | ############ 10 | - A new component is introduced, the DiabaticCombustionChamber: 11 | :py:class:`tespy.components.combustion.diabatic.DiabaticCombustionChamber`. 12 | In contrast to the adiabatic combustion chamber, the new component implements 13 | pressure and heat losses. An example usage can be found in the API reference 14 | of the class linked above 15 | (`PR #301 `_). 16 | - Gaseous mixtures now check for condensation of water in enthalpy and entropy 17 | functions (`PR #318 `_). 18 | 19 | 20 | Documentation 21 | ############# 22 | - Add tutorial for the :code:`DiabaticCombustionChamber` 23 | (`PR #321 `_). 24 | - Fix a lot of bugs in the docs 25 | (`PR #337 `_). 26 | 27 | Bug Fixes 28 | ######### 29 | - Calculation of entropy for gaseous mixtures included the pressure correction 30 | term although the entropy values of the mixture components were calculated at 31 | their respective partial pressure 32 | (`PR #318 `_). 33 | - Fix mass flow multipliers for non SI units 34 | (`PR #317 `_). 35 | - Fix call to wrong (hard coded) key for molecular mass of hydrogen 36 | (`PR #332 `_). 37 | - Fix some typos in the documentation of the class 38 | :py:class:`tespy.components.reactors.water_electrolyzer.WaterElectrolyzer` 39 | (`PR #335 `_). 40 | - Fix an error in the aggregated results of components and busses in the exergy 41 | analysis in case the temperature at turbomachinery is less than or equal to 42 | ambient temperature (`PR #340 `_). 43 | 44 | Other Changes 45 | ############# 46 | - The component :code:`CombustionChamberStoich` has been removed 47 | (`PR #321 `_). 48 | - The fluid property back-end :code:`TESPyFluid` has been removed 49 | (`PR #321 `_). 50 | 51 | Contributors 52 | ############ 53 | - Francesco Witte (`@fwitte `_) 54 | - `@tub-hofmann `_ 55 | - `@nkawerau `_ 56 | - `@BenPortner `_ 57 | - `@matbock `_ 58 | -------------------------------------------------------------------------------- /docs/whats_new/v0-6-1.rst: -------------------------------------------------------------------------------- 1 | v0.6.1 - Leidenfrost's Library (October, 02, 2022) 2 | ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | We have completely revised the documentation improving the overall structure 4 | and introducing a modern look 5 | (`PR #355 `_). Have fun exploring the 6 | website! 7 | 8 | New Features 9 | ############ 10 | - Add support for higher Python versions and remove upper limit 11 | (`PR #350 `_). 12 | - A new component FuelCell is available: 13 | :py:class:`tespy.components.reactors.fuel_cell.FuelCell`. It is analogously 14 | defined to the WaterElectrolyzer 15 | :py:class:`tespy.components.reactors.water_electrolyzer.WaterElectrolyzer` 16 | (`PR #329 `_). 17 | - Integration of an optimization suite using pygmo :cite:`Biscani2020` to apply 18 | a variety of state of the art optimization algorithms to your TESPy model 19 | (`PR #296 `__). It has been further 20 | improved in `PR #357 `__. 21 | - Volumetric flow can be referenced using the 22 | :py:class:`tespy.connections.connection.Ref` class 23 | (`Discussion #352 `__). 24 | 25 | Bug Fixes 26 | ######### 27 | - The Network's component DataFrame is now available as soon as a connection 28 | is added to the network. It is possible to use the 29 | :py:meth:`tespy.networks.network.Network.get_comp` method prior to 30 | initializing or solving 31 | (`PR #362 `_). 32 | 33 | Documentation 34 | ############# 35 | - Fix some typos in the online documentation 36 | (`PR #342 `_). 37 | - New tutorial on starting values for a subcritical heat pump setup 38 | (`PR #346 `_). 39 | 40 | Contributors 41 | ############ 42 | - Francesco Witte (`@fwitte `_) 43 | - `@NicholasFry `_ 44 | - Matthias Bock (`@matbock `_) 45 | - `@maltefritz `_ 46 | -------------------------------------------------------------------------------- /docs/whats_new/v0-6-2.rst: -------------------------------------------------------------------------------- 1 | v0.6.2 - Leidenfrost's Library Hotfix (October, 14, 2022) 2 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | Bug Fixes 5 | ######### 6 | - The Network's component DataFrame is updated when connections are removed 7 | from the Network (`PR #365 `_). 8 | 9 | Contributors 10 | ############ 11 | - Francesco Witte (`@fwitte `_) 12 | -------------------------------------------------------------------------------- /docs/whats_new/v0-6-3.rst: -------------------------------------------------------------------------------- 1 | v0.6.3 - Leidenfrost's Library (July, 30, 2023) 2 | +++++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - A new TESPy logger has been implemented to capture TESPy specific loggings 7 | with a constant string id for the logger object that is retrieved from the 8 | logging module. This allows to modify the logging functionality in a 9 | programmatic way and simplifies the work that has to be done in libraries and 10 | applications that consume the TESPy library 11 | (`PR #390 `__). 12 | - A progress bar for the iterations has been integrated 13 | (`PR #391 `__). 14 | - The chemical exergy analysis features is now available for combustion chamber 15 | and diabatic combustion chamber. The feature also ships the `Ahrendts` 16 | :cite:`Ahrendts1980,Ahrendts1977,Ahrendts1974`, `Szargut1988` 17 | :cite:`Szargut1988` and `Szargut2007` :cite:`Szargut2007,Bakshi2011` chemical 18 | exergy data for the environment model. In your Grassmann exergy flow diagrams 19 | you can now also decide, whether to disaggregate the flows of exergy into 20 | their chemical and physical (and massless, e.g. mechanical or electrical 21 | power) parts (`PR #322 `__). 22 | 23 | Bug Fixes 24 | ######### 25 | - The pressure ratio of the 26 | :py:class:`tespy.components.combustion.diabatic.DiabaticCombustionChamber` 27 | was never calculated in postprocessing if not specified from user 28 | (`PR #380 `_). 29 | - Heat exchangers will now provide a result for the logarithmic temperature 30 | difference and the heat transfer coefficient in case the values of the upper 31 | and lower temperature difference are equal. Some issues in such situations 32 | remain when in offdesign mode 33 | (`PR #396 `__). 34 | - Fix unit display for fluid property ranges in log files 35 | (`PR #420 `__). 36 | - The fluid propagation often got caught in infinite recursion when splitters 37 | and merges are part the network. This PR fixes that bug for many instances 38 | (`PR #427 `__). 39 | 40 | Other Changes 41 | ############# 42 | - Rename `comp_init` method of components to `preprocess` 43 | (`PR #404 `__). 44 | 45 | Contributors 46 | ############ 47 | - Francesco Witte (`@fwitte `__) 48 | - `@jowr `__ 49 | - `@dk-teknologisk-enp `__ 50 | - `@aburabazam `__ 51 | - `@tboussaid `__ 52 | 53 | Special thanks to `@KarimHShawky `__ and 54 | `@tub-hofmann `__ for the compilation and 55 | provision of the standard chemical exergy data. 56 | -------------------------------------------------------------------------------- /docs/whats_new/v0-7-0.rst: -------------------------------------------------------------------------------- 1 | v0.7.0 - Newton's Nature (October, 11, 2023) 2 | ++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | For version 0.7.0 TESPy has undergone a large refactoring of its back end: 5 | 6 | New Features 7 | ############ 8 | 9 | Fluid Properties 10 | ---------------- 11 | 12 | The implementation of the fluid property back end was modularized and is now 13 | much more flexible. The most notable new features are: 14 | 15 | - It is possible to use the same fluid name with different fluid property back 16 | ends in different parts of a single network, e.g. in a Rankine Cycle the main 17 | cycle can be calculated using standard water fluid properties and in the 18 | cooling cycle water may be used as incompressible medium. 19 | - CoolProp's binary incompressible mixtures are now supported. 20 | - The user can implement their own fluid property equations or toolboxes by 21 | masquerading the calls in a standard API inheriting from the new 22 | `FluidPropertyWrapper` class. CoolProp remains the standard back end, but you 23 | may also use other back ends with this feature. 24 | - Similarly, the mixture model can be exchanged by implementing custom mixing 25 | rules for fluid mixtures. 26 | - It is not necessary anymore, to specify the full fluid vector if the sum of 27 | all fixed fluid mass fractions is equal to 1, e.g. if the old specification 28 | was :code:`fluid={"H2O": 1, "Air": 0}` you can now specify 29 | :code:`fluid={"H2O": 1}`. The list of fluids is passed to the `Network` class 30 | anymore, :code:`Network(fluids["H2O", "Air"])` becomes :code:`Network()`. 31 | 32 | Performance Improvements 33 | ------------------------ 34 | 35 | Several performance improvements have been made: 36 | 37 | - Primary variables are not strictly tied to all connections anymore: 38 | 39 | - Any directly specified value removes the respective variable from the 40 | system's variables. For example, a user specified pressure value was part of 41 | the system's variables previously but not touched in the Newton iterations. 42 | Now the variable is directly eliminated effectively reducing the size of the 43 | problem. The same is true for all variables, i.e. mass flow, pressure, 44 | enthalpy and fluid mass fractions. 45 | - If combinations of pressure and temperature, vapor quality or similar are 46 | specified on a single connection, the pressure and enthalpy are pre-solved 47 | if feasible eliminating them from the variable space and eliminating the 48 | respective (e.g. temperature) equation from the equations. 49 | - The plant is subdivided into two types of branches: 50 | 51 | 1. Branches with a single mass flow (connections related to each other in a 52 | way, that their mass flow must be the same). Here the variable space is 53 | reduced to a single mass flow variable. 54 | 2. Branches with identical fluid composition (similar to mass flows, but 55 | e.g. splitters, drums, droplet separators do not change the fluid 56 | composition as well) can also only have a single fluid vector as a 57 | variable and not one per connection. 58 | 59 | - Together with the above changes all partial derivatives now only need to be 60 | calculated, in case a mass flow, pressure, enthalpy or the fluid mass fraction 61 | is a system variable. 62 | 63 | General Improvements 64 | -------------------- 65 | 66 | The code has been simplified and clean up in a lot of places to improve 67 | readability and maintenance. 68 | 69 | 70 | Breaking Changes 71 | ################ 72 | 73 | The release introduces two (known) breaking changes: 74 | 75 | - The structure for saved network states has changed to the minimum necessary 76 | export. Connections only need their label, their parameter values and the 77 | respective units. For that reason, the export of networks to import them at a 78 | different place using the `load_network` functionality has changed as well. If 79 | you want to export a network to load it again, you have to use the `export` 80 | method instead of the `save` method of the network. 81 | - Support for older Python versions (smaller than 3.9) has been dropped. 82 | 83 | Contributors 84 | ############ 85 | - Francesco Witte (`@fwitte `__) 86 | -------------------------------------------------------------------------------- /docs/whats_new/v0-7-1.rst: -------------------------------------------------------------------------------- 1 | v0.7.1 - Newton's Nature (December, 2, 2023) 2 | ++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | Bug Fixes 5 | ######### 6 | - Several bugs introduced by the restructuring of the package in version 0.7.0 7 | have been fixed: 8 | 9 | - `PR #451 `__ 10 | - `PR #453 `__ 11 | 12 | Contributors 13 | ############ 14 | - Francesco Witte (`@fwitte `__) 15 | -------------------------------------------------------------------------------- /docs/whats_new/v0-7-2.rst: -------------------------------------------------------------------------------- 1 | v0.7.1 - Newton's Nature (January, 21, 2024) 2 | ++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | Bug Fixes 5 | ######### 6 | - The `delta` value of the :py:class:`tespy.connections.connection.Ref` class 7 | was oriented with the wrong sign. A positive delta lead to a negative value. 8 | Fixed in (`PR #459 `__). 9 | - In initial simulations the temperature value of mixtures is 0 by default. 10 | For calculating temperatures of the mixtures during that initial simulation, 11 | that value was used as starting value causing CoolProp to raise an error and 12 | the calculation to crash. This is now prevented by checking if the starting 13 | value is reasonable or not 14 | (`PR #477 `__). 15 | 16 | Contributors 17 | ############ 18 | - Francesco Witte (`@fwitte `__) 19 | -------------------------------------------------------------------------------- /docs/whats_new/v0-7-3.rst: -------------------------------------------------------------------------------- 1 | v0.7.3 - Newton's Nature (April, 15, 2024) 2 | ++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | This is a release with some minor fixes and adjustments in 5 | styling. The most relevant change is the exposure of the 6 | `UserDefinedEquation` class to the `tespy.tools` import level. 7 | 8 | Contributors 9 | ############ 10 | - Francesco Witte (`@fwitte `__) 11 | -------------------------------------------------------------------------------- /docs/whats_new/v0-7-4.rst: -------------------------------------------------------------------------------- 1 | v0.7.4 - Newton's Nature (April, 30, 2024) 2 | ++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | Bug Fixes 5 | ######### 6 | - :code:`Component` and :code:`FluidWrapper` objects are now available for the 7 | :code:`load_network` function via the :code:`@component_registry` and 8 | :code:`@wrapper_registry` decorators. E.g. if you are using custom components 9 | you can decorate them with the :code:`@component_registry` and the load a 10 | :code:`Network` with those components without needing to adjust the source 11 | code of the :code:`load_network` function 12 | (`PR #510 `__). 13 | 14 | .. code-block:: python 15 | 16 | >>> from tespy.components.component import component_registry 17 | >>> from tespy.components import Source, Sink, SimpleHeatExchanger 18 | >>> from tespy.connections import Connection 19 | >>> from tespy.networks import Network 20 | 21 | >>> @component_registry 22 | ... class MyComponent(SimpleHeatExchanger): 23 | ... pass 24 | 25 | >>> c = component_registry.items["MyComponent"]("I am a component") 26 | >>> c.label 27 | 'I am a component' 28 | 29 | >>> nwk = Network() 30 | >>> c1 = Connection(Source("source"), "out1", c, "in1", label="1") 31 | >>> c2 = Connection(c, "out1", Sink("sink"), "in1", label="2") 32 | >>> nwk.add_conns(c1, c2) 33 | >>> _ = nwk.export("exported_nwk.json") 34 | >>> nwk = Network.from_json("exported_nwk.json") 35 | >>> nwk.comps.loc["I am a component", "comp_type"] 36 | 'MyComponent' 37 | 38 | Contributors 39 | ############ 40 | - Francesco Witte (`@fwitte `__) 41 | - `@jfreissmann `__ 42 | -------------------------------------------------------------------------------- /docs/whats_new/v0-7-5.rst: -------------------------------------------------------------------------------- 1 | v0.7.5 - Newton's Nature (July, 8, 2024) 2 | ++++++++++++++++++++++++++++++++++++++++ 3 | 4 | Documentation 5 | ############# 6 | - The Rankine cycle example has been adopted to integrate a T-s diagram of the 7 | process into the results 8 | (`PR #514 `__). 9 | - A bug in the results plot of the gas turbine example has been fixed 10 | (`PR #522 `__). 11 | 12 | Other Features 13 | ############## 14 | - More isolines are now available for the drum 15 | (`PR #521 `__). 16 | 17 | Other Changes 18 | ############# 19 | - Remove unused features in the github workflows and tox testing 20 | (`PR #523 `__). 21 | - Simplify dependency installation readthedocs builds 22 | (`PR #524 `__). 23 | - Update various parts of the source code to implement more maintainer-friendly 24 | features (`PR #525 `__). 25 | - Create :code:`numpy` 2.0 compatibility 26 | (`PR #527 `__). 27 | 28 | Contributors 29 | ############ 30 | - Francesco Witte (`@fwitte `__) 31 | - `@Nzb0731 `__ 32 | - `@jfreissmann `__ 33 | -------------------------------------------------------------------------------- /docs/whats_new/v0-7-6-001.rst: -------------------------------------------------------------------------------- 1 | v0.7.6.post1 - Newton's Nature (August, 02, 2024) 2 | +++++++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | This is a post release for version 0.7.6 to fix a bug in the postprocessing of 5 | the :code:`HeatExchanger` classes. 6 | 7 | Bug Fixes 8 | ######### 9 | - An exception is catched in the heat exchanger post processing, in case the 10 | heat exchanger effectiveness cannot be calculated when hot side or cold side 11 | inlet temperature value are out of bounds of the fluid properties for the 12 | other side respectively 13 | (`PR #533 `__). 14 | 15 | Contributors 16 | ############ 17 | - Francesco Witte (`@fwitte `__) 18 | -------------------------------------------------------------------------------- /docs/whats_new/v0-7-6.rst: -------------------------------------------------------------------------------- 1 | v0.7.6 - Newton's Nature (July, 31, 2024) 2 | +++++++++++++++++++++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - Implement new equations for the heat exchanger, i.e. effectiveness parameter. 7 | The parameter can be specified for the hot side `eff_hot` or the cold side 8 | `eff_cold` of the heat exchanger. Additionally, it is possible to specify the 9 | maximum value of both with `eff_max` if it is unknown, which one of them will 10 | be the larger one (`PR #529 `__). 11 | 12 | Bug Fixes 13 | ######### 14 | - The enthalpy numerical precision critereon for mixtures is relaxed: Mixture 15 | fluid property results (temperature, volume, entropy, ...) are only 16 | invalidated, if both absolute and relative precision is not acquired. 17 | Previously, the enthalpy of the mixture, calculated with the temperature 18 | calculated based on the enthalpy determined by the solver had to be within 19 | :code:`1e-3` of the enthalpy determined by the solver 20 | (`PR #529 `__). 21 | 22 | Bug Fixes 23 | ######### 24 | - Fix the logging text for component paramter value violation in the 25 | postprocessing (`PR #529 `__). 26 | 27 | Contributors 28 | ############ 29 | - Francesco Witte (`@fwitte `__) 30 | -------------------------------------------------------------------------------- /docs/whats_new/v0-7-7.rst: -------------------------------------------------------------------------------- 1 | v0.7.7 - Newton's Nature (October, 27, 2024) 2 | ++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | Bug Fixes 5 | ######### 6 | - Only :code:`.json` format files are loaded by the `load_network` method. 7 | Furthermore, it is checked whether a file is represented by a class 8 | available in the namespace via the :code:`@component_registry` decorator 9 | (`PR #536 `__). 10 | - Fixed a typo in the Jacobian of the hot side and cold side 11 | :code:`HeatExchanger` effectiveness. 12 | 13 | Other Changes 14 | ############# 15 | - Make the :code:`reset_topology_reduction_specifications` method of the 16 | `Network` class a public method 17 | (`PR #559 `__). 18 | - Components of class :code:`SimpleHeatExchanger` need explicit specification 19 | of the :code:`dissipative` attribute in the next major version of tespy in 20 | context of the exergy analysis 21 | (`PR #563 `__). 22 | 23 | Documentation 24 | ############# 25 | - Update deprecated information on the indices of variables in the Jacobian of 26 | a :code:`UserDefinedEquation` 27 | (`PR #552 `__). 28 | - A note has been added, that the component and connection labels in subsystems 29 | should be made unique. On top of that, most of the components module docs isn 30 | now testable (`PR #553 `__). 31 | 32 | Contributors 33 | ############ 34 | - Francesco Witte (`@fwitte `__) 35 | -------------------------------------------------------------------------------- /docs/whats_new/v0-7-8-001.rst: -------------------------------------------------------------------------------- 1 | v0.7.8.post1 - Newton's Nature (December, 06, 2024) 2 | +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | Bug Fixes 5 | ######### 6 | - Fixed a too low upper value boundary for the new :code:`dp` parameter. 7 | 8 | Contributors 9 | ############ 10 | - Francesco Witte (`@fwitte `__) 11 | -------------------------------------------------------------------------------- /docs/whats_new/v0-7-8-002.rst: -------------------------------------------------------------------------------- 1 | v0.7.8.post2 - Newton's Nature (December, 29, 2024) 2 | +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | Bug Fixes 5 | ######### 6 | - Fixed a bug in post processing of the :code:`ttd_min` parameter of 7 | :code:`HeatExchangers` 8 | (`PR #587 `__). 9 | 10 | Contributors 11 | ############ 12 | - `@tlmerbecks `__ 13 | - Francesco Witte (`@fwitte `__) 14 | -------------------------------------------------------------------------------- /docs/whats_new/v0-7-8.rst: -------------------------------------------------------------------------------- 1 | v0.7.8 - Newton's Nature (December, 04, 2024) 2 | +++++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - The `HeatExchanger` class now has three new attributes, :code:`dp1`, 7 | :code:`dp2` (hot side and cold side pressure drop in network pressure unit) 8 | as well as :code:`ttd_min` for the minimal value of the terminal temperature 9 | diference values 10 | (`PR #581 `__). 11 | 12 | Contributors 13 | ############ 14 | - Francesco Witte (`@fwitte `__) 15 | -------------------------------------------------------------------------------- /docs/whats_new/v0-7-9.rst: -------------------------------------------------------------------------------- 1 | v0.7.9 - Newton's Nature (March, 02, 2025) 2 | ++++++++++++++++++++++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - Implement a new property for connections to report the phase of the fluid, 7 | i.e. :code:`"l"` for liquid, :code:`"tp"` for two-phase and :code:`"g"` for 8 | gaseous. The phase is only reported in subcritical pressure 9 | (`PR #592 `__). 10 | - Implement the Baumann correlation for wet expansion in steamturbines. The 11 | feature is available in a new component class, 12 | :py:class:`tespy.components.turbomachinery.steam_turbine.SteamTurbine`. To 13 | use the feature check the documentation of the component class 14 | (`PR #602 `__). 15 | - Implement a new component class 16 | :py:class:`tespy.components.heat_exchangers.movingboundary.MovingBoundaryHeatExchanger`, 17 | which allows to make specification of internal pinch temperature difference 18 | in case of heat exchanger internal phase changes on the hot or the cold side 19 | of the component. It splits the heat exchange automatically in sections, 20 | where in each section the phase of the hot and the cold fluid does not change. 21 | These sections are utilized to find the minimum pinch internally, and allow 22 | to assing heat transfer coefficients `UA` for all individual sections as well 23 | as the total sum 24 | (`PR #515 `__). 25 | 26 | Bug Fixes 27 | ######### 28 | - Run the postprocessing only for a converged solution. Otherwise specified 29 | values on buses, components or connections may change to nonsense, because 30 | the calculation is based on not-converged results of the variables 31 | (`PR #609 `__). 32 | - Fix the fuel cell example and make sure it is tested properly 33 | (`PR #618 `__). 34 | 35 | Contributors 36 | ############ 37 | - `@tlmerbecks `__ 38 | - Francesco Witte (`@fwitte `__) 39 | -------------------------------------------------------------------------------- /docs/whats_new/v0-8-0-001.rst: -------------------------------------------------------------------------------- 1 | Fixes for v0.8.0 2 | ++++++++++++++++ 3 | 4 | Bug Fixes 5 | ######### 6 | - A bug was fixed in CoolProp version 6.8.0 7 | `#2447 `__ for the S800 8 | fluid. The tests/examples affected by this in tespy have been updated 9 | (`PR #640 `__). 10 | - In case a heat exchanger heats up the same mass flow (e.g. in a recuperator 11 | or internal heat exchanger), the derivative to the mass flow was assigned 12 | wrong (`PR #646 `__). 13 | 14 | Other Changes 15 | ############# 16 | - To improve convergence for offdesign calculation and problems with small 17 | initial increment of the variables the heuristics for the convergence check 18 | based on the components have been adjusted 19 | (`PR #641 `__). 20 | - Update code, which was subject to be changed with the major release of 0.8. 21 | 22 | Contributors 23 | ############ 24 | - Francesco Witte (`@fwitte `__) 25 | -------------------------------------------------------------------------------- /docs/whats_new/v0-8-1.rst: -------------------------------------------------------------------------------- 1 | v0.8.1 - Newton's Nature (May, 29, 2025) 2 | ++++++++++++++++++++++++++++++++++++++++ 3 | 4 | New Features 5 | ############ 6 | - The :code:`CoolPropWrapper` API can now handle CoolProp based mixtures 7 | and allows the user to specify which type of mixture fractions to use 8 | (mass, molar, volume). This is mostly for REFPROP support and will require 9 | further adaptions for the :code:`CoolPropWrapper` in the future, because the 10 | pure fluid functions may not be applicable in the context of mixtures 11 | (`PR #655 `__). 12 | 13 | In case you are working with incompressible mixtures, this feature is API 14 | breaking. You need to append :code:`|mass`, :code:`|volume` or 15 | :code:`|molar` to your fluid name string at the very end to specify, which 16 | type of mixture is used. This information can be retrieved from the 17 | CoolProp online documentation on the incompressible fluids. 18 | 19 | Bug Fixes 20 | ######### 21 | - In case parts of a :code:`Network` were missing a :code:`CycleCloser` or 22 | a :code:`Source` and :code:`Sink` combination a misleading error was raised. 23 | These cases are checked for explicitly now to make debugging easier 24 | (`PR #653 `__). 25 | - The logging of warnings for :code:`HeatExchanger` based components includes 26 | the label of the component, when cold or hot side effectiveness cannot be 27 | calculated (`PR #670 `__). 28 | 29 | Contributors 30 | ############ 31 | - Francesco Witte (`@fwitte `__) 32 | -------------------------------------------------------------------------------- /docs/whats_new/v0-8-2.rst: -------------------------------------------------------------------------------- 1 | v0.8.2 - Newton's Nature (June, 12, 2025) 2 | +++++++++++++++++++++++++++++++++++++++++ 3 | 4 | API changes 5 | ########### 6 | - The API of the :code:`Subsystem` class has been revised to make it act more 7 | like a :code:`Network`. You can get components and connections from the 8 | subsystem with respective methods, and the :code:`SubsystemInterface` class 9 | is utilized to target the :code:`subsystem.inlet` and 10 | :code:`subsystem.outlet` in a :code:`Connection` object. For the required 11 | changes please check the respective section 12 | :ref:`in the docs ` 13 | (`PR #652 `__). 14 | - The attribute :code:`progress` of the class :code:`Network` has been removed. 15 | (`PR #684 `__). 16 | - To raise an :code:`AssertionError` on non-convergence of a simulation you 17 | must now use :code:`Network.assert_convergence()` instead of 18 | :code:`Network._convergence_check()` 19 | (`PR #684 `__). 20 | 21 | New Features 22 | ############ 23 | - The combustion based component classes :code:`CombustionChamber`, 24 | :code:`DiabaticCombustionChamber` and :code:`CombustionEngine` can now handle 25 | carbonmonoxide as fuel 26 | (`PR #674 `__). 27 | - The :code:`Network`'s :code:`solve` method will now assign status values 28 | depending of the outcome of the simulation. Check the section on 29 | :ref:`convergence ` for more information 30 | (`PR #684 `__). 31 | 32 | Other Changes 33 | ############# 34 | - The partial derivatives for specified temperature are only calculated towards 35 | enthalpy and pressure, not towards the fluid compostion. The reason for this 36 | is, that it is not intended, that the composition of a fluid can be 37 | determined by specifying temperature. Removing this saves a lot of 38 | computational overhead for mixtures 39 | (`PR #674 `__). 40 | - The calculation of the logarithmic temperature difference in heat exchanger 41 | classes was error-prone due to rounding differences in temperature. The 42 | calculation is now consistent through all respective classes and can handle 43 | temperature differences to a precision of :code:`1e-6` 44 | (`PR #679 `__). 45 | - The export method :code:`to_exerpy` now includes the results for components 46 | (`PR #680 `__). 47 | 48 | Contributors 49 | ############ 50 | - Francesco Witte (`@fwitte `__) 51 | -------------------------------------------------------------------------------- /docs/zliterature.rst: -------------------------------------------------------------------------------- 1 | Literature 2 | ========== 3 | 4 | .. bibliography:: references.bib 5 | :all: 6 | :style: unsrt 7 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["flit_core >=3.2,<4"] 3 | build-backend = "flit_core.buildapi" 4 | 5 | [tool.flit.sdist] 6 | include = [ 7 | "CHANGELOG.rst", 8 | "CODE_OF_CONDUCT.md", 9 | "CONTRIBUTING.md", 10 | "LICENSE*", 11 | "PULL_REQUEST_TEMPLATE.md", 12 | ".coveragerc", 13 | ".editorconfig", 14 | ".pep8speaks.yml", 15 | ".readthedocs.yml", 16 | "paper.bib", 17 | "paper.md", 18 | "tox.ini", 19 | "docs/", 20 | "tests/", 21 | "tutorial/", 22 | ] 23 | exclude = ["docs/_build"] 24 | 25 | [project] 26 | name = "tespy" 27 | version = "0.8.2" 28 | description = "Thermal Engineering Systems in Python (TESPy)" 29 | readme = "README.rst" 30 | authors = [ 31 | {name = "Francesco Witte", email = "tespy@witte.sh"}, 32 | ] 33 | classifiers = [ 34 | "Development Status :: 4 - Beta", 35 | "Intended Audience :: Education", 36 | "Intended Audience :: Science/Research", 37 | "License :: OSI Approved :: MIT License", 38 | "Operating System :: Microsoft :: Windows", 39 | "Operating System :: POSIX", 40 | "Operating System :: Unix", 41 | "Programming Language :: Python", 42 | "Programming Language :: Python :: 3.9", 43 | "Programming Language :: Python :: 3.10", 44 | "Programming Language :: Python :: 3.11", 45 | "Topic :: Scientific/Engineering", 46 | ] 47 | requires-python = ">=3.9" 48 | dependencies = [ 49 | "CoolProp>=6.8", 50 | "jinja2", 51 | "matplotlib>=3.2.1", 52 | "numpy>=1.13.3", 53 | "pandas>=1.3.0", 54 | "scipy", 55 | "tabulate>=0.8.2", 56 | ] 57 | license = {text = "MIT"} 58 | 59 | [project.urls] 60 | Homepage = "https://github.com/oemof/tespy" 61 | Documentation = "https://tespy.readthedocs.io/" 62 | Changelog = "https://tespy.readthedocs.io/en/main/whats_new.html" 63 | "Issue Tracker" = "https://github.com/oemof/tespy/issues" 64 | 65 | [project.optional-dependencies] 66 | dev = [ 67 | "build", 68 | "flit", 69 | "fluprodia", 70 | "furo", 71 | "iapws", 72 | "pyromat", 73 | "pytest", 74 | "sphinx>=7.2.2", 75 | "sphinx-copybutton", 76 | "sphinx-design", 77 | "sphinxcontrib.bibtex", 78 | "tox", 79 | ] 80 | 81 | [tool.pytest.ini_options] 82 | python_files = [ 83 | "test_*.py", 84 | "*_test.py", 85 | "tests.py", 86 | ] 87 | addopts = """ 88 | -ra 89 | --strict-markers 90 | --doctest-modules 91 | --doctest-glob=\"*.rst\" 92 | --tb=short 93 | --pyargs 94 | --ignore=docs/conf.py 95 | --ignore=docs/scripts 96 | --ignore=docs/_build 97 | """ 98 | testpaths = [ 99 | "src/", 100 | "tests/", 101 | "docs/", 102 | ] 103 | 104 | [tool.isort] 105 | force_single_line = true 106 | line_length = 120 107 | known_first_party = "tespy" 108 | default_section = "THIRDPARTY" 109 | forced_separate = "test_tespy" 110 | skip = "migrations" 111 | 112 | [tool.coverage.run] 113 | branch = true 114 | source = ["src"] 115 | parallel = true 116 | 117 | [tool.coverage.report] 118 | show_missing = true 119 | precision = 2 120 | omit = ["migrations"] 121 | -------------------------------------------------------------------------------- /src/tespy/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | import importlib.resources 3 | import os 4 | import sys 5 | import warnings 6 | 7 | if sys.version_info[1] < 10: 8 | msg = ( 9 | "Supprt for python versions below 3.10 will be dropped with the " 10 | "next major release" 11 | ) 12 | warnings.warn(FutureWarning(msg)) 13 | 14 | __datapath__ = os.path.join(importlib.resources.files("tespy"), "data") 15 | __version__ = '0.8.2 - Newton\'s Nature' 16 | 17 | # tespy data and connections import 18 | from . import connections # noqa: F401 19 | from . import data # noqa: F401 20 | # tespy components imports 21 | from .components import basics # noqa: F401 22 | from .components import combustion # noqa: F401 23 | from .components import component # noqa: F401 24 | from .components import heat_exchangers # noqa: F401 25 | from .components import nodes # noqa: F401 26 | from .components import piping # noqa: F401 27 | from .components import reactors # noqa: F401 28 | from .components import subsystem # noqa: F401 29 | from .components import turbomachinery # noqa: F401 30 | # tespy networks imports 31 | from .networks import network # noqa: F401 32 | from .networks import network_reader # noqa: F401 33 | # tespy tools imports 34 | from .tools import characteristics # noqa: F401 35 | from .tools import data_containers # noqa: F401 36 | from .tools import fluid_properties # noqa: F401 37 | from .tools import global_vars # noqa: F401 38 | from .tools import helpers # noqa: F401 39 | from .tools import logger # noqa: F401 40 | -------------------------------------------------------------------------------- /src/tespy/components/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | from .basics.cycle_closer import CycleCloser # noqa: F401 4 | from .basics.sink import Sink # noqa: F401 5 | from .basics.source import Source # noqa: F401 6 | from .basics.subsystem_interface import SubsystemInterface # noqa: F401 7 | from .combustion.base import CombustionChamber # noqa: F401 8 | from .combustion.diabatic import DiabaticCombustionChamber # noqa: F401 9 | from .combustion.engine import CombustionEngine # noqa: F401 10 | from .heat_exchangers.base import HeatExchanger # noqa: F401 11 | from .heat_exchangers.condenser import Condenser # noqa: F401 12 | from .heat_exchangers.desuperheater import Desuperheater # noqa: F401 13 | from .heat_exchangers.movingboundary import MovingBoundaryHeatExchanger # noqa: F401 14 | from .heat_exchangers.parabolic_trough import ParabolicTrough # noqa: F401 15 | from .heat_exchangers.simple import SimpleHeatExchanger # noqa: F401 16 | from .heat_exchangers.solar_collector import SolarCollector # noqa: F401 17 | from .nodes.droplet_separator import DropletSeparator # noqa: F401 18 | from .nodes.drum import Drum # noqa: F401 19 | from .nodes.merge import Merge # noqa: F401 20 | from .nodes.separator import Separator # noqa: F401 21 | from .nodes.splitter import Splitter # noqa: F401 22 | from .piping.pipe import Pipe # noqa: F401 23 | from .piping.valve import Valve # noqa: F401 24 | from .reactors.fuel_cell import FuelCell # noqa: F401 25 | from .reactors.water_electrolyzer import WaterElectrolyzer # noqa: F401 26 | from .subsystem import Subsystem # noqa: F401 27 | from .turbomachinery.compressor import Compressor # noqa: F401 28 | from .turbomachinery.pump import Pump # noqa: F401 29 | from .turbomachinery.steam_turbine import SteamTurbine # noqa: F401 30 | from .turbomachinery.turbine import Turbine # noqa: F401 31 | -------------------------------------------------------------------------------- /src/tespy/components/basics/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | -------------------------------------------------------------------------------- /src/tespy/components/basics/sink.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | """Module for class Sink. 4 | 5 | 6 | This file is part of project TESPy (github.com/oemof/tespy). It's copyrighted 7 | by the contributors recorded in the version control history of the file, 8 | available from its original location tespy/components/basics/sink.py 9 | 10 | SPDX-License-Identifier: MIT 11 | """ 12 | 13 | import numpy as np 14 | 15 | from tespy.components.component import Component 16 | from tespy.components.component import component_registry 17 | from tespy.tools.data_containers import SimpleDataContainer as dc_simple 18 | 19 | 20 | @component_registry 21 | class Sink(Component): 22 | r""" 23 | A flow drains in a Sink. 24 | 25 | Parameters 26 | ---------- 27 | label : str 28 | The label of the component. 29 | 30 | design : list 31 | List containing design parameters (stated as String). 32 | 33 | offdesign : list 34 | List containing offdesign parameters (stated as String). 35 | 36 | design_path : str 37 | Path to the components design case. 38 | 39 | local_offdesign : boolean 40 | Treat this component in offdesign mode in a design calculation. 41 | 42 | local_design : boolean 43 | Treat this component in design mode in an offdesign calculation. 44 | 45 | char_warnings : boolean 46 | Ignore warnings on default characteristics usage for this component. 47 | 48 | printout : boolean 49 | Include this component in the network's results printout. 50 | 51 | Example 52 | ------- 53 | Create a sink and specify a label. 54 | 55 | >>> from tespy.components import Sink 56 | >>> si = Sink('a labeled sink') 57 | >>> si.component() 58 | 'sink' 59 | >>> si.label 60 | 'a labeled sink' 61 | """ 62 | 63 | @staticmethod 64 | def component(): 65 | return 'sink' 66 | 67 | @staticmethod 68 | def inlets(): 69 | return ['in1'] 70 | 71 | @staticmethod 72 | def get_mandatory_constraints(): 73 | return {} 74 | 75 | @staticmethod 76 | def get_bypass_constraints(): 77 | return {} 78 | 79 | def propagate_to_target(self, branch): 80 | return 81 | 82 | def propagate_wrapper_to_target(self, branch): 83 | branch["components"] += [self] 84 | return 85 | 86 | def exergy_balance(self, T0): 87 | r"""Exergy balance calculation method of a sink. 88 | 89 | A sink does not destroy or produce exergy. The value of 90 | :math:`\dot{E}_\mathrm{bus}` is set to the exergy of the mass flow to 91 | make exergy balancing methods more simple as in general a mass flow can 92 | be fuel, product or loss. 93 | 94 | Parameters 95 | ---------- 96 | T0 : float 97 | Ambient temperature T0 / K. 98 | 99 | Note 100 | ---- 101 | .. math:: 102 | 103 | \dot{E}_\mathrm{bus} = \dot{E}_\mathrm{in}^\mathrm{PH} 104 | """ 105 | self.E_P = np.nan 106 | self.E_F = np.nan 107 | self.E_bus = { 108 | "chemical": self.inl[0].Ex_chemical, 109 | "physical": self.inl[0].Ex_physical, 110 | "massless": 0 111 | } 112 | self.E_D = np.nan 113 | self.epsilon = self._calc_epsilon() 114 | -------------------------------------------------------------------------------- /src/tespy/components/basics/source.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | """Module for class Source. 4 | 5 | 6 | This file is part of project TESPy (github.com/oemof/tespy). It's copyrighted 7 | by the contributors recorded in the version control history of the file, 8 | available from its original location tespy/components/basics/source.py 9 | 10 | SPDX-License-Identifier: MIT 11 | """ 12 | 13 | import numpy as np 14 | 15 | from tespy.components.component import Component 16 | from tespy.components.component import component_registry 17 | from tespy.tools.data_containers import SimpleDataContainer as dc_simple 18 | 19 | 20 | @component_registry 21 | class Source(Component): 22 | r""" 23 | A flow originates from a Source. 24 | 25 | Parameters 26 | ---------- 27 | label : str 28 | The label of the component. 29 | 30 | design : list 31 | List containing design parameters (stated as String). 32 | 33 | offdesign : list 34 | List containing offdesign parameters (stated as String). 35 | 36 | design_path : str 37 | Path to the components design case. 38 | 39 | local_offdesign : boolean 40 | Treat this component in offdesign mode in a design calculation. 41 | 42 | local_design : boolean 43 | Treat this component in design mode in an offdesign calculation. 44 | 45 | char_warnings : boolean 46 | Ignore warnings on default characteristics usage for this component. 47 | 48 | printout : boolean 49 | Include this component in the network's results printout. 50 | 51 | Example 52 | ------- 53 | Create a source and specify a label. 54 | 55 | >>> from tespy.components import Source 56 | >>> so = Source('a labeled source') 57 | >>> so.component() 58 | 'source' 59 | >>> so.label 60 | 'a labeled source' 61 | """ 62 | 63 | @staticmethod 64 | def component(): 65 | return 'source' 66 | 67 | @staticmethod 68 | def outlets(): 69 | return ['out1'] 70 | 71 | @staticmethod 72 | def get_mandatory_constraints(): 73 | return {} 74 | 75 | @staticmethod 76 | def get_bypass_constraints(): 77 | return {} 78 | 79 | @staticmethod 80 | def is_branch_source(): 81 | return True 82 | 83 | def start_branch(self): 84 | outconn = self.outl[0] 85 | branch = { 86 | "connections": [outconn], 87 | "components": [self, outconn.target], 88 | "subbranches": {} 89 | } 90 | outconn.target.propagate_to_target(branch) 91 | 92 | return {outconn.label: branch} 93 | 94 | def start_fluid_wrapper_branch(self): 95 | outconn = self.outl[0] 96 | branch = { 97 | "connections": [outconn], 98 | "components": [self] 99 | } 100 | outconn.target.propagate_wrapper_to_target(branch) 101 | 102 | return {outconn.label: branch} 103 | 104 | def exergy_balance(self, T0): 105 | r"""Exergy balance calculation method of a source. 106 | 107 | A source does not destroy or produce exergy. The value of 108 | :math:`\dot{E}_\mathrm{bus}` is set to the exergy of the mass flow to 109 | make exergy balancing methods more simple as in general a mass flow can 110 | be fuel, product or loss. 111 | 112 | Parameters 113 | ---------- 114 | T0 : float 115 | Ambient temperature T0 / K. 116 | 117 | Note 118 | ---- 119 | .. math:: 120 | 121 | \dot{E}_\mathrm{bus} = \dot{E}_\mathrm{out}^\mathrm{PH} 122 | """ 123 | self.E_P = np.nan 124 | self.E_F = np.nan 125 | self.E_bus = { 126 | "chemical": self.outl[0].Ex_chemical, 127 | "physical": self.outl[0].Ex_physical, 128 | "massless": 0 129 | } 130 | self.E_D = np.nan 131 | self.epsilon = self._calc_epsilon() 132 | -------------------------------------------------------------------------------- /src/tespy/components/combustion/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | -------------------------------------------------------------------------------- /src/tespy/components/customs/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | -------------------------------------------------------------------------------- /src/tespy/components/heat_exchangers/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | -------------------------------------------------------------------------------- /src/tespy/components/nodes/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | -------------------------------------------------------------------------------- /src/tespy/components/piping/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | -------------------------------------------------------------------------------- /src/tespy/components/reactors/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | -------------------------------------------------------------------------------- /src/tespy/components/turbomachinery/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | -------------------------------------------------------------------------------- /src/tespy/connections/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | from .bus import Bus # noqa: F401 4 | from .connection import Connection # noqa: F401 5 | from .connection import Ref # noqa: F401 6 | -------------------------------------------------------------------------------- /src/tespy/data/char_maps.json: -------------------------------------------------------------------------------- 1 | { 2 | "compressor": { 3 | "char_map_pr": { 4 | "DEFAULT": { 5 | "x": [0.810, 0.870, 0.946, 0.971, 1, 1.029, 1.062], 6 | "y": [[0.460, 0.481, 0.502, 0.523, 0.543, 7 | 0.562,0.583, 0.598, 0.606, 0.612], 8 | [0.590, 0.605, 0.620, 0.640, 0.660, 9 | 0.685, 0.703, 0.710, 0.711, 0.713], 10 | [0.767, 0.805, 0.838, 0.859, 0.87, 11 | 0.876, 0.878, 0.878, 0.879, 0.88], 12 | [0.874, 0.908, 0.93, 0.943, 0.953, 13 | 0.961, 0.962, 0.963, 0.963, 0.964], 14 | [0.948, 0.974, 0.987, 0.995, 1.0, 15 | 1.002, 1.005, 1.005, 1.006, 1.006], 16 | [1.014, 1.017, 1.02, 1.023, 1.026, 17 | 1.028, 1.03, 1.032, 1.034, 1.036], 18 | [1.045, 1.047, 1.049, 1.051, 1.052, 19 | 1.053, 1.054, 1.054, 1.055, 1.056]], 20 | "z": [[0.502, 0.493, 0.485, 0.467, 0.442, 21 | 0.411, 0.378, 0.344, 0.31, 0.276], 22 | [0.65, 0.637, 0.617, 0.589, 0.556, 23 | 0.519, 0.482, 0.445, 0.407, 0.37], 24 | [0.931, 0.917, 0.893, 0.859, 0.82, 25 | 0.779, 0.738, 0.698, 0.657, 0.616], 26 | [1.05, 1.02, 0.982, 0.939, 0.895, 27 | 0.851, 0.806, 0.762, 0.717, 0.672], 28 | [1.195, 1.151, 1.102, 1.052, 1.0, 29 | 0.951, 0.9, 0.85, 0.799, 0.748], 30 | [1.34, 1.276, 1.213, 1.149, 1.085, 31 | 1.022, 0.958, 0.894, 0.831, 0.767], 32 | [1.441, 1.37, 1.3, 1.229, 1.158, 33 | 1.088, 1.017, 0.946, 0.876, 0.805]], 34 | "ref": "Plis2016" 35 | } 36 | }, 37 | "char_map_eta_s": { 38 | "DEFAULT": { 39 | "x": [0.810, 0.870, 0.946, 0.971, 1, 1.029, 1.062], 40 | "y": [[0.460, 0.481, 0.502, 0.523, 0.543, 41 | 0.562,0.583, 0.598, 0.606, 0.612], 42 | [0.590, 0.605, 0.620, 0.640, 0.660, 43 | 0.685, 0.703, 0.710, 0.711, 0.713], 44 | [0.767, 0.805, 0.838, 0.859, 0.87, 45 | 0.876, 0.878, 0.878, 0.879, 0.88], 46 | [0.874, 0.908, 0.93, 0.943, 0.953, 47 | 0.961, 0.962, 0.963, 0.963, 0.964], 48 | [0.948, 0.974, 0.987, 0.995, 1.0, 49 | 1.002, 1.005, 1.005, 1.006, 1.006], 50 | [1.014, 1.017, 1.02, 1.023, 1.026, 51 | 1.028, 1.03, 1.032, 1.034, 1.036], 52 | [1.045, 1.047, 1.049, 1.051, 1.052, 53 | 1.053, 1.054, 1.054, 1.055, 1.056]], 54 | "z": [[0.872, 0.885, 0.898, 0.911, 0.925, 55 | 0.94, 0.945, 0.926, 0.903, 0.879], 56 | [0.887, 0.909, 0.93, 0.947, 0.963, 57 | 0.971, 0.965, 0.939, 0.913, 0.887], 58 | [0.891, 0.918, 0.946, 0.973, 1.001, 59 | 1.014, 1.015, 0.986, 0.955, 0.925], 60 | [0.977, 0.977, 0.981, 0.995, 1.007, 61 | 1.002, 0.981, 0.961, 0.94, 0.92], 62 | [0.956, 0.959, 0.969, 0.984, 1.0, 63 | 0.985, 0.967, 0.95, 0.932, 0.914], 64 | [0.948, 0.959, 0.962, 0.949, 0.935, 65 | 0.922, 0.908, 0.895, 0.881, 0.868], 66 | [0.879, 0.888, 0.898, 0.907, 0.916, 67 | 0.924, 0.915, 0.906, 0.896, 0.887]], 68 | "ref": "Plis2016" 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/tespy/networks/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | from .network import Network # noqa: F401 3 | from .network_reader import load_network # noqa: F401 4 | -------------------------------------------------------------------------------- /src/tespy/tools/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | from .analyses import ExergyAnalysis # noqa: F401 4 | from .characteristics import CharLine # noqa: F401 5 | from .characteristics import CharMap # noqa: F401 6 | from .characteristics import load_custom_char # noqa: F401 7 | from .characteristics import load_default_char # noqa: F401 8 | from .data_containers import ComponentCharacteristicMaps # noqa: F401 9 | from .data_containers import ComponentCharacteristics # noqa: F401 10 | from .data_containers import ComponentProperties # noqa: F401 11 | from .data_containers import FluidComposition # noqa: F401 12 | from .data_containers import FluidProperties # noqa: F401 13 | from .data_containers import GroupedComponentProperties # noqa: F401 14 | from .data_containers import SimpleDataContainer # noqa: F401 15 | from .document_models import document_model # noqa: F401 16 | from .helpers import UserDefinedEquation # noqa: F401 17 | from .optimization import OptimizationProblem # noqa: F401 18 | -------------------------------------------------------------------------------- /src/tespy/tools/fluid_properties/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | from .functions import Q_mix_ph # noqa: F401 4 | from .functions import T_mix_ph # noqa: F401 5 | from .functions import T_mix_ps # noqa: F401 6 | from .functions import T_sat_p # noqa: F401 7 | from .functions import dh_mix_dpQ # noqa: F401 8 | from .functions import dT_mix_dph # noqa: F401 9 | from .functions import dT_mix_pdh # noqa: F401 10 | from .functions import dT_sat_dp # noqa: F401 11 | from .functions import dv_mix_dph # noqa: F401 12 | from .functions import dv_mix_pdh # noqa: F401 13 | from .functions import h_mix_pQ # noqa: F401 14 | from .functions import h_mix_pT # noqa: F401 15 | from .functions import isentropic # noqa: F401 16 | from .functions import phase_mix_ph # noqa: F401 17 | from .functions import s_mix_ph # noqa: F401 18 | from .functions import s_mix_pT # noqa: F401 19 | from .functions import v_mix_ph # noqa: F401 20 | from .functions import v_mix_pT # noqa: F401 21 | from .functions import viscosity_mix_ph # noqa: F401 22 | from .functions import viscosity_mix_pT # noqa: F401 23 | from .helpers import single_fluid # noqa: F401 24 | from .wrappers import CoolPropWrapper # noqa: F401 25 | -------------------------------------------------------------------------------- /src/tespy/tools/global_vars.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | """Module for global variables used by other modules of the tespy package. 4 | 5 | This file is part of project TESPy (github.com/oemof/tespy). It's copyrighted 6 | by the contributors recorded in the version control history of the file, 7 | available from its original location tespy/tools/global_vars.py 8 | 9 | SPDX-License-Identifier: MIT 10 | """ 11 | 12 | ERR = 1e-6 13 | molar_masses = {} 14 | gas_constants = {} 15 | gas_constants['uni'] = 8.314462618 16 | 17 | fluid_property_data = { 18 | 'm': { 19 | 'text': 'mass flow', 20 | 'SI_unit': 'kg / s', 21 | 'units': { 22 | 'kg / s': 1, 'kg / min': 1 / 60, 'kg / h': 1 / 3.6e3, 23 | 't / h': 1 / 3.6, 'g / s': 1 / 1e3 24 | }, 25 | 'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', 26 | 'documentation': {'float_fmt': '{:,.3f}'} 27 | }, 28 | 'v': { 29 | 'text': 'volumetric flow', 30 | 'SI_unit': 'm3 / s', 31 | 'units': { 32 | 'm3 / s': 1, 'm3 / min': 1 / 60, 'm3 / h': 1 / 3.6e3, 33 | 'l / s': 1 / 1e3, 'l / min': 1 / 60e3, 'l / h': 1 / 3.6e6 34 | }, 35 | 'latex_eq': ( 36 | r'0 = \dot{m} \cdot v \left(p,h\right)- \dot{V}_\mathrm{spec}'), 37 | 'documentation': {'float_fmt': '{:,.3f}'} 38 | }, 39 | 'p': { 40 | 'text': 'pressure', 41 | 'SI_unit': 'Pa', 42 | 'units': { 43 | 'Pa': 1, 'kPa': 1e3, 'psi': 6.8948e3, 44 | 'bar': 1e5, 'atm': 1.01325e5, 'MPa': 1e6 45 | }, 46 | 'latex_eq': r'0 = p - p_\mathrm{spec}', 47 | 'documentation': {'float_fmt': '{:,.3f}'} 48 | }, 49 | 'h': { 50 | 'text': 'enthalpy', 51 | 'SI_unit': 'J / kg', 52 | 'units': { 53 | 'J / kg': 1, 'kJ / kg': 1e3, 'MJ / kg': 1e6, 54 | 'cal / kg': 4.184, 'kcal / kg': 4.184e3, 55 | 'Wh / kg': 3.6e3, 'kWh / kg': 3.6e6 56 | }, 57 | 'latex_eq': r'0 = h - h_\mathrm{spec}', 58 | 'documentation': {'float_fmt': '{:,.3f}'} 59 | }, 60 | 'T': { 61 | 'text': 'temperature', 62 | 'SI_unit': 'K', 63 | 'units': { 64 | 'K': [0, 1], 'R': [0, 5 / 9], 65 | 'C': [273.15, 1], 'F': [459.67, 5 / 9] 66 | }, 67 | 'latex_eq': r'0 = T \left(p, h \right) - T_\mathrm{spec}', 68 | 'documentation': {'float_fmt': '{:,.1f}'} 69 | }, 70 | 'Td_bp': { 71 | 'text': 'temperature difference to boiling point', 72 | 'SI_unit': 'K', 73 | 'units': { 74 | 'K': 1, 'R': 5 / 9, 'C': 1, 'F': 5 / 9 75 | }, 76 | 'latex_eq': r'0 = \Delta T_\mathrm{spec}- T_\mathrm{sat}\left(p\right)', 77 | 'documentation': {'float_fmt': '{:,.1f}'} 78 | }, 79 | 'vol': { 80 | 'text': 'specific volume', 81 | 'SI_unit': 'm3 / kg', 82 | 'units': {'m3 / kg': 1, 'l / kg': 1e-3}, 83 | 'latex_eq': ( 84 | r'0 = v\left(p,h\right) \cdot \dot{m} - \dot{V}_\mathrm{spec}'), 85 | 'documentation': {'float_fmt': '{:,.3f}'} 86 | }, 87 | 'x': { 88 | 'text': 'vapor mass fraction', 89 | 'SI_unit': '-', 90 | 'units': {'-': 1, '%': 1e-2, 'ppm': 1e-6}, 91 | 'latex_eq': r'0 = h - h\left(p, x_\mathrm{spec}\right)', 92 | 'documentation': {'float_fmt': '{:,.2f}'} 93 | }, 94 | 's': { 95 | 'text': 'entropy', 96 | 'SI_unit': 'J / kgK', 97 | 'units': {'J / kgK': 1, 'kJ / kgK': 1e3, 'MJ / kgK': 1e6}, 98 | 'latex_eq': r'0 = s_\mathrm{spec} - s\left(p, h \right)', 99 | 'documentation': {'float_fmt': '{:,.2f}'} 100 | }, 101 | 102 | } 103 | 104 | combustion_gases = [ 105 | 'methane', 'ethane', 'propane', 'butane', 'hydrogen', 'nDodecane', 106 | 'CO' 107 | ] 108 | -------------------------------------------------------------------------------- /tests/test_advanced_tutorials.py: -------------------------------------------------------------------------------- 1 | import os 2 | import runpy 3 | 4 | import pytest 5 | 6 | path = os.path.join(os.path.dirname(__file__), "..", "tutorial", "advanced") 7 | scripts = (os.path.join(path, f) for f in os.listdir(path) if f.endswith(".py")) 8 | 9 | 10 | @pytest.mark.parametrize('script', scripts) 11 | def test_tutorial_execution(script): 12 | try: 13 | runpy.run_path(script) 14 | except ModuleNotFoundError: 15 | pytest.skip("Test skipped due to missing dependency") -------------------------------------------------------------------------------- /tests/test_analyses/test_entropy_analysis.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | """Module for testing network properties. 4 | 5 | This file is part of project TESPy (github.com/oemof/tespy). It's copyrighted 6 | by the contributors recorded in the version control history of the file, 7 | available from its original location 8 | tests/test_networks/test_exergy_and_entropy_analysis.py 9 | 10 | SPDX-License-Identifier: MIT 11 | """ 12 | from tespy.components import CycleCloser 13 | from tespy.components import Merge 14 | from tespy.components import Pump 15 | from tespy.components import SimpleHeatExchanger 16 | from tespy.components import Splitter 17 | from tespy.components import Turbine 18 | from tespy.connections import Bus 19 | from tespy.connections import Connection 20 | from tespy.networks import Network 21 | 22 | 23 | class TestClausiusRankine: 24 | 25 | def setup_method(self): 26 | """Set up clausis rankine cycle with turbine driven feed water pump.""" 27 | self.Tamb = 20 28 | self.pamb = 1 29 | self.nw = Network() 30 | self.nw.set_attr(p_unit='bar', T_unit='C', h_unit='kJ / kg') 31 | 32 | # create components 33 | splitter1 = Splitter('splitter 1') 34 | merge1 = Merge('merge 1') 35 | turb = Turbine('turbine') 36 | fwp_turb = Turbine('feed water pump turbine') 37 | condenser = SimpleHeatExchanger('condenser') 38 | fwp = Pump('pump') 39 | steam_generator = SimpleHeatExchanger('steam generator') 40 | cycle_close = CycleCloser('cycle closer') 41 | 42 | # create busses 43 | # power output bus 44 | self.power = Bus('power_output') 45 | self.power.add_comps({'comp': turb, 'char': 1}) 46 | # turbine driven feed water pump internal bus 47 | self.fwp_power = Bus('feed water pump power', P=0) 48 | self.fwp_power.add_comps( 49 | {'comp': fwp_turb, 'char': 1}, 50 | {'comp': fwp, 'char': 1, 'base': 'bus'}) 51 | # heat input bus 52 | self.heat = Bus('heat_input') 53 | self.heat.add_comps({'comp': steam_generator, 'base': 'bus'}) 54 | self.nw.add_busses(self.power, self.fwp_power, self.heat) 55 | 56 | # create connections 57 | fs_in = Connection(cycle_close, 'out1', splitter1, 'in1', label='fs') 58 | fs_fwpt = Connection(splitter1, 'out1', fwp_turb, 'in1') 59 | fs_t = Connection(splitter1, 'out2', turb, 'in1') 60 | fwpt_ws = Connection(fwp_turb, 'out1', merge1, 'in1') 61 | t_ws = Connection(turb, 'out1', merge1, 'in2') 62 | ws = Connection(merge1, 'out1', condenser, 'in1') 63 | cond = Connection(condenser, 'out1', fwp, 'in1', label='cond') 64 | fw = Connection(fwp, 'out1', steam_generator, 'in1', label='fw') 65 | fs_out = Connection(steam_generator, 'out1', cycle_close, 'in1') 66 | self.nw.add_conns(fs_in, fs_fwpt, fs_t, fwpt_ws, t_ws, ws, cond, fw, 67 | fs_out) 68 | 69 | # component parameters 70 | turb.set_attr(eta_s=1) 71 | fwp_turb.set_attr(eta_s=1) 72 | condenser.set_attr(pr=1) 73 | fwp.set_attr(eta_s=1) 74 | steam_generator.set_attr(pr=1) 75 | 76 | # connection parameters 77 | fs_in.set_attr(m=10, p=120, T=600, fluid={'water': 1}) 78 | cond.set_attr(T=self.Tamb, x=0) 79 | 80 | # solve network 81 | self.nw.solve('design') 82 | for cp in self.nw.comps['object']: 83 | cp.entropy_balance() 84 | self.nw.assert_convergence() 85 | 86 | def test_entropy_perfect_cycle(self): 87 | """Test entropy values in the perfect clausius rankine cycle.""" 88 | labels = [ 89 | 'turbine', 'feed water pump turbine', 'condenser', 90 | 'steam generator', 'pump' 91 | ] 92 | for label in labels: 93 | cp = self.nw.get_comp(label) 94 | msg = ( 95 | 'Entropy production due to irreversibility must be 0 for all ' 96 | 'components in this test but is ' + str(round(cp.S_irr, 4)) + 97 | ' at component ' + label + ' of type ' + cp.component() + '.') 98 | assert round(cp.S_irr, 4) == 0, msg 99 | sg = self.nw.get_comp('steam generator') 100 | cd = self.nw.get_comp('condenser') 101 | msg = ( 102 | 'Value of entropy production due to heat input at steam generator ' 103 | '(S_Q=' + str(round(sg.S_Q, 4)) + ') must equal the negative ' 104 | 'value of entropy reduction in condenser (S_Q=' + 105 | str(round(cd.S_Q, 4)) + ').') 106 | assert round(sg.S_Q, 4) == -round(cd.S_Q, 4), msg 107 | -------------------------------------------------------------------------------- /tests/test_basic_tutorials.py: -------------------------------------------------------------------------------- 1 | import os 2 | import runpy 3 | 4 | import pytest 5 | 6 | path = os.path.join(os.path.dirname(__file__), "..", "tutorial", "basics") 7 | scripts = (os.path.join(path, f) for f in os.listdir(path) if f.endswith(".py")) 8 | 9 | 10 | @pytest.mark.parametrize('script', scripts) 11 | def test_tutorial_execution(script): 12 | runpy.run_path(script) -------------------------------------------------------------------------------- /tests/test_components/test_customs.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | """Module for testing components of type orc evaporator. 4 | This file is part of project TESPy (github.com/oemof/tespy). It's copyrighted 5 | by the contributors recorded in the version control history of the file, 6 | available from its original location 7 | tests/test_components/test_customs.py 8 | SPDX-License-Identifier: MIT 9 | """ 10 | -------------------------------------------------------------------------------- /tests/test_components/test_drum.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | """Module for testing components of type merge. 4 | This file is part of project TESPy (github.com/oemof/tespy). It's copyrighted 5 | by the contributors recorded in the version control history of the file, 6 | available from its original location 7 | tests/test_components/test_merge.py 8 | SPDX-License-Identifier: MIT 9 | """ 10 | from pytest import approx 11 | from pytest import fixture 12 | 13 | from tespy.components import Drum 14 | from tespy.components import SimpleHeatExchanger 15 | from tespy.components import Sink 16 | from tespy.components import Source 17 | from tespy.components import Splitter 18 | from tespy.connections import Connection 19 | from tespy.networks import Network 20 | 21 | 22 | @fixture() 23 | def drum_network_setup(): 24 | nw = Network(T_unit="C", p_unit="bar") 25 | dr = Drum("drum") 26 | so = Source("liquid") 27 | si = Sink("vapor") 28 | c1 = Connection(so, "out1", dr, "in1", label="1") 29 | c2 = Connection(dr, "out2", si, "in1", label="2") 30 | nw.add_conns(c1, c2) 31 | c1.set_attr(fluid={"R290": 1}, m=10, Td_bp=-10, T=50) 32 | yield nw 33 | 34 | 35 | def test_drum_with_blowdown(drum_network_setup): 36 | nw = drum_network_setup 37 | sp = Splitter("blowdown splitter") 38 | si = Sink("blowdown sink") 39 | eva = SimpleHeatExchanger("evaporator") 40 | dr = nw.get_comp("drum") 41 | c3 = Connection(dr, "out1", sp, "in1", label="3") 42 | c4 = Connection(sp, "out1", si, "in1", label="4") 43 | c5 = Connection(sp, "out2", eva, "in1", label="5") 44 | c6 = Connection(eva, "out1", dr, "in2", label="6") 45 | 46 | c6.set_attr(x=0.7, m=15) 47 | 48 | nw.add_conns(c3, c4, c5, c6) 49 | 50 | nw.solve("design") 51 | 52 | assert 0.72728 == approx(c4.m.val_SI) 53 | -------------------------------------------------------------------------------- /tests/test_components/test_merge.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | """Module for testing components of type merge. 4 | This file is part of project TESPy (github.com/oemof/tespy). It's copyrighted 5 | by the contributors recorded in the version control history of the file, 6 | available from its original location 7 | tests/test_components/test_merge.py 8 | SPDX-License-Identifier: MIT 9 | """ 10 | 11 | from pytest import approx 12 | 13 | from tespy.components import Merge 14 | from tespy.components import SimpleHeatExchanger 15 | from tespy.components import Sink 16 | from tespy.components import Source 17 | from tespy.components import Splitter 18 | from tespy.connections import Connection 19 | from tespy.networks import Network 20 | 21 | 22 | class TestMerge: 23 | 24 | def setup_method(self): 25 | self.nwk = Network(T_unit="C", p_unit="bar", h_unit="kJ / kg") 26 | 27 | so1 = Source("Source1") 28 | so2 = Source("Source2") 29 | me = Merge("Merge") 30 | si = Sink("Sink") 31 | 32 | c1 = Connection(so1, "out1", me, "in1", label="1") 33 | c2 = Connection(so2, "out1", me, "in2", label="2") 34 | c3 = Connection(me, "out1", si, "in1", label="3") 35 | 36 | self.nwk.add_conns(c1, c2, c3) 37 | 38 | def test_single_fluid_at_outlet(self): 39 | 40 | c1, c2, c3 = self.nwk.get_conn(["1", "2", "3"]) 41 | c1.set_attr(m=5, p=10, h=200) 42 | c2.set_attr(m=5, h=200) 43 | c3.set_attr(fluid={"water": 1}) 44 | 45 | self.nwk.solve("design") 46 | self.nwk.assert_convergence() 47 | 48 | target = c1.m.val_SI + c2.m.val_SI 49 | msg = f"Target value for mass flow at connection 3 must be {target}." 50 | assert c3.m.val_SI == approx(target), msg 51 | 52 | def test_massflows_from_two_fluid_fractions(self): 53 | 54 | c1, c2, c3 = self.nwk.get_conn(["1", "2", "3"]) 55 | c1.set_attr(m=5, p=10, h=200, fluid={"N2": 1}) 56 | c2.set_attr(h=200, fluid={"O2": 1}) 57 | c3.set_attr(fluid={"N2": 0.3, "O2": 0.7}) 58 | 59 | self.nwk.solve("design") 60 | self.nwk.assert_convergence() 61 | 62 | target = c1.m.val / c3.fluid.val["N2"] 63 | msg = f"Target value for mass flow at connection 3 is {target}" 64 | assert c3.m.val_SI == approx(target), msg 65 | 66 | 67 | class TestCyclicMerging: 68 | """ 69 | Testing issue raised in https://github.com/oemof/tespy/issues/424 70 | """ 71 | 72 | def setup_method(self): 73 | 74 | self.nwk = Network(T_unit="C", p_unit="bar", h_unit="kJ / kg") 75 | 76 | source = Source("source1") 77 | merge = Merge("merge") 78 | component1 = SimpleHeatExchanger("comp1", pr=1) 79 | splitter = Splitter("splitter") 80 | component2 = SimpleHeatExchanger("comp2") 81 | sink = Sink("sink") 82 | 83 | c1 = Connection(source, "out1", merge, "in1", label="1") 84 | c2 = Connection(merge, "out1", component1, "in1", label="2") 85 | c3 = Connection(component1, "out1", splitter, "in1", label="3") 86 | c4 = Connection(splitter, "out1", component2, "in1", label="4") 87 | c5 = Connection(component2, "out1", merge, "in2", label="5") 88 | c6 = Connection(splitter, "out2", sink, "in1", label="6") 89 | 90 | self.nwk.add_conns(c1, c2, c3, c4, c5, c6) 91 | 92 | def test_single_fluid_setup(self): 93 | 94 | c1, c3, c4, c5, c6 = self.nwk.get_conn(["1", "3", "4", "5", "6"]) 95 | 96 | c1.set_attr(p=1, h=200, m=10, fluid={"R134a": 1}) 97 | c3.set_attr(h=180) 98 | c4.set_attr(m=1) 99 | c5.set_attr(h=170) 100 | 101 | self.nwk.solve("design") 102 | self.nwk.assert_convergence() 103 | 104 | target = c1.m.val_SI 105 | msg = f"Target value for mass flow at connection 3 is {target}" 106 | assert c6.m.val_SI == approx(target), msg 107 | 108 | def test_two_fluid_setup(self): 109 | c1, c3, c4, c5, c6 = self.nwk.get_conn(["1", "3", "4", "5", "6"]) 110 | 111 | c1.set_attr(p=1, h=200, m=10, fluid={"R134a": 1}) 112 | c3.set_attr(h=180) 113 | c4.set_attr(m=1) 114 | c5.set_attr(h=170) 115 | 116 | self.nwk.solve("design") 117 | self.nwk.assert_convergence() 118 | 119 | target = c1.m.val_SI 120 | msg = f"Target value for mass flow at connection 3 is {target}" 121 | assert c6.m.val_SI == approx(target), msg 122 | -------------------------------------------------------------------------------- /tests/test_components/test_piping.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | """Module for testing components of the piping module. 4 | 5 | This file is part of project TESPy (github.com/oemof/tespy). It's copyrighted 6 | by the contributors recorded in the version control history of the file, 7 | available from its original location 8 | tests/test_components/test_piping.py 9 | 10 | SPDX-License-Identifier: MIT 11 | """ 12 | import numpy as np 13 | 14 | from tespy.components import Pipe 15 | from tespy.components import Sink 16 | from tespy.components import Source 17 | from tespy.components import Valve 18 | from tespy.connections import Connection 19 | from tespy.networks import Network 20 | from tespy.tools.characteristics import CharLine 21 | 22 | 23 | class TestPiping: 24 | 25 | def setup_piping_network(self, instance): 26 | self.nw = Network(T_unit='C', p_unit='bar') 27 | self.source = Source('source') 28 | self.sink = Sink('sink') 29 | self.c1 = Connection(self.source, 'out1', instance, 'in1') 30 | self.c2 = Connection(instance, 'out1', self.sink, 'in1') 31 | self.nw.add_conns(self.c1, self.c2) 32 | 33 | def test_Valve(self): 34 | """Test component properties of valves.""" 35 | instance = Valve('valve') 36 | self.setup_piping_network(instance) 37 | 38 | # parameter specification 39 | self.c1.set_attr(fluid={'CH4': 1}, m=10, p=10, T=120) 40 | self.c2.set_attr(p=1) 41 | 42 | # test variable pressure ration 43 | instance.set_attr(pr='var') 44 | self.nw.solve('design') 45 | self.nw.assert_convergence() 46 | pr = round(self.c2.p.val_SI / self.c1.p.val_SI, 2) 47 | msg = ('Value of pressure ratio must be ' + str(pr) + ', is ' + 48 | str(round(instance.pr.val, 2)) + '.') 49 | assert pr == round(instance.pr.val, 2), msg 50 | 51 | # test variable zeta value 52 | zeta = round(instance.zeta.val, 0) 53 | instance.set_attr(zeta='var', pr=None) 54 | self.nw.solve('design') 55 | self.nw.assert_convergence() 56 | msg = ('Value of dimension independent zeta value must be ' + 57 | str(zeta) + ', is ' + str(round(instance.zeta.val, 0)) + '.') 58 | assert zeta == round(instance.zeta.val, 0), msg 59 | 60 | # dp char 61 | x = np.array([8, 9, 10, 11, 12]) 62 | y = np.array([5, 8, 9, 9.5, 9.6]) * 1e5 63 | dp_char = CharLine(x, y) 64 | instance.set_attr(zeta=None, dp_char={ 65 | 'char_func': dp_char, 'is_set': True}) 66 | m = 11 67 | self.c1.set_attr(m=m) 68 | self.c2.set_attr(p=None) 69 | self.nw.solve('design') 70 | self.nw.assert_convergence() 71 | self.nw.print_results() 72 | dp = round(-dp_char.evaluate(m), 0) 73 | dp_act = round(self.c2.p.val_SI - self.c1.p.val_SI) 74 | msg = ('The pressure drop at the valve should be ' + str(dp) + ' but ' 75 | 'is ' + str(dp_act) + '.') 76 | assert dp == dp_act, msg 77 | 78 | def test_Pipe(self): 79 | """Test component properties of pipe.""" 80 | instance = Pipe('pipe') 81 | self.setup_piping_network(instance) 82 | 83 | # NO TEST NEEDED AT THE MOMENT, THE PIPE PROPERTIES ARE IDENTICAL TO 84 | # THE PROPERTIES OF THE SIMPLE HEAT EXCHANGER. TESTS ARE LOCATED AT 85 | # heat_exchanger_tests.py 86 | -------------------------------------------------------------------------------- /tests/test_connections.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | """Module for testing busses. 4 | 5 | This file is part of project TESPy (github.com/oemof/tespy). It's copyrighted 6 | by the contributors recorded in the version control history of the file, 7 | available from its original location 8 | tests/test_busses.py 9 | 10 | SPDX-License-Identifier: MIT 11 | """ 12 | 13 | from tespy.components import Sink 14 | from tespy.components import Source 15 | from tespy.connections import Connection 16 | from tespy.connections import Ref 17 | from tespy.networks import Network 18 | from tespy.tools.helpers import convert_from_SI 19 | 20 | 21 | class TestConnections: 22 | 23 | def setup_method(self): 24 | """Set up the model.""" 25 | self.nw = Network(p_unit='bar', T_unit='C', v_unit="l / s", m_unit="t / h") 26 | 27 | so1 = Source('source 1') 28 | so2 = Source('source 2') 29 | si1 = Sink('sink 1') 30 | si2 = Sink('sink 2') 31 | 32 | c1 = Connection(so1, 'out1', si1, 'in1', label='Some example label') 33 | c2 = Connection(so2, 'out1', si2, 'in1') 34 | 35 | self.nw.add_conns(c1, c2) 36 | 37 | c1.set_attr(m=1, p=1, T=25, fluid={'Air': 1}) 38 | c2.set_attr(m=0.5, p=10, T=25, fluid={'Air': 1}) 39 | 40 | self.nw.solve('design') 41 | 42 | def test_volumetric_flow_reference(self): 43 | """Test the referenced volumetric flow.""" 44 | c1, c2 = self.nw.get_conn( 45 | ['Some example label', 'source 2:out1_sink 2:in1'] 46 | ) 47 | c2.set_attr(m=None, v=Ref(c1, 1, 0)) 48 | self.nw.solve('design') 49 | 50 | m_expected = round(c1.m.val * c1.vol.val / c2.vol.val, 4) 51 | m_is = round(c2.m.val, 4) 52 | msg = ( 53 | 'The mass flow of the connection 2 should be equal to ' 54 | f'{m_expected} kg/s, but is {m_is} kg/s' 55 | ) 56 | assert m_is == m_expected, msg 57 | 58 | c2.set_attr(v=Ref(c1, 2, 10)) 59 | self.nw.solve('design') 60 | 61 | v_expected = round(c1.v.val * 2 + 10, 4) 62 | v_is = round(c2.v.val, 4) 63 | msg = ( 64 | 'The mass flow of the connection 2 should be equal to ' 65 | f'{v_expected} l/s, but is {v_is} l/s' 66 | ) 67 | assert v_is == v_expected, msg 68 | 69 | def test_temperature_reference(self): 70 | """Test the referenced temperature.""" 71 | c1, c2 = self.nw.get_conn( 72 | ['Some example label', 'source 2:out1_sink 2:in1'] 73 | ) 74 | c2.set_attr(T=None) 75 | c2.set_attr(T=Ref(c1, 1, 0)) 76 | 77 | self.nw.solve('design') 78 | 79 | T_expected = round(c1.T.val, 4) 80 | T_is = round(c2.T.val, 4) 81 | msg = ( 82 | 'The temperature of the connection 2 should be equal to ' 83 | f'{T_expected} C, but is {T_is} C' 84 | ) 85 | assert T_is == T_expected, msg 86 | 87 | c2.set_attr(T=Ref(c1, 1.5, -75)) 88 | self.nw.solve('design') 89 | 90 | T_expected = round(convert_from_SI("T", c1.T.val_SI * 1.5, c1.T.unit) - 75, 4) 91 | T_is = round(c2.T.val, 4) 92 | msg = ( 93 | 'The temperature of the connection 2 should be equal to ' 94 | f'{T_expected} C, but is {T_is} C' 95 | ) 96 | assert T_is == T_expected, msg 97 | 98 | def test_primary_reference(self): 99 | """Test referenced primary variable.""" 100 | c1, c2 = self.nw.get_conn( 101 | ['Some example label', 'source 2:out1_sink 2:in1'] 102 | ) 103 | c2.set_attr(m=None) 104 | c2.set_attr(m=Ref(c1, 1, 0)) 105 | 106 | self.nw.solve('design') 107 | 108 | m_expected = round(c1.m.val, 4) 109 | m_is = round(c2.m.val, 4) 110 | msg = ( 111 | 'The mass flow of the connection 2 should be equal to ' 112 | f'{m_expected} kg/s, but is {m_is} kg/s' 113 | ) 114 | assert m_is == m_expected, msg 115 | 116 | c2.set_attr(m=Ref(c1, 2, -0.5)) 117 | self.nw.solve('design') 118 | 119 | m_expected = round(convert_from_SI("m", c1.m.val_SI * 2, c1.m.unit) - 0.5, 4) 120 | m_is = round(c2.m.val, 4) 121 | msg = ( 122 | 'The mass flow of the connection 2 should be equal to ' 123 | f'{m_expected} kg/s, but is {m_is} kg/s' 124 | ) 125 | assert m_is == m_expected, msg 126 | -------------------------------------------------------------------------------- /tests/test_heat_pump_exergy.py: -------------------------------------------------------------------------------- 1 | import os 2 | import runpy 3 | 4 | import pytest 5 | 6 | path = os.path.join(os.path.dirname(__file__), "..", "tutorial", "heat_pump_exergy") 7 | scripts = (os.path.join(path, f) for f in os.listdir(path) if f.endswith(".py") and f != "plots.py") 8 | 9 | 10 | @pytest.mark.parametrize('script', scripts) 11 | def test_tutorial_execution(script): 12 | try: 13 | runpy.run_path(script) 14 | except ModuleNotFoundError: 15 | pytest.skip("Test skipped due to missing dependency") -------------------------------------------------------------------------------- /tests/test_models/cgam-ebsilon-results.csv: -------------------------------------------------------------------------------- 1 | ,m,T,p,h,s,N2,O2,CO2,H2O,CH4,P 2 | 1,90.95607457,298.15,1.013,25.54462052,6.959011766,0.7748,0.2059,0.0003,0.019,0 3 | 2,90.95607457,611.0017687,10.13,351.6329236,7.036467531,0.7748,0.2059,0.0003,0.019,0 4 | 3,90.95607457,850,9.623,615.0663618,7.414722394,0.7748,0.2059,0.0003,0.019,0 5 | 4,92.60039501,1520.00001,9.142,1476.468227,8.32714917,0.75057,0.13691,0.03157,0.08095,0 6 | 5,92.60039501,1010.9922,1.099,832.1976645,8.435597263,0.75057,0.13691,0.03157,0.08095,0 7 | 6,92.60039501,794.2475402,1.066,573.442057,8.156767346,0.75057,0.13691,0.03157,0.08095,0 8 | 6p,92.60039501,532.4008782,1.0395,277.4765691,7.712996342,0.75057,0.13691,0.03157,0.08095,0 9 | 7,92.60039501,430.0422698,1.013,166.50407,7.489199432,0.75057,0.13691,0.03157,0.08095,0 10 | 8,14,298.15,20,106.6769842,0.366707889,0,0,0,1,0 11 | 8p,14,470.5272254,20,840.6839368,2.304887098,0,0,0,1,0 12 | 9,14,485.5272256,20,2798.292603,6.339006637,0,0,0,1,0 13 | 10,1.644320438,298.15,12,54.77825261,10.33378605,0,0,0,0,1 14 | AC,,,,,,,,,,,29659712 15 | EXP,,,,,,,,,,,-59659709 16 | -------------------------------------------------------------------------------- /tests/test_networks/design_state/busses.json: -------------------------------------------------------------------------------- 1 | { 2 | "total power output": { 3 | "compressor": 942962.5546897707, 4 | "turbine": -1942962.5546897715 5 | } 6 | } -------------------------------------------------------------------------------- /tests/test_networks/design_state/components/CombustionChamber.csv: -------------------------------------------------------------------------------- 1 | ;lamb;ti 2 | combustion;3.0569404567072014;2830665.2214692426 3 | -------------------------------------------------------------------------------- /tests/test_networks/design_state/components/Compressor.csv: -------------------------------------------------------------------------------- 1 | ;P;pr;dp;eta_s;igva 2 | compressor;942962.5546897707;10.0;-9.0;0.8799999999999998;nan 3 | -------------------------------------------------------------------------------- /tests/test_networks/design_state/components/SimpleHeatExchanger.csv: -------------------------------------------------------------------------------- 1 | ;Q;pr;dp;zeta;D;L;ks;ks_HW;kA;Tamb 2 | fuel preheater;1683.058395253897;0.25;30.0;11618007742.658394;nan;nan;nan;nan;nan;nan 3 | -------------------------------------------------------------------------------- /tests/test_networks/design_state/components/Sink.csv: -------------------------------------------------------------------------------- 1 | "" 2 | -------------------------------------------------------------------------------- /tests/test_networks/design_state/components/Source.csv: -------------------------------------------------------------------------------- 1 | "" 2 | -------------------------------------------------------------------------------- /tests/test_networks/design_state/components/Turbine.csv: -------------------------------------------------------------------------------- 1 | ;P;pr;dp;eta_s 2 | turbine;-1942962.5546897715;0.1;9.0;0.8999999999984899 3 | -------------------------------------------------------------------------------- /tests/test_networks/design_state/connections.csv: -------------------------------------------------------------------------------- 1 | ;m;m_unit;v;v_unit;p;p_unit;h;h_unit;T;T_unit;Td_bp;Td_bp_unit;vol;vol_unit;x;x_unit;s;s_unit;Ar;CO2;N2;O2;H2O;CH4;phase 2 | ambient air;2.9806404310591246;kg / s;2.5510294199168175;m3 / s;1.0;bar;298.5072132870764;kJ / kg;25.0;C;0.0;C;0.8558662069179369;m3 / kg;0.0;-;6863.951017983647;J / kgK;0.0129;0.0;0.7556;0.2315;0.0;0.0;nan 3 | compressor:out1_combustion:in1;2.9806404310591246;kg / s;0.5208592782275424;m3 / s;10.0;bar;614.8696114025389;kJ / kg;333.9145499752034;C;0.0;C;0.174747437765401;m3 / kg;0.0;-;6928.423164802237;J / kgK;0.0129;0.0;0.7556;0.2315;0.0;0.0;nan 4 | fuel:out1_fuel preheater:in1;0.058941183587408665;kg / s;0.00207807299157296;m3 / s;40.0;bar;856.9279645910249;kJ / kg;25.0;C;0.0;C;0.035256723144882506;m3 / kg;0.0;-;4608.521667706131;J / kgK;0.0;0.04;0.0;0.0;0.0;0.96;nan 5 | fuel preheater:out1_combustion:in2;0.058941183587408665;kg / s;0.008731548689244886;m3 / s;10.0;bar;885.4828440965908;kJ / kg;25.0;C;0.0;C;0.14814002973483156;m3 / kg;0.0;-;5379.530355955076;J / kgK;0.0;0.04;0.0;0.0;0.0;0.96;nan 6 | combustion:out1_turbine:in1;3.0395816146465333;kg / s;1.2178448307141214;m3 / s;10.0;bar;1646.6569281296818;kJ / kg;1099.9999032861047;C;0.0;C;0.400661994021089;m3 / kg;0.0;-;7814.209028623376;J / kgK;0.012649854253243865;0.051843258872292054;0.7409480522287648;0.15275011552273815;0.04180871912296114;0.0;nan 7 | turbine:out1_sink:in1;3.0395816146465333;kg / s;7.517699852953736;m3 / s;1.0;bar;1007.4365349915576;kJ / kg;575.6266962800402;C;0.0;C;2.473267971068431;m3 / kg;0.0;-;7901.068425237439;J / kgK;0.012649854253243865;0.051843258872292054;0.7409480522287648;0.15275011552273815;0.04180871912296114;0.0;nan 8 | -------------------------------------------------------------------------------- /tests/test_networks/exported_nwk/busses.json: -------------------------------------------------------------------------------- 1 | { 2 | "total power output": { 3 | "P": { 4 | "val": -1000000.0000000005, 5 | "is_set": true 6 | }, 7 | "compressor": { 8 | "param": null, 9 | "base": "bus", 10 | "char": { 11 | "x": [ 12 | 0.0, 13 | 3.0 14 | ], 15 | "y": [ 16 | 1.0, 17 | 1.0 18 | ], 19 | "extrapolate": false 20 | } 21 | }, 22 | "turbine": { 23 | "param": null, 24 | "base": "component", 25 | "char": { 26 | "x": [ 27 | 0.0, 28 | 3.0 29 | ], 30 | "y": [ 31 | 1.0, 32 | 1.0 33 | ], 34 | "extrapolate": false 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /tests/test_networks/exported_nwk/components/CombustionChamber.json: -------------------------------------------------------------------------------- 1 | { 2 | "combustion": { 3 | "design": [], 4 | "offdesign": [], 5 | "local_design": false, 6 | "local_offdesign": false, 7 | "design_path": null, 8 | "printout": true, 9 | "fkt_group": "combustion", 10 | "char_warnings": true, 11 | "lamb": { 12 | "val": 3.0569404567072036, 13 | "val_SI": 0, 14 | "is_set": false, 15 | "d": 0.0001, 16 | "min_val": 1, 17 | "max_val": 1000000000000.0, 18 | "is_var": false 19 | }, 20 | "ti": { 21 | "val": 2830665.221469252, 22 | "val_SI": 0, 23 | "is_set": false, 24 | "d": 0.0001, 25 | "min_val": 0, 26 | "max_val": 1000000000000.0, 27 | "is_var": false 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /tests/test_networks/exported_nwk/components/Sink.json: -------------------------------------------------------------------------------- 1 | { 2 | "sink": { 3 | "design": [], 4 | "offdesign": [], 5 | "local_design": false, 6 | "local_offdesign": false, 7 | "design_path": null, 8 | "printout": true, 9 | "fkt_group": "sink", 10 | "char_warnings": true 11 | } 12 | } -------------------------------------------------------------------------------- /tests/test_networks/exported_nwk/components/Source.json: -------------------------------------------------------------------------------- 1 | { 2 | "air": { 3 | "design": [], 4 | "offdesign": [], 5 | "local_design": false, 6 | "local_offdesign": false, 7 | "design_path": null, 8 | "printout": true, 9 | "fkt_group": "air", 10 | "char_warnings": true 11 | }, 12 | "fuel": { 13 | "design": [], 14 | "offdesign": [], 15 | "local_design": false, 16 | "local_offdesign": false, 17 | "design_path": null, 18 | "printout": true, 19 | "fkt_group": "fuel", 20 | "char_warnings": true 21 | } 22 | } -------------------------------------------------------------------------------- /tests/test_networks/exported_nwk/components/Turbine.json: -------------------------------------------------------------------------------- 1 | { 2 | "turbine": { 3 | "design": [ 4 | "eta_s" 5 | ], 6 | "offdesign": [ 7 | "eta_s_char", 8 | "cone" 9 | ], 10 | "local_design": false, 11 | "local_offdesign": false, 12 | "design_path": null, 13 | "printout": true, 14 | "fkt_group": "turbine", 15 | "char_warnings": true, 16 | "P": { 17 | "val": -1942962.554689775, 18 | "val_SI": 0, 19 | "is_set": false, 20 | "d": 0.0001, 21 | "min_val": -1000000000000.0, 22 | "max_val": 1000000000000.0, 23 | "is_var": false 24 | }, 25 | "pr": { 26 | "val": 0.1, 27 | "val_SI": 0, 28 | "is_set": false, 29 | "d": 0.0001, 30 | "min_val": -1000000000000.0, 31 | "max_val": 1000000000000.0, 32 | "is_var": false 33 | }, 34 | "dp": { 35 | "val": 9.0, 36 | "val_SI": 900000.0, 37 | "is_set": false, 38 | "d": 0.0001, 39 | "min_val": -1000000000000.0, 40 | "max_val": 1000000000000.0, 41 | "is_var": false 42 | }, 43 | "eta_s": { 44 | "val": 0.8999999999984893, 45 | "val_SI": 0, 46 | "is_set": true, 47 | "d": 0.0001, 48 | "min_val": 0, 49 | "max_val": 1, 50 | "is_var": false 51 | }, 52 | "eta_s_char": { 53 | "char_func": { 54 | "x": [ 55 | 0.0, 56 | 0.3, 57 | 0.6, 58 | 0.7, 59 | 0.8, 60 | 0.9, 61 | 1.0, 62 | 1.1, 63 | 1.2, 64 | 1.3, 65 | 1.4, 66 | 1.5 67 | ], 68 | "y": [ 69 | 0.95, 70 | 0.98, 71 | 0.993, 72 | 0.996, 73 | 0.998, 74 | 0.9995, 75 | 1.0, 76 | 0.999, 77 | 0.996, 78 | 0.99, 79 | 0.98, 80 | 0.96 81 | ], 82 | "extrapolate": false 83 | }, 84 | "is_set": false, 85 | "param": "m", 86 | "char_params": { 87 | "type": "rel", 88 | "inconn": 0, 89 | "outconn": 0 90 | } 91 | }, 92 | "cone": { 93 | "val": NaN, 94 | "is_set": false 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /tests/test_networks/exported_nwk/network.json: -------------------------------------------------------------------------------- 1 | { 2 | "m_unit": "kg / s", 3 | "m_range": [ 4 | -1000000000000.0, 5 | 1000000000000.0 6 | ], 7 | "p_unit": "bar", 8 | "p_range": [ 9 | 0.002, 10 | 300.0 11 | ], 12 | "h_unit": "kJ / kg", 13 | "h_range": [ 14 | 1.0, 15 | 7000.0 16 | ], 17 | "T_unit": "C", 18 | "x_unit": "-", 19 | "v_unit": "m3 / s", 20 | "s_unit": "J / kgK" 21 | } -------------------------------------------------------------------------------- /tests/test_networks/test_binary_incompressible.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | """Module for testing mixing rule propagation in networks. 4 | This file is part of project TESPy (github.com/oemof/tespy). It's copyrighted 5 | by the contributors recorded in the version control history of the file, 6 | available from its original location 7 | tests/test_networks/test_binary_incompressible.py 8 | SPDX-License-Identifier: MIT 9 | """ 10 | 11 | from tespy.components import HeatExchanger 12 | from tespy.components import Pump 13 | from tespy.components import Sink 14 | from tespy.components import Source 15 | from tespy.connections import Connection 16 | from tespy.networks import Network 17 | 18 | 19 | class TestBinaryIncompressibles: 20 | 21 | 22 | def setup_method(self): 23 | self.nw = Network() 24 | 25 | so1 = Source("Source1") 26 | so2 = Source("Source2") 27 | pu = Pump("Pump") 28 | he = HeatExchanger("Heat") 29 | si1 = Sink("Sink1") 30 | si2 = Sink("Sink2") 31 | 32 | c1 = Connection(so1, "out1", pu, "in1", label="1") 33 | c2 = Connection(pu, "out1", he, "in2", label="2") 34 | c3 = Connection(he, "out2", si1, "in1", label="3") 35 | 36 | c4 = Connection(so2, "out1", he, "in1", label="4") 37 | c5 = Connection(he, "out1", si2, "in1", label="5") 38 | 39 | self.nw.add_conns(c1, c2, c3, c4, c5) 40 | 41 | c1.set_attr(v=1, p=1e5, T=300, fluid={"INCOMP::MPG[0.2]|mass": 1}) 42 | c2.set_attr(h0=2e4) 43 | c3.set_attr(p=1e5, T=320, h0=1e5) 44 | 45 | he.set_attr(pr1=0.98, pr2=0.98, ttd_l=10) 46 | pu.set_attr(eta_s=0.7) 47 | 48 | c4.set_attr(p=1e5, T=350, fluid={"INCOMP::MEG[0.2]|mass": 1}) 49 | c5.set_attr(h0=1e5) 50 | 51 | self.nw.solve("design") 52 | 53 | def test_binaries(self): 54 | self.nw.assert_convergence() 55 | -------------------------------------------------------------------------------- /tests/test_networks/test_bypassing.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | """Module for testing network properties. 4 | 5 | This file is part of project TESPy (github.com/oemof/tespy). It's copyrighted 6 | by the contributors recorded in the version control history of the file, 7 | available from its original location 8 | tests/test_networks/test_network.py 9 | 10 | SPDX-License-Identifier: MIT 11 | """ 12 | from tespy.components import HeatExchanger 13 | from tespy.components import Merge 14 | from tespy.components import Pump 15 | from tespy.components import SimpleHeatExchanger 16 | from tespy.components import Sink 17 | from tespy.components import Source 18 | from tespy.components import Splitter 19 | from tespy.components import Turbine 20 | from tespy.components import Valve 21 | from tespy.connections import Connection 22 | from tespy.networks import Network 23 | 24 | 25 | def test_bypass_system(): 26 | nw = Network(p_unit="bar", T_unit="C", h_unit="kJ / kg") 27 | 28 | source = Source("In") 29 | sink = Sink("Out") 30 | heater = SimpleHeatExchanger("Heater") 31 | 32 | c1 = Connection(source, "out1", heater, "in1", "1") 33 | c2 = Connection(heater, "out1", sink, "in1", "2") 34 | 35 | nw.add_conns(c1, c2) 36 | 37 | c1.set_attr(T=100, p=2, m=1, fluid={"water":1}) 38 | heater.set_attr(Q=2e6, pr=0.9) 39 | 40 | nw.solve("design") 41 | nw.assert_convergence() 42 | 43 | msg = "In non-bypass mode, pressure ratio must be the specified value" 44 | assert round(c2.p.val, 4) == round(c1.p.val * 0.9, 4), msg 45 | msg = "In non-bypass mode, temperature must result from heat input" 46 | assert round(c2.T.val, 4) == 116.9113, msg 47 | 48 | heater.set_attr(bypass=True) 49 | 50 | nw.solve("design") 51 | nw.assert_convergence() 52 | msg = "With bypass enabled, temperature an pressure should not change." 53 | assert round(c2.T.val, 4) == round(c1.T.val, 4), msg 54 | 55 | 56 | def test_bypass_regenerative_preheater(): 57 | nw = Network(p_unit='bar', T_unit='C', h_unit='kJ / kg') 58 | 59 | source = Source("In") 60 | turbine_hp = Turbine("high pressure turbine") 61 | extraction = Splitter("steam extraction") 62 | turbine_lp = Turbine("low pressure turbine") 63 | merge = Merge("condensate merge") 64 | main_condenser = SimpleHeatExchanger("main condenser") 65 | pump = Pump("feed water pump") 66 | 67 | preheater = HeatExchanger("preheater") 68 | valve = Valve("condensate throttle") 69 | 70 | sink = Sink("Out") 71 | 72 | 73 | c1 = Connection(source, "out1", turbine_hp, "in1", "1") 74 | c2 = Connection(turbine_hp, "out1", extraction, "in1", "2") 75 | c3 = Connection(extraction, "out1", turbine_lp, "in1", "3") 76 | c4 = Connection(turbine_lp, "out1", merge, "in1", "4") 77 | c5 = Connection(merge, "out1", main_condenser, "in1", "5") 78 | c6 = Connection(main_condenser, "out1", pump, "in1", "6") 79 | c7 = Connection(pump, "out1", preheater, "in2", "7") 80 | c8 = Connection(preheater, "out2", sink, "in1", "8") 81 | nw.add_conns(c1, c2, c3, c4, c5, c6, c7, c8) 82 | 83 | c11 = Connection(extraction, "out2", preheater, "in1", "11") 84 | c12 = Connection(preheater, "out1", valve, "in1", "12") 85 | c13 = Connection(valve, "out1", merge, "in2", "13") 86 | nw.add_conns(c11, c12, c13) 87 | 88 | c1.set_attr(T=500, p=100, m=10, fluid={"water":1}) 89 | c2.set_attr(p=7) 90 | 91 | c4.set_attr(p=0.5) 92 | c6.set_attr(p=0.5, x=0) 93 | c7.set_attr(p=100) 94 | 95 | c11.set_attr(m=1) 96 | c12.set_attr(x=0) 97 | 98 | turbine_hp.set_attr(eta_s=0.9) 99 | turbine_lp.set_attr(eta_s=0.88) 100 | pump.set_attr(eta_s=0.75) 101 | dp1 = 0.2 102 | dp2 = 1 103 | preheater.set_attr(dp1=dp1, dp2=dp2) 104 | 105 | nw.solve("design") 106 | nw.assert_convergence() 107 | 108 | assert round(c12.p.val, 2) == round(c11.p.val - dp1, 2) 109 | assert round(c8.p.val, 2) == round(c7.p.val - dp2, 2) 110 | assert round(c11.h.val, 2) > round(c12.h.val, 2) 111 | assert round(c8.h.val, 2) > round(c7.h.val, 2) 112 | 113 | preheater.set_attr(bypass=True) 114 | c12.set_attr(p=None, x=None) 115 | c8.set_attr(p=None) 116 | nw.solve("design") 117 | nw.assert_convergence() 118 | assert round(c12.p.val, 2) == round(c11.p.val, 2) 119 | assert round(c8.p.val, 2) == round(c7.p.val, 2) 120 | assert round(c11.h.val, 2) == round(c12.h.val, 2) 121 | assert round(c8.h.val, 2) == round(c7.h.val, 2) 122 | -------------------------------------------------------------------------------- /tests/test_tools/test_fluid_properties/test_iapws.py: -------------------------------------------------------------------------------- 1 | from tespy.components import Sink 2 | from tespy.components import Source 3 | from tespy.components import Turbine 4 | from tespy.connections import Connection 5 | from tespy.networks import Network 6 | from tespy.tools.fluid_properties.wrappers import IAPWSWrapper 7 | 8 | 9 | class TestIAPWS: 10 | 11 | def setup_method(self): 12 | self.nwk = Network() 13 | 14 | so = Source("Source") 15 | tu = Turbine("Pump") 16 | si = Sink("Sink") 17 | 18 | c1 = Connection(so, "out1", tu, "in1", label="1") 19 | c2 = Connection(tu, "out1", si, "in1", label="2") 20 | 21 | self.nwk.add_conns(c1, c2) 22 | 23 | tu.set_attr(eta_s=0.9) 24 | 25 | c1.set_attr(v=1, p=1e5, T=500, fluid={"H2O": 1}) 26 | c2.set_attr(p=1e4) 27 | 28 | def test_iapws_95(self): 29 | c1, c2 = self.nwk.get_conn(["1", "2"]) 30 | 31 | self.nwk.solve("design") 32 | self.nwk.assert_convergence() 33 | 34 | h_out_ref = round(c2.h.val_SI, 3) 35 | T_out_ref = round(c2.T.val_SI, 3) 36 | x_out_ref = round(c2.x.val_SI, 3) 37 | 38 | self.setup_method() 39 | c1, c2 = self.nwk.get_conn(["1", "2"]) 40 | c1.set_attr(fluid={"IF95::H2O": 1}, fluid_engines={"H2O": IAPWSWrapper}) 41 | 42 | self.nwk.solve("design") 43 | self.nwk.assert_convergence() 44 | 45 | assert h_out_ref == round(c2.h.val_SI, 3) 46 | assert T_out_ref == round(c2.T.val_SI, 3) 47 | assert x_out_ref == round(c2.x.val_SI, 3) 48 | 49 | def test_iapws_97(self): 50 | c1, c2 = self.nwk.get_conn(["1", "2"]) 51 | c1.set_attr(fluid={"IF97::H2O": 1}) 52 | 53 | self.nwk.solve("design") 54 | self.nwk.assert_convergence() 55 | 56 | h_out_ref = round(c2.h.val_SI / 1000) 57 | T_out_ref = round(c2.T.val_SI) 58 | x_out_ref = round(c2.x.val_SI, 3) 59 | 60 | self.setup_method() 61 | c1, c2 = self.nwk.get_conn(["1", "2"]) 62 | c1.set_attr(fluid={"IF97::H2O": 1}, fluid_engines={"H2O": IAPWSWrapper}) 63 | 64 | self.nwk.solve("design") 65 | self.nwk.assert_convergence() 66 | 67 | assert h_out_ref == round(c2.h.val_SI / 1000) 68 | assert T_out_ref == round(c2.T.val_SI) 69 | assert x_out_ref == round(c2.x.val_SI, 3) 70 | -------------------------------------------------------------------------------- /tests/test_tools/test_fluid_properties/test_pyromat.py: -------------------------------------------------------------------------------- 1 | from tespy.components import Sink 2 | from tespy.components import Source 3 | from tespy.components import Turbine 4 | from tespy.connections import Connection 5 | from tespy.networks import Network 6 | from tespy.tools.fluid_properties.wrappers import PyromatWrapper 7 | 8 | 9 | class TestPyromat: 10 | 11 | def setup_method(self): 12 | self.nwk = Network() 13 | 14 | so = Source("Source") 15 | tu = Turbine("Pump") 16 | si = Sink("Sink") 17 | 18 | c1 = Connection(so, "out1", tu, "in1", label="1") 19 | c2 = Connection(tu, "out1", si, "in1", label="2") 20 | 21 | self.nwk.add_conns(c1, c2) 22 | 23 | tu.set_attr(eta_s=0.9) 24 | 25 | c1.set_attr(v=1, p=1e5, T=500, fluid={"H2O": 1}) 26 | c2.set_attr(p=1e4) 27 | 28 | def test_pyromat(self): 29 | c1, c2 = self.nwk.get_conn(["1", "2"]) 30 | 31 | self.nwk.solve("design") 32 | self.nwk.assert_convergence() 33 | 34 | h_out_ref = round(c2.h.val_SI / 1e3) 35 | T_out_ref = round(c2.T.val_SI) 36 | x_out_ref = round(c2.x.val_SI, 3) 37 | 38 | self.setup_method() 39 | c1, c2 = self.nwk.get_conn(["1", "2"]) 40 | c1.set_attr(fluid={"mp::H2O": 1}, fluid_engines={"H2O": PyromatWrapper}) 41 | 42 | self.nwk.solve("design") 43 | self.nwk.assert_convergence() 44 | 45 | assert h_out_ref == round(c2.h.val_SI / 1e3) 46 | assert T_out_ref == round(c2.T.val_SI) 47 | assert x_out_ref == round(c2.x.val_SI, 3) 48 | -------------------------------------------------------------------------------- /tests/test_tools/test_helpers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 2 | 3 | """Module for testing helper functions. 4 | 5 | This file is part of project TESPy (github.com/oemof/tespy). It's copyrighted 6 | by the contributors recorded in the version control history of the file, 7 | available from its original location 8 | tests/test_tools/test_helpers.py 9 | 10 | SPDX-License-Identifier: MIT 11 | """ 12 | from pytest import approx 13 | 14 | from tespy.tools.helpers import newton_with_kwargs 15 | 16 | 17 | def func(x, **kwargs): 18 | return x ** 2 + x - 20 19 | 20 | 21 | def deriv(x, **kwargs): 22 | return 2 * x + 1 23 | 24 | 25 | def test_newton_bounds(): 26 | """ 27 | Test newton algorithm value limit handling. 28 | 29 | Try to calculate a zero crossing of a quadratic function in three 30 | tries. 31 | 32 | - zero crossing within limits, starting value near 4 33 | - zero crossing within limits, starting value near -5 34 | 35 | - zero crossing below minimum 36 | - zero crossing above maximum 37 | 38 | The function is x^2 + x - 20, there crossings are -5 and 4. 39 | """ 40 | kwargs = {"function": func, "parameter": "x"} 41 | result = newton_with_kwargs(deriv, 0, valmin=-10, valmax=10, val0=0, **kwargs) 42 | msg = ('The newton algorithm should find the zero crossing at 4.0. ' + 43 | str(round(result, 1)) + ' was found instead.') 44 | assert 4.0 == approx(result), msg 45 | 46 | result = newton_with_kwargs(deriv, 0, valmin=-10, valmax=10, val0=-10, **kwargs) 47 | msg = ('The newton algorithm should find the zero crossing at -5.0. ' + 48 | str(round(result, 1)) + ' was found instead.') 49 | assert -5.0 == approx(result), msg 50 | 51 | result = newton_with_kwargs(deriv, 0, valmin=-4, valmax=-2, val0=-3, **kwargs) 52 | msg = ('The newton algorithm should not be able to find a zero crossing. ' 53 | 'The value ' + str(round(result, 1)) + ' was found, but the ' 54 | 'algorithm should have found the lower boundary of -4.0.') 55 | assert -4.0 == approx(result), msg 56 | 57 | result = newton_with_kwargs(deriv, 0, valmin=-20, valmax=-10, val0=-10, **kwargs) 58 | msg = ('The newton algorithm should not be able to find a zero crossing. ' 59 | 'The value ' + str(round(result, 1)) + ' was found, but the ' 60 | 'algorithm should have found the upper boundary of -10.0.') 61 | assert -10.0 == approx(result), msg 62 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = 3 | check, 4 | docs, 5 | py39, 6 | py310, 7 | py311 8 | 9 | [gh-actions] 10 | python = 11 | 3.9: py39 12 | 3.10: py310 13 | 3.11: py311 14 | 15 | [testenv] 16 | basepython = 17 | {check,docs}: {env:TOXPYTHON:python3.11} 18 | setenv = 19 | PYTHONPATH={toxinidir}/tests 20 | PYTHONUNBUFFERED=yes 21 | passenv = 22 | * 23 | extras = 24 | dev 25 | commands = 26 | {posargs:pytest -vv --ignore=src} 27 | 28 | [testenv:check] 29 | deps = 30 | check-manifest 31 | isort 32 | skip_install = true 33 | commands = 34 | check-manifest {toxinidir} 35 | isort --verbose --check-only --diff src tests 36 | 37 | [testenv:docs] 38 | usedevelop = true 39 | commands = 40 | sphinx-build {posargs:-E} -b html docs docs/_build 41 | sphinx-build -b linkcheck docs docs/_build 42 | 43 | [testenv:py39] 44 | basepython = {env:TOXPYTHON:python3.9} 45 | setenv = 46 | {[testenv]setenv} 47 | usedevelop = true 48 | commands = 49 | {posargs:pytest --cov --cov-report=term-missing -vv} 50 | deps = 51 | pytest-cov 52 | 53 | [testenv:py310] 54 | basepython = {env:TOXPYTHON:python3.10} 55 | setenv = 56 | {[testenv]setenv} 57 | usedevelop = true 58 | commands = 59 | {posargs:pytest --cov --cov-report=term-missing -vv} 60 | deps = 61 | pytest-cov 62 | 63 | [testenv:py311] 64 | basepython = {env:TOXPYTHON:python3.11} 65 | setenv = 66 | {[testenv]setenv} 67 | usedevelop = true 68 | commands = 69 | {posargs:pytest --cov --cov-report=term-missing -vv} 70 | deps = 71 | pytest-cov 72 | -------------------------------------------------------------------------------- /tutorial/README.rst: -------------------------------------------------------------------------------- 1 | Tutorials 2 | --------- 3 | These are the python scripts presented as tutorials in the online documentation 4 | of TESPy. The description and explanations on the tutorials can be found in the 5 | `respective sections `_ of the documentation. 6 | -------------------------------------------------------------------------------- /tutorial/basics/heat_pump.py: -------------------------------------------------------------------------------- 1 | # %%[sec_1] 2 | from tespy.networks import Network 3 | 4 | # create a network object with R134a as fluid 5 | my_plant = Network() 6 | # %%[sec_2] 7 | # set the unitsystem for temperatures to °C and for pressure to bar 8 | my_plant.set_attr(T_unit='C', p_unit='bar', h_unit='kJ / kg') 9 | # %%[sec_3] 10 | from tespy.components import ( 11 | CycleCloser, Compressor, Valve, SimpleHeatExchanger 12 | ) 13 | 14 | cc = CycleCloser('cycle closer') 15 | 16 | # heat sink 17 | co = SimpleHeatExchanger('condenser') 18 | # heat source 19 | ev = SimpleHeatExchanger('evaporator') 20 | 21 | va = Valve('expansion valve') 22 | cp = Compressor('compressor') 23 | # %%[sec_4] 24 | from tespy.connections import Connection 25 | 26 | # connections of heat pump 27 | c1 = Connection(cc, 'out1', ev, 'in1', label='1') 28 | c2 = Connection(ev, 'out1', cp, 'in1', label='2') 29 | c3 = Connection(cp, 'out1', co, 'in1', label='3') 30 | c4 = Connection(co, 'out1', va, 'in1', label='4') 31 | c0 = Connection(va, 'out1', cc, 'in1', label='0') 32 | 33 | # this line is crutial: you have to add all connections to your network 34 | my_plant.add_conns(c1, c2, c3, c4, c0) 35 | # %%[sec_5] 36 | co.set_attr(pr=0.98, Q=-1e6) 37 | ev.set_attr(pr=0.98) 38 | cp.set_attr(eta_s=0.85) 39 | 40 | c2.set_attr(T=20, x=1, fluid={'R134a': 1}) 41 | c4.set_attr(T=80, x=0) 42 | # %%[sec_6] 43 | my_plant.solve(mode='design') 44 | my_plant.print_results() 45 | 46 | print(f'COP = {abs(co.Q.val) / cp.P.val}') 47 | # %%[sec_7] 48 | co.set_attr(Q=None) 49 | c1.set_attr(m=5) 50 | 51 | my_plant.solve('design') 52 | my_plant.print_results() 53 | # %%[sec_8] 54 | cp.set_attr(pr=4) 55 | c4.set_attr(T=None) 56 | 57 | my_plant.solve('design') 58 | my_plant.print_results() 59 | # %%[sec_9] 60 | cp.set_attr(pr=None, eta_s=None) 61 | c3.set_attr(T=97.3) 62 | c4.set_attr(T=80) 63 | 64 | my_plant.solve('design') 65 | my_plant.print_results() 66 | # %%[sec_10] 67 | # first go back to the original state of the specifications 68 | co.set_attr(Q=-1e6) 69 | cp.set_attr(pr=None, eta_s=0.85) 70 | c1.set_attr(m=None) 71 | c3.set_attr(T=None) 72 | c4.set_attr(T=80) 73 | 74 | import matplotlib.pyplot as plt 75 | import numpy as np 76 | 77 | # make text reasonably sized 78 | plt.rc('font', **{'size': 18}) 79 | 80 | 81 | data = { 82 | 'T_source': np.linspace(0, 40, 11), 83 | 'T_sink': np.linspace(60, 100, 11), 84 | 'eta_s': np.linspace(0.75, 0.95, 11) * 100 85 | } 86 | COP = { 87 | 'T_source': [], 88 | 'T_sink': [], 89 | 'eta_s': [] 90 | } 91 | description = { 92 | 'T_source': 'Evaporation temperature in °C', 93 | 'T_sink': 'Condensation temperature in °C', 94 | 'eta_s': 'Isentropic efficiency in %' 95 | } 96 | 97 | for T in data['T_source']: 98 | c2.set_attr(T=T) 99 | my_plant.solve('design') 100 | COP['T_source'] += [abs(co.Q.val) / cp.P.val] 101 | 102 | # reset to base temperature 103 | c2.set_attr(T=20) 104 | 105 | for T in data['T_sink']: 106 | c4.set_attr(T=T) 107 | my_plant.solve('design') 108 | COP['T_sink'] += [abs(co.Q.val) / cp.P.val] 109 | 110 | # reset to base temperature 111 | c4.set_attr(T=80) 112 | 113 | for eta_s in data['eta_s']: 114 | cp.set_attr(eta_s=eta_s / 100) 115 | my_plant.solve('design') 116 | COP['eta_s'] += [abs(co.Q.val) / cp.P.val] 117 | 118 | fig, ax = plt.subplots(1, 3, sharey=True, figsize=(16, 8)) 119 | 120 | [a.grid() for a in ax] 121 | 122 | i = 0 123 | for key in data: 124 | ax[i].scatter(data[key], COP[key], s=100, color="#1f567d") 125 | ax[i].set_xlabel(description[key]) 126 | i += 1 127 | 128 | ax[0].set_ylabel('COP of the heat pump') 129 | 130 | plt.tight_layout() 131 | 132 | fig.savefig('heat_pump_parametric.svg') 133 | # %%[sec_11] 134 | -------------------------------------------------------------------------------- /tutorial/heat_pump_exergy/NH3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from tespy.components import Compressor 4 | from tespy.components import Condenser 5 | from tespy.components import CycleCloser 6 | from tespy.components import HeatExchanger 7 | from tespy.components import Sink 8 | from tespy.components import Source 9 | from tespy.components import Valve 10 | from tespy.components import Pump 11 | from tespy.connections import Connection 12 | from tespy.connections import Bus 13 | from tespy.networks import Network 14 | from tespy.tools.characteristics import CharLine 15 | from tespy.tools.characteristics import load_default_char as ldc 16 | import numpy as np 17 | 18 | pamb = 1.013 # ambient pressure 19 | Tamb = 2.8 # ambient temperature 20 | 21 | # mean geothermal temperature (mean value of ground feed and return flow) 22 | Tgeo = 9.5 23 | 24 | nw = Network(T_unit='C', p_unit='bar', h_unit='kJ / kg', m_unit='kg / s') 25 | 26 | # %% components 27 | 28 | cc = CycleCloser('cycle closer') 29 | 30 | # heat pump system 31 | cd = Condenser('condenser') 32 | va = Valve('valve') 33 | ev = HeatExchanger('evaporator') 34 | cp = Compressor('compressor') 35 | 36 | # geothermal heat collector 37 | gh_in = Source('ground heat feed flow') 38 | gh_out = Sink('ground heat return flow') 39 | ghp = Pump('ground heat loop pump') 40 | 41 | # heating system 42 | hs_feed = Sink('heating system feed flow') 43 | hs_ret = Source('heating system return flow') 44 | hsp = Pump('heating system pump') 45 | 46 | # %% connections 47 | 48 | # heat pump system 49 | cc_cd = Connection(cc, 'out1', cd, 'in1') 50 | cd_va = Connection(cd, 'out1', va, 'in1') 51 | va_ev = Connection(va, 'out1', ev, 'in2') 52 | ev_cp = Connection(ev, 'out2', cp, 'in1') 53 | cp_cc = Connection(cp, 'out1', cc, 'in1') 54 | nw.add_conns(cc_cd, cd_va, va_ev, ev_cp, cp_cc) 55 | 56 | # geothermal heat collector 57 | gh_in_ghp = Connection(gh_in, 'out1', ghp, 'in1') 58 | ghp_ev = Connection(ghp, 'out1', ev, 'in1') 59 | ev_gh_out = Connection(ev, 'out1', gh_out, 'in1') 60 | nw.add_conns(gh_in_ghp, ghp_ev, ev_gh_out) 61 | 62 | # heating system 63 | hs_ret_hsp = Connection(hs_ret, 'out1', hsp, 'in1') 64 | hsp_cd = Connection(hsp, 'out1', cd, 'in2') 65 | cd_hs_feed = Connection(cd, 'out2', hs_feed, 'in1') 66 | nw.add_conns(hs_ret_hsp, hsp_cd, cd_hs_feed) 67 | 68 | 69 | # %% component parametrization 70 | 71 | # condenser 72 | cd.set_attr(pr1=0.99, pr2=0.99, ttd_u=5, design=['pr2', 'ttd_u'], 73 | offdesign=['zeta2', 'kA_char']) 74 | # evaporator 75 | kA_char1 = ldc('heat exchanger', 'kA_char1', 'DEFAULT', CharLine) 76 | kA_char2 = ldc('heat exchanger', 'kA_char2', 'EVAPORATING FLUID', CharLine) 77 | ev.set_attr(pr1=0.99, pr2=0.99, ttd_l=5, 78 | kA_char1=kA_char1, kA_char2=kA_char2, 79 | design=['pr1', 'ttd_l'], offdesign=['zeta1', 'kA_char']) 80 | # compressor 81 | cp.set_attr(eta_s=0.8, design=['eta_s'], offdesign=['eta_s_char']) 82 | # heating system pump 83 | hsp.set_attr(eta_s=0.75, design=['eta_s'], offdesign=['eta_s_char']) 84 | # ground heat loop pump 85 | ghp.set_attr(eta_s=0.75, design=['eta_s'], offdesign=['eta_s_char']) 86 | 87 | 88 | # %% connection parametrization 89 | 90 | # heat pump system 91 | cc_cd.set_attr(fluid={'NH3': 1}) 92 | ev_cp.set_attr(Td_bp=3) 93 | 94 | # geothermal heat collector 95 | gh_in_ghp.set_attr(T=Tgeo + 1.5, p=1.5, fluid={'water': 1}) 96 | ev_gh_out.set_attr(T=Tgeo - 1.5, p=1.5) 97 | 98 | # heating system 99 | cd_hs_feed.set_attr(T=40, p=2, fluid={'water': 1}) 100 | hs_ret_hsp.set_attr(T=35, p=2) 101 | 102 | # starting values 103 | ev_cp.set_attr(p0=5) 104 | cc_cd.set_attr(p0=18) 105 | 106 | # %% create busses 107 | 108 | # characteristic function for motor efficiency 109 | x = np.array([0, 0.2, 0.4, 0.6, 0.8, 1, 1.2]) 110 | y = np.array([0, 0.86, 0.9, 0.93, 0.95, 0.96, 0.95]) 111 | 112 | # power bus 113 | char = CharLine(x=x, y=y) 114 | power = Bus('power input') 115 | power.add_comps( 116 | {'comp': cp, 'char': char, 'base': 'bus'}, 117 | {'comp': ghp, 'char': char, 'base': 'bus'}, 118 | {'comp': hsp, 'char': char, 'base': 'bus'} 119 | ) 120 | 121 | # consumer heat bus 122 | heat_cons = Bus('heating system') 123 | heat_cons.add_comps({'comp': hs_ret, 'base': 'bus'}, {'comp': hs_feed}) 124 | 125 | # geothermal heat bus 126 | heat_geo = Bus('geothermal heat') 127 | heat_geo.add_comps({'comp': gh_in, 'base': 'bus'}, {'comp': gh_out}) 128 | 129 | 130 | nw.add_busses(power, heat_cons, heat_geo) 131 | 132 | 133 | # %% key parameter 134 | 135 | cd.set_attr(Q=-4e3) 136 | 137 | # %% design calculation 138 | 139 | path = 'NH3.json' 140 | nw.solve('design') 141 | # alternatively use: 142 | # nw.solve('design', init_path = path) 143 | print("\n##### DESIGN CALCULATION #####\n") 144 | nw.print_results() 145 | nw.save(path) 146 | -------------------------------------------------------------------------------- /tutorial/heat_pump_exergy/R410A.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from tespy.components import Compressor 4 | from tespy.components import Condenser 5 | from tespy.components import CycleCloser 6 | from tespy.components import HeatExchanger 7 | from tespy.components import Sink 8 | from tespy.components import Source 9 | from tespy.components import Valve 10 | from tespy.components import Pump 11 | from tespy.connections import Connection 12 | from tespy.connections import Bus 13 | from tespy.networks import Network 14 | from tespy.tools.characteristics import CharLine 15 | from tespy.tools.characteristics import load_default_char as ldc 16 | import numpy as np 17 | 18 | # %% network 19 | pamb = 1.013 # ambient pressure 20 | Tamb = 2.8 # ambient temperature 21 | 22 | # mean geothermal temperature (mean value of ground feed and return flow) 23 | Tgeo = 9.5 24 | 25 | nw = Network(T_unit='C', p_unit='bar', h_unit='kJ / kg', m_unit='kg / s') 26 | 27 | # %% components 28 | 29 | cc = CycleCloser('cycle closer') 30 | 31 | # heat pump system 32 | cd = Condenser('condenser') 33 | va = Valve('valve') 34 | ev = HeatExchanger('evaporator') 35 | cp = Compressor('compressor') 36 | 37 | # geothermal heat collector 38 | gh_in = Source('ground heat feed flow') 39 | gh_out = Sink('ground heat return flow') 40 | ghp = Pump('ground heat loop pump') 41 | 42 | # heating system 43 | hs_feed = Sink('heating system feed flow') 44 | hs_ret = Source('heating system return flow') 45 | hsp = Pump('heating system pump') 46 | 47 | # %% connections 48 | 49 | # heat pump system 50 | cc_cd = Connection(cc, 'out1', cd, 'in1') 51 | cd_va = Connection(cd, 'out1', va, 'in1') 52 | va_ev = Connection(va, 'out1', ev, 'in2') 53 | ev_cp = Connection(ev, 'out2', cp, 'in1') 54 | cp_cc = Connection(cp, 'out1', cc, 'in1') 55 | nw.add_conns(cc_cd, cd_va, va_ev, ev_cp, cp_cc) 56 | 57 | # geothermal heat collector 58 | gh_in_ghp = Connection(gh_in, 'out1', ghp, 'in1') 59 | ghp_ev = Connection(ghp, 'out1', ev, 'in1') 60 | ev_gh_out = Connection(ev, 'out1', gh_out, 'in1') 61 | nw.add_conns(gh_in_ghp, ghp_ev, ev_gh_out) 62 | 63 | # heating system 64 | hs_ret_hsp = Connection(hs_ret, 'out1', hsp, 'in1') 65 | hsp_cd = Connection(hsp, 'out1', cd, 'in2') 66 | cd_hs_feed = Connection(cd, 'out2', hs_feed, 'in1') 67 | nw.add_conns(hs_ret_hsp, hsp_cd, cd_hs_feed) 68 | 69 | 70 | # %% component parametrization 71 | 72 | # condenser 73 | cd.set_attr(pr1=0.99, pr2=0.99, ttd_u=5, design=['pr2', 'ttd_u'], 74 | offdesign=['zeta2', 'kA_char']) 75 | # evaporator 76 | kA_char1 = ldc('heat exchanger', 'kA_char1', 'DEFAULT', CharLine) 77 | kA_char2 = ldc('heat exchanger', 'kA_char2', 'EVAPORATING FLUID', CharLine) 78 | ev.set_attr(pr1=0.99, pr2=0.99, ttd_l=5, 79 | kA_char1=kA_char1, kA_char2=kA_char2, 80 | design=['pr1', 'ttd_l'], offdesign=['zeta1', 'kA_char']) 81 | # compressor 82 | cp.set_attr(eta_s=0.8, design=['eta_s'], offdesign=['eta_s_char']) 83 | # heating system pump 84 | hsp.set_attr(eta_s=0.75, design=['eta_s'], offdesign=['eta_s_char']) 85 | # ground heat loop pump 86 | ghp.set_attr(eta_s=0.75, design=['eta_s'], offdesign=['eta_s_char']) 87 | 88 | 89 | # %% connection parametrization 90 | 91 | # heat pump system 92 | cc_cd.set_attr(fluid={'R410A': 1}) 93 | ev_cp.set_attr(Td_bp=3) 94 | 95 | # geothermal heat collector 96 | gh_in_ghp.set_attr(T=Tgeo + 1.5, p=1.5, fluid={'water': 1}) 97 | ev_gh_out.set_attr(T=Tgeo - 1.5, p=1.5) 98 | 99 | # heating system 100 | cd_hs_feed.set_attr(T=40, p=2, fluid={'water': 1}) 101 | hs_ret_hsp.set_attr(T=35, p=2) 102 | 103 | # starting values 104 | va_ev.set_attr(h0=275) 105 | cc_cd.set_attr(p0=18) 106 | 107 | # %% create busses 108 | 109 | # characteristic function for motor efficiency 110 | x = np.array([0, 0.2, 0.4, 0.6, 0.8, 1, 1.2]) 111 | y = np.array([0, 0.86, 0.9, 0.93, 0.95, 0.96, 0.95]) 112 | 113 | # power bus 114 | char = CharLine(x=x, y=y) 115 | power = Bus('power input') 116 | power.add_comps( 117 | {'comp': cp, 'char': char, 'base': 'bus'}, 118 | {'comp': ghp, 'char': char, 'base': 'bus'}, 119 | {'comp': hsp, 'char': char, 'base': 'bus'} 120 | ) 121 | 122 | # consumer heat bus 123 | heat_cons = Bus('heating system') 124 | heat_cons.add_comps({'comp': hs_ret, 'base': 'bus'}, {'comp': hs_feed}) 125 | 126 | # geothermal heat bus 127 | heat_geo = Bus('geothermal heat') 128 | heat_geo.add_comps({'comp': gh_in, 'base': 'bus'}, {'comp': gh_out}) 129 | 130 | 131 | nw.add_busses(power, heat_cons, heat_geo) 132 | 133 | # %% key parameter 134 | 135 | cd.set_attr(Q=-4e3) 136 | 137 | # %% design calculation 138 | 139 | path = 'R410A.json' 140 | nw.solve('design') 141 | # alternatively use: 142 | # nw.solve('design', init_path=path) 143 | print("\n##### DESIGN CALCULATION #####\n") 144 | nw.print_results() 145 | nw.save(path) 146 | --------------------------------------------------------------------------------