diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 71bafbf41..c6b46c38b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,14 +38,14 @@ jobs: # Upgrade pip python3 -m pip install --upgrade pip # Install twine - python3 -m pip install setuptools wheel twine + python3 -m pip install build setuptools wheel twine # Upload to TestPyPI - name: Build and Upload to TestPyPI if: ${{ inputs.upload_server == 'testpypi'}} run: | - python3 setup.py sdist --formats=zip - twine check dist/* --strict + python3 -m build + python3 -m twine check dist/* --strict python3 -m twine upload dist/* env: TWINE_USERNAME: __token__ @@ -56,8 +56,8 @@ jobs: - name: Build and Upload to PyPI if: ${{ inputs.upload_server == 'pypi' }} run: | - python3 setup.py sdist --formats=zip - twine check dist/* --strict + python3 -m build + python3 -m twine check dist/* --strict python3 -m twine upload dist/* env: TWINE_USERNAME: __token__ @@ -70,12 +70,11 @@ jobs: time: 300s build: - runs-on: ${{ matrix.os }} needs: upload strategy: matrix: - python-version: ['3.8', '3.9', '3.10', '3.11'] + python-version: ['3.9', '3.10', '3.11', '3.12'] os: [ ubuntu-latest, windows-latest ] steps: - name: Set up Python ${{ matrix.python-version }} diff --git a/.github/workflows/run_tests_develop.yml b/.github/workflows/run_tests_develop.yml index ac4f46a1a..e3a7b98d8 100644 --- a/.github/workflows/run_tests_develop.yml +++ b/.github/workflows/run_tests_develop.yml @@ -1,8 +1,10 @@ # This workflow will install Python dependencies, run tests and lint with a variety of Python versions -# A coverage report will be created for the Python 3.8 version +# A coverage report will be created for the Python 3.9 version # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions -# pandapipes-develop branch is designed to work with pandapower-develop branch +# pandapipes-develop branch is designed to work with pandapower-master branch, but checks the ability to +# work with pandapower-develop branch (relying tests, usually not required for merges) in order to avoid +# problems in future releases name: ppipes_dev @@ -17,7 +19,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ['3.8', '3.9', '3.10', '3.11'] + python-version: ['3.9', '3.10', '3.11', '3.12'] os: [ ubuntu-latest, windows-latest ] steps: - uses: actions/checkout@v4 @@ -28,30 +30,63 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install pytest pytest-split - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - python -m pip install git+https://github.com/e2nIEE/pandapower@develop#egg=pandapower python -m pip install .["all"] shell: bash - name: List all installed packages run: | python -m pip list - name: Test with pytest - if: ${{ matrix.python-version != '3.9' }} + if: ${{ matrix.python-version != '3.11' }} run: | python -m pytest - - name: Test with numba + - name: Test without numba + if: ${{ matrix.python-version == '3.11' }} + run: | + python -m pip uninstall numba -y + python -m pytest -n=auto + - name: Test with pytest and Codecov + if: ${{ matrix.python-version == '3.11' }} + run: | + python -m pip install pytest-cov + python -m pytest --cov=./ --cov-report=xml + - name: Upload coverage to Codecov if: ${{ matrix.python-version == '3.11' }} + uses: codecov/codecov-action@v1 + with: + verbose: true + + relying: + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: ['3.9', '3.10', '3.11', '3.12'] + os: [ ubuntu-latest, windows-latest ] + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install git+https://github.com/e2nIEE/pandapower@develop#egg=pandapower + python -m pip install .["all"] + shell: bash + - name: List all installed packages + run: | + python -m pip list + - name: Test with pytest + if: ${{ matrix.python-version != '3.11' }} run: | - python -m pip install numba python -m pytest - name: Test with pytest and Codecov - if: ${{ matrix.python-version == '3.9' }} + if: ${{ matrix.python-version == '3.11' }} run: | python -m pip install pytest-cov python -m pytest -n=auto --cov=./ --cov-report=xml - name: Upload coverage to Codecov - if: ${{ matrix.python-version == '3.9' }} + if: ${{ matrix.python-version == '3.11' }} uses: codecov/codecov-action@v4 with: verbose: true @@ -65,12 +100,17 @@ jobs: 'pandapipes/networks/network_files/**' '**.yml' '**.rst' + - name: Test without numba + if: ${{ matrix.python-version == '3.11' }} + run: | + python -m pip uninstall numba -y + python -m pytest -n=auto linting: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ['3.10'] + python-version: ['3.11'] os: [ ubuntu-latest, windows-latest ] steps: - uses: actions/checkout@v4 @@ -82,8 +122,6 @@ jobs: run: | python -m pip install --upgrade pip python -m pip install flake8 - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - python -m pip install git+https://github.com/e2nIEE/pandapower@develop#egg=pandapower python -m pip install .["all"] shell: bash - name: List all installed packages @@ -102,7 +140,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ['3.8', '3.9', '3.10', '3.11'] + python-version: ['3.9', '3.10', '3.11', '3.12'] os: [ ubuntu-latest, windows-latest ] steps: - uses: actions/checkout@v4 @@ -113,10 +151,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install pytest==8.0.2 nbmake pytest-xdist pytest-split - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - python -m pip install git+https://github.com/e2nIEE/pandapower@develop#egg=pandapower - python -m pip install . + python -m pip install .["all"] shell: bash - name: List all installed packages run: | @@ -124,17 +159,17 @@ jobs: - name: Test with pytest run: | python -m pytest --nbmake -n=auto "./tutorials" - - name: Test with numba + - name: Test without numba if: ${{ matrix.python-version == '3.11' }} run: | - python -m pip install numba + python -m pip uninstall numba -y python -m pytest --nbmake -n=auto "./tutorials" docs_check: runs-on: ubuntu-latest strategy: matrix: - python-version: [ '3.10' ] + python-version: [ '3.11' ] steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} @@ -144,10 +179,7 @@ jobs: - name: Check docs for Python ${{ matrix.python-version }} uses: e2nIEE/sphinx-action@master with: - pre-build-command: "apt-get update -y && apt-get install -y git; - git --version; - python -m pip install --upgrade pip; - python -m pip install git+https://github.com/e2nIEE/pandapower@develop#egg=pandapower; - python -m pip install .['all']" + pre-build-command: "python -m pip install --upgrade pip; + python -m pip install .[docs]" build-command: "sphinx-build -b html source _build -W" docs-folder: "doc/" diff --git a/.github/workflows/run_tests_master.yml b/.github/workflows/run_tests_master.yml index 4dd3c27e6..339bfc688 100644 --- a/.github/workflows/run_tests_master.yml +++ b/.github/workflows/run_tests_master.yml @@ -16,7 +16,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ['3.8', '3.9', '3.10', '3.11'] + python-version: ['3.9', '3.10', '3.11', '3.12'] os: [ ubuntu-latest, windows-latest ] steps: - uses: actions/checkout@v4 @@ -27,37 +27,29 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install pytest pytest-split - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - python -m pip install pandapower; python -m pip install .["all"] shell: bash - name: List all installed packages run: | python -m pip list - name: Test with pytest - if: ${{ matrix.python-version != '3.9' }} + if: ${{ matrix.python-version != '3.11' }} run: | python -m pytest - - name: Test with numba - if: ${{ matrix.python-version == '3.11' }} - run: | - python -m pip install numba - python -m pytest -n=auto - name: Test with pytest, Codecov and Coverage - if: ${{ matrix.python-version == '3.9' }} + if: ${{ matrix.python-version == '3.11' }} run: | python -m pip install pytest-cov python -m pytest --nbmake -n=auto --cov=./ --cov-report=xml cp ./coverage.xml ./codecov_coverage.xml - name: Upload coverage to Codacy - if: ${{ matrix.python-version == '3.9' && matrix.os == 'ubuntu-latest'}} + if: ${{ matrix.python-version == '3.11' && matrix.os == 'ubuntu-latest'}} env: CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }} run: | bash <(curl -Ls https://coverage.codacy.com/get.sh) report -r coverage.xml - name: Upload coverage to Codecov - if: ${{ matrix.python-version == '3.9' }} + if: ${{ matrix.python-version == '3.11' }} uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} @@ -71,13 +63,48 @@ jobs: 'pandapipes/networks/network_files/**' '**.yml' '**.rst' + - name: Test without numba + if: ${{ matrix.python-version == '3.11' }} + run: | + python -m pip uninstall numba -y + python -m pytest -n=auto + + relying: + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: ['3.9', '3.10', '3.11', '3.12'] + os: [ ubuntu-latest, windows-latest ] + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install .["all"] + shell: bash + - name: List all installed packages + run: | + python -m pip list + - name: Test with pytest + # if: ${{ matrix.python-version != '3.11' }} + run: | + python -m pytest -n=auto + - name: Test without numba + if: ${{ matrix.python-version == '3.11' }} + run: | + python -m pip uninstall numba -y + python -m pytest -n=auto tutorial_tests: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ['3.8', '3.9', '3.10', '3.11'] + python-version: ['3.9', '3.10', '3.11', '3.12'] os: [ ubuntu-latest, windows-latest ] steps: - uses: actions/checkout@v4 @@ -88,9 +115,6 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install pytest==8.0.2 nbmake pytest-xdist pytest-split - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - python -m pip install pandapower python -m pip install .["all"] shell: bash - name: List all installed packages @@ -99,10 +123,10 @@ jobs: - name: Test with pytest run: | python -m pytest --nbmake -n=auto "./tutorials" - - name: Test with numba + - name: Test without numba if: ${{ matrix.python-version == '3.11' }} run: | - python -m pip install numba + python -m pip uninstall numba -y python -m pytest --nbmake -n=auto "./tutorials" @@ -110,7 +134,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [ '3.10' ] + python-version: [ '3.11' ] steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} @@ -120,10 +144,7 @@ jobs: - name: Check docs for Python ${{ matrix.python-version }} uses: e2nIEE/sphinx-action@master with: - pre-build-command: "apt-get update -y && apt-get install -y git; - git --version; - python -m pip install --upgrade pip; - python -m pip install pandapower; - python -m pip install .['all']" + pre-build-command: "python -m pip install --upgrade pip; + python -m pip install .[docs]" build-command: "sphinx-build -b html source _build -W" docs-folder: "doc/" diff --git a/.readthedocs.yml b/.readthedocs.yml index b6911a40a..202694c89 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -7,4 +7,6 @@ build: python: install: + - method: pip + path: . - requirements: doc/requirements.txt \ No newline at end of file diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3e79f9eb2..49fc6afcc 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,35 @@ Change Log ============= +[0.11.0] - 2024-11-07 +------------------------------- +- [ADDED] heat_consumer plotting +- [ADDED] variable "u_w_per_m2k" to std_type pipe +- [ADDED] standard district heating pipe types +- [ADDED] support for Python 3.12 +- [ADDED] t_outlet_k to result tables of branch components +- [ADDED] relying tests, to check the ability to work with pandapower develop +- [ADDED] bidirectional calculation mode for heat calculations +- [CHANGED] heat_consumer to enable temperature control +- [CHANGED] switched from setup.py to pyproject.toml +- [CHANGED] variable "alpha_w_per_m2k" to "u_w_per_m2k" +- [CHANGED] option "all" for pipeflow heat calculations to "sequential", the new option is "bidirectional" +- [CHANGED] volume flow in result tables instead of normalized volume flow for non gas fluids +- [CHANGED] introduction of slack mass flow into nodes as solved variable +- [CHANGED] circulation pumps are now branches and thus cannot generate or consume mass +- [FIXED] Pressure plot not working for circ pump +- [FIXED] volume flow rate for incompressible fluids based on real density, thus in this case results are renamed from "vdot_norm_m3_per_s" to "vdot_m3_per_s" +- [FIXED] some imports from pandapower +- [FIXED] NAN to nan because of numpy changes +- [FIXED] if velocity in a branch is negative to get corrected nodes from the branch pit +- [FIXED] plot pressure profile not working for circulation pump sources +- [FIXED] Infeed switches are considered correctly +- [FIXED] Heat consumers with qext_w = 0 and temperature control ignore temperature set points +- [FIXED] alpha also applied to mdot +- [REMOVED] support for Python 3.8 due to EOL + + + [0.10.0] - 2024-04-09 ------------------------------- diff --git a/doc/requirements.txt b/doc/requirements.txt index 778fafa16..88d2ee075 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -1,4 +1,5 @@ sphinx>=5.3.0 sphinx_rtd_theme>=1.1.1 numpydoc>=1.5.0 -sphinxcontrib.bibtex>=2.5.0 \ No newline at end of file +sphinxcontrib.bibtex>=2.5.0 +sphinx-pyproject \ No newline at end of file diff --git a/doc/source/components/sink/sink_par.csv b/doc/source/components/sink/sink_par.csv index 1326571fa..541d982c5 100644 --- a/doc/source/components/sink/sink_par.csv +++ b/doc/source/components/sink/sink_par.csv @@ -1,7 +1,7 @@ **Parameter**;**Datatype**;**Value Range**;**Explanation** name;string;;Name of the sink junction;integer;;Index of connected junction -mdot_kg_per_s;float;:math:`\leq 0`;Drawn mass flow [kg/s] +mdot_kg_per_s;float;:math:`\geq 0`;Drawn mass flow [kg/s] scaling *;float;:math:`\geq 0`;Scaling factor to adapt the drawn mass flow in_service*;boolean;True / False;Specifies if the sink is in service. type;string;;Component type diff --git a/doc/source/conf.py b/doc/source/conf.py index 31072d076..350b8c5cc 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -12,17 +12,22 @@ # import os import sys +from sphinx_pyproject import SphinxConfig sys.path.append(os.path.abspath('..')) sys.path.append(os.path.abspath('../..')) sys.path.append(os.path.abspath('../../..')) sys.path.append(os.path.abspath('../../../pandapower')) - +sys.path.append(os.path.abspath('../../src')) master_doc = 'index' + +# load pyproject.toml configuration +config = SphinxConfig("../../pyproject.toml") + # -- Project information ----------------------------------------------------- -project = 'pandapipes' +project = config.name copyright = '2020-2024 by Fraunhofer Institute for Energy Economics \ and Energy System Technology (IEE), Kassel, and University of Kassel. All rights reserved.' @@ -47,9 +52,9 @@ # built documents. # # The short X.Y version. -version = "0.10" +version = config.version.rsplit(".", 1)[0] # The full version, including alpha/beta/rc tags. -release = "0.10.0" +release = config.version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/source/pipeflow/calculation_modes.rst b/doc/source/pipeflow/calculation_modes.rst index 6a8b38bbe..b94dc4a81 100644 --- a/doc/source/pipeflow/calculation_modes.rst +++ b/doc/source/pipeflow/calculation_modes.rst @@ -34,7 +34,7 @@ variations are very small. The user has to decide if these assumptions are suitable for his purposes. In future, pandapipes will be extended in order to make sure that calculated temperatures also effect hydraulic fluid properties. To activate temperature calculation, the pipe flow option "mode" has to be set -to "all" or "heat". If heat is chosen, the user has to provide a solution vector of the hydraulics calculation manually. +to "sequential", "bidirectional" or "heat". If heat is chosen, the user has to provide a solution vector of the hydraulics calculation manually. Hydraulic calculations for incompressible media @@ -92,8 +92,8 @@ In gas flows, the velocity is typically not constant along a pipeline. For this tables for pipes show more entries in comparison with the result tables for incompressible media. -Temperature calculations (pipeflow option: mode = "all" or mode = "heat") -========================================================================= +Temperature calculations (pipeflow option: mode = "sequential", mode = "bidrectional" or mode = "heat") +======================================================================================================= Important parameters of the network main components (junctions and pipes) needed for the calculation are listed in the following table. The :ref:`component section ` of this manual contains diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..0e181cb54 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,68 @@ +[build-system] +requires = ["build", "wheel", "setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "pandapipes" +version = "0.11.0" # File format version '__format_version__' is tracked in __init__.py +authors=[ + { name = "Simon Ruben Drauz-Mauel", email = "simon.ruben.drauz-mauel@iee.fraunhofer.de" }, + { name = "Daniel Lohmeier", email = "daniel.lohmeier@retoflow.de" }, + { name = "Jolando Marius Kisse", email = "jolando.kisse@uni-kassel.de" } +] +description = "A pipeflow calculation tool that complements pandapower in the simulation of multi energy grids" +readme = "README.rst" +license = { file = "LICENSE" } +requires-python = ">=3.9" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Console", + "Intended Audience :: Developers", + "Intended Audience :: Education", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: BSD License", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + # Add the specific Python versions supported here, e.g.: + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12" +] +dependencies = [ + "pandapower ~= 2.14.11", + "matplotlib", + "shapely", +] +keywords = [ + "network", "analysis", "optimization", "automation", "grid", "energy", "engineering", + "simulation", "pipeflow", "pandapipes", "gas" +] + +[project.urls] +Homepage = "https://www.pandapipes.org" +Documentation = "https://pandapipes.readthedocs.io" +Source = "https://github.com/e2nIEE/pandapipes" +Repository = "https://github.com/e2nIEE/pandapipes.git" +Issues = "https://github.com/e2nIEE/pandapipes/issues" +Download = "https://pypi.org/project/pandapipes/#files" +Changelog = "https://github.com/e2nIEE/pandapipes/blob/develop/CHANGELOG.rst" + +[project.optional-dependencies] +docs = ["numpydoc", "sphinx", "sphinx_rtd_theme", "sphinxcontrib.bibtex", "sphinx-pyproject"] +plotting = ["plotly", "igraph"] +test = [ + "pytest", "pytest-xdist", "pytest-split", "nbmake", "numba", + "setuptools; python_version >= '3.12'" +] +all = [ + "numpydoc", "sphinx", "sphinx_rtd_theme", "sphinxcontrib.bibtex", + "plotly", "igraph", "pytest", "pytest-xdist", "pytest-split", "nbmake", "numba", + "setuptools; python_version >= '3.12'" +] + +[tool.setuptools.packages.find] +where = ["src"] +include = ["pandapipes*"] diff --git a/setup.py b/setup.py index b29abc6eb..c44eaf35e 100644 --- a/setup.py +++ b/setup.py @@ -1,57 +1,9 @@ +# -*- coding: utf-8 -*- + # Copyright (c) 2020-2024 by Fraunhofer Institute for Energy Economics # and Energy System Technology (IEE), Kassel, and University of Kassel. All rights reserved. # Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. -import re - -from setuptools import find_namespace_packages from setuptools import setup -with open('README.rst', 'rb') as f: - install = f.read().decode('utf-8') - -with open('CHANGELOG.rst', 'rb') as f: - changelog = f.read().decode('utf-8') - -classifiers = [ - 'Development Status :: 4 - Beta', - 'Environment :: Console', - 'Intended Audience :: Developers', - 'Intended Audience :: Education', - 'Intended Audience :: Science/Research', - 'License :: OSI Approved :: BSD License', - 'Natural Language :: English', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3'] - -with open('.github/workflows/run_tests_master.yml', 'rb') as f: - lines = f.read().decode('utf-8') - versions = set(re.findall('3.[8-9]', lines)) | set(re.findall('3.1[0-9]', lines)) - for version in versions: - classifiers.append('Programming Language :: Python :: %s' % version) - -long_description = '\n\n'.join((install, changelog)) - -setup( - name='pandapipes', - version='0.10.0', - author='Simon Ruben Drauz-Mauel, Daniel Lohmeier, Jolando Marius Kisse', - author_email='simon.ruben.drauz-mauel@iee.fraunhofer.de, daniel.lohmeier@retoflow.de, ' - 'jolando.kisse@uni-kassel.de', - description='A pipeflow calculation tool that complements pandapower in the simulation of multi energy grids', - long_description=long_description, - long_description_content_type='text/x-rst', - url='http://www.pandapipes.org', - license='BSD', - install_requires=["pandapower>=2.14.6", "matplotlib", "shapely"], - extras_require={"docs": ["numpydoc", "sphinx", "sphinx_rtd_theme", "sphinxcontrib.bibtex"], - "plotting": ["plotly", "igraph"], - "test": ["pytest", "pytest-xdist", "nbmake"], - "all": ["numpydoc", "sphinx", "sphinx_rtd_theme", "sphinxcontrib.bibtex", - "plotly", "igraph", "pytest", "pytest-xdist", "nbmake"]}, - packages=find_namespace_packages(where='src'), - package_dir={"": "src"}, - include_package_data=True, - classifiers=classifiers -) +setup() diff --git a/src/pandapipes/__init__.py b/src/pandapipes/__init__.py index f8e6f2dec..6fa953b19 100644 --- a/src/pandapipes/__init__.py +++ b/src/pandapipes/__init__.py @@ -2,8 +2,10 @@ # and Energy System Technology (IEE), Kassel, and University of Kassel. All rights reserved. # Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. -__version__ = '0.10.0' -__format_version__ = '0.10.0' +import importlib.metadata + +__version__ = importlib.metadata.version("pandapipes") +__format_version__ = '0.11.0' import pandas as pd import os diff --git a/src/pandapipes/component_models/__init__.py b/src/pandapipes/component_models/__init__.py index 3437b0c3a..52d454806 100644 --- a/src/pandapipes/component_models/__init__.py +++ b/src/pandapipes/component_models/__init__.py @@ -16,3 +16,5 @@ from pandapipes.component_models.compressor_component import * from pandapipes.component_models.flow_control_component import * from pandapipes.component_models.mass_storage_component import * +from pandapipes.component_models.heat_consumer_component import * +from pandapipes.component_models.component_toolbox import * \ No newline at end of file diff --git a/src/pandapipes/component_models/abstract_models/branch_models.py b/src/pandapipes/component_models/abstract_models/branch_models.py index 8ebf80323..a486fabaa 100644 --- a/src/pandapipes/component_models/abstract_models/branch_models.py +++ b/src/pandapipes/component_models/abstract_models/branch_models.py @@ -5,8 +5,8 @@ import numpy as np from pandapipes.component_models.abstract_models.base_component import Component -from pandapipes.idx_branch import MDOTINIT, branch_cols -from pandapipes.pf.pipeflow_setup import get_table_number, get_lookup +from pandapipes.idx_branch import MDOTINIT, branch_cols, TEXT +from pandapipes.pf.pipeflow_setup import get_table_number, get_lookup, get_net_option try: import pandaplan.core.pplog as logging @@ -89,6 +89,7 @@ def create_pit_branch_entries(cls, net, branch_pit): to_nodes = junction_idx_lookup[net[cls.table_name()][tn_col].values] branch_component_pit[:, :] = np.array([branch_table_nr] + [0] * (branch_cols - 1)) branch_component_pit[:, MDOTINIT] = 0.1 + branch_component_pit[:, TEXT] = get_net_option(net, 'ambient_temperature') return branch_component_pit, node_pit, from_nodes, to_nodes @classmethod diff --git a/src/pandapipes/component_models/abstract_models/branch_w_internals_models.py b/src/pandapipes/component_models/abstract_models/branch_w_internals_models.py index de85aa611..19faae681 100644 --- a/src/pandapipes/component_models/abstract_models/branch_w_internals_models.py +++ b/src/pandapipes/component_models/abstract_models/branch_w_internals_models.py @@ -7,7 +7,7 @@ from pandapipes.component_models.abstract_models.branch_models import BranchComponent from pandapipes.component_models.component_toolbox import set_entry_check_repeat, vinterp, \ p_correction_height_air -from pandapipes.idx_branch import ACTIVE, FROM_NODE, FROM_NODE_T, TO_NODE, TO_NODE_T, TOUTINIT, ELEMENT_IDX, TOUTINIT +from pandapipes.idx_branch import ACTIVE, FROM_NODE, TO_NODE, ELEMENT_IDX, TOUTINIT from pandapipes.idx_node import (L, node_cols, TINIT as TINIT_NODE, HEIGHT, PINIT, PAMB, ACTIVE as ACTIVE_ND) from pandapipes.pf.pipeflow_setup import add_table_lookup, get_lookup, get_table_number @@ -207,9 +207,7 @@ def create_pit_branch_entries(cls, net, branch_pit): branch_w_internals_pit, ACTIVE, net[cls.table_name()][cls.active_identifier()].values, internal_pipe_number, has_internals) branch_w_internals_pit[:, FROM_NODE] = from_nodes - branch_w_internals_pit[:, FROM_NODE_T] = from_nodes branch_w_internals_pit[:, TO_NODE] = to_nodes - branch_w_internals_pit[:, TO_NODE_T] = to_nodes branch_w_internals_pit[:, TOUTINIT] = node_pit[to_nodes, TINIT_NODE] return branch_w_internals_pit, internal_pipe_number diff --git a/src/pandapipes/component_models/abstract_models/branch_wo_internals_models.py b/src/pandapipes/component_models/abstract_models/branch_wo_internals_models.py index 0ce5f8e57..9af9e0df3 100644 --- a/src/pandapipes/component_models/abstract_models/branch_wo_internals_models.py +++ b/src/pandapipes/component_models/abstract_models/branch_wo_internals_models.py @@ -4,7 +4,7 @@ from pandapipes.component_models.abstract_models.branch_models import BranchComponent -from pandapipes.idx_branch import FROM_NODE, FROM_NODE_T, TO_NODE, TO_NODE_T, TOUTINIT, ELEMENT_IDX, ACTIVE +from pandapipes.idx_branch import FROM_NODE, TO_NODE, TOUTINIT, ELEMENT_IDX, ACTIVE from pandapipes.idx_node import TINIT as TINIT_NODE from pandapipes.pf.pipeflow_setup import add_table_lookup @@ -80,9 +80,7 @@ def create_pit_branch_entries(cls, net, branch_pit): = super().create_pit_branch_entries(net, branch_pit) branch_wo_internals_pit[:, ELEMENT_IDX] = net[cls.table_name()].index.values branch_wo_internals_pit[:, FROM_NODE] = from_nodes - branch_wo_internals_pit[:, FROM_NODE_T] = from_nodes branch_wo_internals_pit[:, TO_NODE] = to_nodes - branch_wo_internals_pit[:, TO_NODE_T] = to_nodes branch_wo_internals_pit[:, TOUTINIT] = node_pit[to_nodes, TINIT_NODE] branch_wo_internals_pit[:, ACTIVE] = net[cls.table_name()][cls.active_identifier()].values return branch_wo_internals_pit diff --git a/src/pandapipes/component_models/abstract_models/branch_wzerolength_models.py b/src/pandapipes/component_models/abstract_models/branch_wzerolength_models.py index 31c013d45..ce6f0d71b 100644 --- a/src/pandapipes/component_models/abstract_models/branch_wzerolength_models.py +++ b/src/pandapipes/component_models/abstract_models/branch_wzerolength_models.py @@ -2,9 +2,11 @@ # and Energy System Technology (IEE), Kassel, and University of Kassel. All rights reserved. # Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. +import numpy as np + from pandapipes.component_models.abstract_models.branch_wo_internals_models import \ BranchWOInternalsComponent -from pandapipes.idx_branch import LENGTH, K, TEXT, ALPHA +from pandapipes.idx_branch import LENGTH, K, TEXT, ALPHA, D, AREA try: import pandaplan.core.pplog as logging @@ -60,6 +62,8 @@ def create_pit_branch_entries(cls, net, branch_pit): branch_wzerolength_pit[:, K] = 1000 branch_wzerolength_pit[:, TEXT] = 293.15 branch_wzerolength_pit[:, ALPHA] = 0 + branch_wzerolength_pit[:, D] = 0.1 + branch_wzerolength_pit[:, AREA] = branch_wzerolength_pit[:, D] ** 2 * np.pi / 4 return branch_wzerolength_pit @classmethod diff --git a/src/pandapipes/component_models/abstract_models/circulation_pump.py b/src/pandapipes/component_models/abstract_models/circulation_pump.py index c678b44a2..5f7bfb4e1 100644 --- a/src/pandapipes/component_models/abstract_models/circulation_pump.py +++ b/src/pandapipes/component_models/abstract_models/circulation_pump.py @@ -4,13 +4,12 @@ import numpy as np -from pandapipes.component_models.abstract_models.branch_wzerolength_models import \ - BranchWZeroLengthComponent -from pandapipes.component_models.component_toolbox import set_fixed_node_entries, \ - get_mass_flow_at_nodes -from pandapipes.idx_branch import D, AREA, ACTIVE -from pandapipes.idx_node import PINIT -from pandapipes.pf.pipeflow_setup import get_lookup +from pandapipes.component_models.abstract_models.branch_wzerolength_models import BranchWZeroLengthComponent +from pandapipes.component_models.component_toolbox import set_fixed_node_entries, standard_branch_wo_internals_result_lookup +from pandapipes.idx_branch import D, AREA, BRANCH_TYPE, CIRC, LOAD_VEC_BRANCHES_T, TO_NODE +from pandapipes.idx_node import MDOTSLACKINIT, VAR_MASS_SLACK, JAC_DERIV_MSL +from pandapipes.pf.pipeflow_setup import get_fluid +from pandapipes.pf.result_extraction import extract_branch_results_without_internals try: import pandaplan.core.pplog as logging @@ -34,13 +33,23 @@ def get_component_input(cls): def get_result_table(cls, net): """ + Gets the result table. + :param net: The pandapipes network :type net: pandapipesNet :return: (columns, all_float) - the column names and whether they are all float type. Only if False, returns columns as tuples also specifying the dtypes :rtype: (list, bool) """ - return ["mdot_flow_kg_per_s", "deltap_bar"], True + if get_fluid(net).is_gas: + output = ["v_from_m_per_s", "v_to_m_per_s", "v_mean_m_per_s", "p_from_bar", "p_to_bar", "t_from_k", + "t_to_k", "t_outlet_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_norm_m3_per_s", + "normfactor_from", "normfactor_to"] + else: + output = ["v_mean_m_per_s", "p_from_bar", "p_to_bar", "t_from_k", "t_to_k", "t_outlet_k", "mdot_from_kg_per_s", + "mdot_to_kg_per_s", "vdot_m3_per_s"] + output += ['deltat_k', 'qext_w'] + return output, True @classmethod def active_identifier(cls): @@ -72,10 +81,14 @@ def create_pit_node_entries(cls, net, node_pit): # TODO: there should be a warning, if any p_bar value is not given or any of the types does # not contain "p", as this should not be allowed for this component - press = circ_pump_tbl.p_flow_bar.values - set_fixed_node_entries(net, node_pit, junction, circ_pump_tbl.type.values, press, - circ_pump_tbl.t_flow_k.values, cls.get_connected_node_type()) - return circ_pump_tbl, press + types = circ_pump_tbl.type.values + p_values = circ_pump_tbl.p_flow_bar.values + t_values = circ_pump_tbl.t_flow_k.values + index_p = set_fixed_node_entries( + net, node_pit, junction, types, p_values, cls.get_connected_node_type(), 'p') + set_fixed_node_entries(net, node_pit, junction, types, t_values, cls.get_connected_node_type(), 't') + node_pit[index_p, JAC_DERIV_MSL] = -1. + return circ_pump_tbl, p_values @classmethod def create_pit_branch_entries(cls, net, branch_pit): @@ -90,7 +103,39 @@ def create_pit_branch_entries(cls, net, branch_pit): circ_pump_pit = super().create_pit_branch_entries(net, branch_pit) circ_pump_pit[:, D] = 0.1 circ_pump_pit[:, AREA] = circ_pump_pit[:, D] ** 2 * np.pi / 4 - circ_pump_pit[:, ACTIVE] = False + circ_pump_pit[:, BRANCH_TYPE] = CIRC + return circ_pump_pit + + @classmethod + def adaption_after_derivatives_hydraulic(cls, net, branch_pit, node_pit, idx_lookups, options): + """ + Function which creates pit branch entries with a specific table. + :param net: The pandapipes network + :type net: pandapipesNet + :param branch_pit: + :type branch_pit: + :return: No Output. + """ + f, t = idx_lookups[cls.table_name()] + circ_pump_pit = branch_pit[f:t, :] + tn = circ_pump_pit[:, TO_NODE].astype(np.int32) + mask = node_pit[tn, VAR_MASS_SLACK].astype(bool) + node_pit[tn[~mask], MDOTSLACKINIT] = 0 + return circ_pump_pit + + @classmethod + def adaption_after_derivatives_thermal(cls, net, branch_pit, node_pit, idx_lookups, options): + """ + Function which creates pit branch entries with a specific table. + :param net: The pandapipes network + :type net: pandapipesNet + :param branch_pit: + :type branch_pit: + :return: No Output. + """ + f, t = idx_lookups[cls.table_name()] + circ_pump_pit = branch_pit[f:t, :] + circ_pump_pit[:, LOAD_VEC_BRANCHES_T] = 0 @classmethod def extract_results(cls, net, options, branch_results, mode): @@ -107,34 +152,8 @@ def extract_results(cls, net, options, branch_results, mode): :type options: :return: No Output. """ - circ_pump_tbl = net[cls.table_name()] - - if len(circ_pump_tbl) == 0: - return - - res_table = net["res_" + cls.table_name()] - - branch_pit = net['_pit']['branch'] - node_pit = net["_pit"]["node"] - - junction_lookup = get_lookup(net, "node", "index")[ - cls.get_connected_node_type().table_name()] - fn_col, tn_col = cls.from_to_node_cols() - # get indices in internal structure for flow_junctions in circ_pump tables which are - # "active" - flow_junctions = circ_pump_tbl[tn_col].values - flow_nodes = junction_lookup[flow_junctions] - in_service = circ_pump_tbl.in_service.values - p_grids = np.isin(circ_pump_tbl.type.values, ["p", "pt"]) & in_service - sum_mass_flows, inverse_nodes, counts = get_mass_flow_at_nodes(net, node_pit, branch_pit, - flow_nodes[p_grids], cls) - - # positive results mean that the circ_pump feeds in, negative means that the ext grid - # extracts (like a load) - res_table["mdot_flow_kg_per_s"].values[p_grids] = - (sum_mass_flows / counts)[inverse_nodes] - return_junctions = circ_pump_tbl[fn_col].values - return_nodes = junction_lookup[return_junctions] + required_results_hyd, required_results_ht = standard_branch_wo_internals_result_lookup(net) - deltap_bar = node_pit[flow_nodes, PINIT] - node_pit[return_nodes, PINIT] - res_table["deltap_bar"].values[in_service] = deltap_bar[in_service] + extract_branch_results_without_internals(net, branch_results, required_results_hyd, required_results_ht, + cls.table_name(), mode) diff --git a/src/pandapipes/component_models/circulation_pump_mass_component.py b/src/pandapipes/component_models/circulation_pump_mass_component.py index 39cdb217b..64e3f8728 100644 --- a/src/pandapipes/component_models/circulation_pump_mass_component.py +++ b/src/pandapipes/component_models/circulation_pump_mass_component.py @@ -2,15 +2,12 @@ # and Energy System Technology (IEE), Kassel, and University of Kassel. All rights reserved. # Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. -import numpy as np from numpy import dtype -from pandapipes.component_models.junction_component import Junction from pandapipes.component_models.abstract_models.circulation_pump import CirculationPump -from pandapipes.idx_node import LOAD -from pandapipes.pf.internals_toolbox import _sum_by_group -from pandapipes.pf.pipeflow_setup import get_lookup -from pandapipes.pf.pipeflow_setup import get_net_option +from pandapipes.component_models.junction_component import Junction +from pandapipes.idx_branch import JAC_DERIV_DP, JAC_DERIV_DP1, JAC_DERIV_DM, MDOTINIT, \ + LOAD_VEC_BRANCHES try: import pandaplan.core.pplog as logging @@ -51,24 +48,17 @@ def active_identifier(cls): return "in_service" @classmethod - def create_pit_node_entries(cls, net, node_pit): - """ - Function which creates pit node entries. + def create_pit_branch_entries(cls, net, branch_pit): + circ_pump_pit = super().create_pit_branch_entries(net, branch_pit) + circ_pump_pit[:, MDOTINIT] = net[cls.table_name()].mdot_flow_kg_per_s.values - :param net: The pandapipes network - :type net: pandapipesNet - :param node_pit: - :type node_pit: - :return: No Output. - """ - circ_pump, _ = super().create_pit_node_entries(net, node_pit) - - mf = np.nan_to_num(circ_pump.mdot_flow_kg_per_s.values) - mass_flow_loads = mf * circ_pump.in_service.values - juncts, loads_sum = _sum_by_group(get_net_option(net, "use_numba"), - circ_pump.return_junction.values, mass_flow_loads) - junction_idx_lookups = get_lookup(net, "node", "index")[ - cls.get_connected_node_type().table_name()] - index = junction_idx_lookups[juncts] - node_pit[index, LOAD] += loads_sum + @classmethod + def adaption_after_derivatives_hydraulic(cls, net, branch_pit, node_pit, idx_lookups, options): + # set all pressure derivatives to 0 and velocity to 1; load vector must be 0, as no change + # of velocity is allowed during the pipeflow iteration + circ_pump_pit = super().adaption_after_derivatives_hydraulic(net, branch_pit, node_pit, idx_lookups, options) + circ_pump_pit[:, JAC_DERIV_DP] = 0 + circ_pump_pit[:, JAC_DERIV_DP1] = 0 + circ_pump_pit[:, JAC_DERIV_DM] = 1 + circ_pump_pit[:, LOAD_VEC_BRANCHES] = 0 diff --git a/src/pandapipes/component_models/circulation_pump_pressure_component.py b/src/pandapipes/component_models/circulation_pump_pressure_component.py index fb7ff2af3..9e77a5491 100644 --- a/src/pandapipes/component_models/circulation_pump_pressure_component.py +++ b/src/pandapipes/component_models/circulation_pump_pressure_component.py @@ -5,8 +5,8 @@ from numpy import dtype from pandapipes.component_models.abstract_models.circulation_pump import CirculationPump -from pandapipes.component_models.component_toolbox import set_fixed_node_entries from pandapipes.component_models.junction_component import Junction +from pandapipes.idx_branch import JAC_DERIV_DP, JAC_DERIV_DP1, PL try: import pandaplan.core.pplog as logging @@ -29,14 +29,8 @@ def get_component_input(cls): :return: :rtype: """ - return [("name", dtype(object)), - ("return_junction", "u4"), - ("flow_junction", "u4"), - ("p_flow_bar", "f8"), - ("t_flow_k", "f8"), - ("plift_bar", "f8"), - ("in_service", 'bool'), - ("type", dtype(object))] + return [("name", dtype(object)), ("return_junction", "u4"), ("flow_junction", "u4"), ("p_flow_bar", "f8"), + ("t_flow_k", "f8"), ("plift_bar", "f8"), ("in_service", 'bool'), ("type", dtype(object))] @classmethod def active_identifier(cls): @@ -47,19 +41,23 @@ def get_connected_node_type(cls): return Junction @classmethod - def create_pit_node_entries(cls, net, node_pit): + def create_pit_branch_entries(cls, net, branch_pit): """ - Function which creates pit node entries. - + Function which creates pit branch entries with a specific table. :param net: The pandapipes network :type net: pandapipesNet - :param node_pit: - :type node_pit: + :param branch_pit: + :type branch_pit: :return: No Output. """ - circ_pump, press = super().create_pit_node_entries(net, node_pit) + circ_pump_pit = super().create_pit_branch_entries(net, branch_pit) + circ_pump_pit[:, PL] = net[cls.table_name()]['plift_bar'].values + return circ_pump_pit - junction = circ_pump[cls.from_to_node_cols()[0]].values - p_in = press - circ_pump.plift_bar.values - set_fixed_node_entries(net, node_pit, junction, circ_pump.type.values, p_in, None, - cls.get_connected_node_type(), "p") + @classmethod + def adaption_after_derivatives_hydraulic(cls, net, branch_pit, node_pit, idx_lookups, options): + # set all pressure derivatives to 0 and velocity to 1; load vector must be 0, as no change + # of velocity is allowed during the pipeflow iteration + circ_pump_pit = super().adaption_after_derivatives_hydraulic(net, branch_pit, node_pit, idx_lookups, options) + circ_pump_pit[:, JAC_DERIV_DP] = 1 + circ_pump_pit[:, JAC_DERIV_DP1] = -1 diff --git a/src/pandapipes/component_models/component_toolbox.py b/src/pandapipes/component_models/component_toolbox.py index 840929bc4..e4cbf92ed 100644 --- a/src/pandapipes/component_models/component_toolbox.py +++ b/src/pandapipes/component_models/component_toolbox.py @@ -8,11 +8,11 @@ from pandapipes import get_fluid from pandapipes.constants import NORMAL_PRESSURE, TEMP_GRADIENT_KPM, AVG_TEMPERATURE_K, \ HEIGHT_EXPONENT -from pandapipes.idx_branch import LOAD_VEC_NODES, FROM_NODE, TO_NODE -from pandapipes.idx_node import EXT_GRID_OCCURENCE, EXT_GRID_OCCURENCE_T -from pandapipes.idx_node import PINIT, NODE_TYPE, P, TINIT, NODE_TYPE_T, T, LOAD -from pandapipes.pf.internals_toolbox import _sum_by_group +from pandapipes.idx_branch import LOAD_VEC_NODES_FROM, LOAD_VEC_NODES_TO, FROM_NODE, TO_NODE +from pandapipes.idx_node import (EXT_GRID_OCCURENCE, EXT_GRID_OCCURENCE_T, + PINIT, NODE_TYPE, P, TINIT, NODE_TYPE_T, T, LOAD) from pandapipes.pf.pipeflow_setup import get_net_option, get_lookup +from pandapipes.pf.internals_toolbox import _sum_by_group def p_correction_height_air(height): @@ -84,11 +84,11 @@ def init_results_element(net, element, output, all_float): """ res_element = "res_" + element if all_float: - net[res_element] = pd.DataFrame(np.NAN, columns=output, index=net[element].index, + net[res_element] = pd.DataFrame(np.nan, columns=output, index=net[element].index, dtype=np.float64) else: net[res_element] = pd.DataFrame(np.zeros(0, dtype=output), index=[]) - net[res_element] = pd.DataFrame(np.NaN, index=net[element].index, + net[res_element] = pd.DataFrame(np.nan, index=net[element].index, columns=net[res_element].columns) @@ -136,29 +136,36 @@ def set_entry_check_repeat(pit, column, entry, repeat_number, repeated=True): pit[:, column] = entry -def set_fixed_node_entries(net, node_pit, junctions, eg_types, p_values, t_values, node_comp, - mode="all"): +def set_fixed_node_entries(net, node_pit, junctions, types, values, node_comp, mode): + if not len(junctions): + return [], [] + junction_idx_lookups = get_lookup(net, "node", "index")[node_comp.table_name()] - for eg_type in ("p", "t"): - if eg_type not in mode and mode != "all": - continue - if eg_type == "p": - val_col, type_col, eg_count_col, typ, valid_types, values = \ - PINIT, NODE_TYPE, EXT_GRID_OCCURENCE, P, ["p", "pt"], p_values - else: - val_col, type_col, eg_count_col, typ, valid_types, values = \ - TINIT, NODE_TYPE_T, EXT_GRID_OCCURENCE_T, T, ["t", "pt"], t_values - mask = np.isin(eg_types, valid_types) - if not np.any(mask): - continue - use_numba = get_net_option(net, "use_numba") - juncts, press_sum, number = _sum_by_group(use_numba, junctions[mask], values[mask], - np.ones_like(values[mask], dtype=np.int32)) - index = junction_idx_lookups[juncts] - node_pit[index, val_col] = (node_pit[index, val_col] * node_pit[index, eg_count_col] - + press_sum) / (number + node_pit[index, eg_count_col]) - node_pit[index, type_col] = typ - node_pit[index, eg_count_col] += number + use_numba = get_net_option(net, "use_numba") + + if mode == "p": + val_col, type_col, count_col, typ, valid_types, values = \ + PINIT, NODE_TYPE, EXT_GRID_OCCURENCE, P, ["p", "pt"], values + elif mode == "t": + val_col, type_col, count_col, typ, valid_types, values = \ + TINIT, NODE_TYPE_T, EXT_GRID_OCCURENCE_T, T, ["t", "pt"], values + else: + raise UserWarning(r'The mode %s is not supported. Choose either mode "p" or "t"' % mode) + + mask = np.isin(types, valid_types) + + juncts, val_sum, number = _sum_by_group(use_numba, junctions[mask], values[mask], + np.ones_like(values[mask], dtype=np.int32)) + + index = junction_idx_lookups[juncts] + + node_pit[index, val_col] = (node_pit[index, val_col] * node_pit[index, count_col] + val_sum) / \ + (number + node_pit[index, count_col]) + + node_pit[index, count_col] += number + node_pit[index, type_col] = typ + + return index def get_mass_flow_at_nodes(net, node_pit, branch_pit, eg_nodes, comp): @@ -167,8 +174,8 @@ def get_mass_flow_at_nodes(net, node_pit, branch_pit, eg_nodes, comp): eg_to_branches = np.isin(branch_pit[:, TO_NODE], node_uni) from_nodes = branch_pit[eg_from_branches, FROM_NODE] to_nodes = branch_pit[eg_to_branches, TO_NODE] - mass_flow_from = branch_pit[eg_from_branches, LOAD_VEC_NODES] - mass_flow_to = branch_pit[eg_to_branches, LOAD_VEC_NODES] + mass_flow_from = branch_pit[eg_from_branches, LOAD_VEC_NODES_FROM] + mass_flow_to = branch_pit[eg_to_branches, LOAD_VEC_NODES_TO] loads = node_pit[node_uni, LOAD] all_index_nodes = np.concatenate([from_nodes, to_nodes, node_uni]) all_mass_flows = np.concatenate([-mass_flow_from, mass_flow_to, -loads]) @@ -183,24 +190,22 @@ def get_mass_flow_at_nodes(net, node_pit, branch_pit, eg_nodes, comp): def standard_branch_wo_internals_result_lookup(net): required_results_hyd = [ ("p_from_bar", "p_from"), ("p_to_bar", "p_to"), ("mdot_to_kg_per_s", "mf_to"), - ("mdot_from_kg_per_s", "mf_from"), ("vdot_norm_m3_per_s", "vf"), ("lambda", "lambda"), - ("reynolds", "reynolds") + ("mdot_from_kg_per_s", "mf_from") ] - required_results_ht = [("t_from_k", "temp_from"), ("t_to_k", "temp_to")] + required_results_ht = [("t_from_k", "temp_from"), ("t_to_k", "temp_to"), ("t_outlet_k", "t_outlet")] if get_fluid(net).is_gas: required_results_hyd.extend([ - ("v_from_m_per_s", "v_gas_from"), ("v_to_m_per_s", "v_gas_to"), - ("v_mean_m_per_s", "v_gas_mean"), ("normfactor_from", "normfactor_from"), - ("normfactor_to", "normfactor_to") + ("normfactor_from", "normfactor_from"), + ("normfactor_to", "normfactor_to"), ("vdot_norm_m3_per_s", "vf") ]) else: - required_results_hyd.extend([("v_mean_m_per_s", "v_mps")]) + required_results_hyd.extend([("vdot_m3_per_s", "vf")]) return required_results_hyd, required_results_ht -def get_component_array(net, component_name, component_type="branch", only_active=True): +def get_component_array(net, component_name, component_type="branch", mode='hydraulics', only_active=True): """ Returns the internal array of a component. @@ -215,8 +220,8 @@ def get_component_array(net, component_name, component_type="branch", only_activ :return: component_array - internal array of the component :rtype: numpy.ndarray """ - f_all, t_all = get_lookup(net, component_type, "from_to")[component_name] if not only_active: return net["_pit"]["components"][component_name] - in_service_elm = get_lookup(net, component_type, "active_hydraulics")[f_all:t_all] + f_all, t_all = get_lookup(net, component_type, "from_to")[component_name] + in_service_elm = get_lookup(net, component_type, "active_%s"%mode)[f_all:t_all] return net["_pit"]["components"][component_name][in_service_elm] diff --git a/src/pandapipes/component_models/compressor_component.py b/src/pandapipes/component_models/compressor_component.py index 3d16b7b5d..84c0e8a18 100644 --- a/src/pandapipes/component_models/compressor_component.py +++ b/src/pandapipes/component_models/compressor_component.py @@ -40,9 +40,6 @@ def create_pit_branch_entries(cls, net, branch_pit): :return: No Output. """ compressor_pit = super(Pump, cls).create_pit_branch_entries(net, branch_pit) - - compressor_pit[:, D] = 0.1 - compressor_pit[:, AREA] = compressor_pit[:, D] ** 2 * np.pi / 4 compressor_pit[:, LC] = 0 @classmethod diff --git a/src/pandapipes/component_models/ext_grid_component.py b/src/pandapipes/component_models/ext_grid_component.py index 2e1d9e792..e88590a09 100644 --- a/src/pandapipes/component_models/ext_grid_component.py +++ b/src/pandapipes/component_models/ext_grid_component.py @@ -6,9 +6,9 @@ from numpy import dtype from pandapipes.component_models.abstract_models.node_element_models import NodeElementComponent -from pandapipes.component_models.component_toolbox import set_fixed_node_entries, \ - get_mass_flow_at_nodes +from pandapipes.component_models.component_toolbox import set_fixed_node_entries from pandapipes.pf.pipeflow_setup import get_lookup +from pandapipes.idx_node import MDOTSLACKINIT, VAR_MASS_SLACK, JAC_DERIV_MSL try: import pandaplan.core.pplog as logging @@ -55,11 +55,15 @@ def create_pit_node_entries(cls, net, node_pit): ext_grids = ext_grids[ext_grids[cls.active_identifier()].values] junction = ext_grids[cls.get_node_col()].values - press = ext_grids.p_bar.values - set_fixed_node_entries(net, node_pit, junction, ext_grids.type.values, press, - ext_grids.t_k.values, cls.get_connected_node_type()) - - return ext_grids, press + types = ext_grids.type.values + p_values = ext_grids.p_bar.values + t_values = ext_grids.t_k.values + index_p = set_fixed_node_entries( + net, node_pit, junction, types, p_values, cls.get_connected_node_type(), 'p') + set_fixed_node_entries(net, node_pit, junction, types, t_values, cls.get_connected_node_type(), 't') + node_pit[index_p, JAC_DERIV_MSL] = -1. + node_pit[index_p, VAR_MASS_SLACK] = True + return ext_grids, p_values @classmethod def extract_results(cls, net, options, branch_results, mode): @@ -91,8 +95,8 @@ def extract_results(cls, net, options, branch_results, mode): # get indices in internal structure for junctions in ext_grid tables which are "active" eg_nodes = get_lookup(net, "node", "index")[cls.get_connected_node_type().table_name()][ junction[p_grids]] - sum_mass_flows, inverse_nodes, counts = get_mass_flow_at_nodes(net, node_pit, branch_pit, - eg_nodes, cls) + node_uni, inverse_nodes, counts = np.unique(eg_nodes, return_counts=True, return_inverse=True) + sum_mass_flows = node_pit[node_uni, MDOTSLACKINIT] # positive results mean that the ext_grid feeds in, negative means that the ext grid # extracts (like a load) diff --git a/src/pandapipes/component_models/flow_control_component.py b/src/pandapipes/component_models/flow_control_component.py index fbcf909d1..78db23dc1 100644 --- a/src/pandapipes/component_models/flow_control_component.py +++ b/src/pandapipes/component_models/flow_control_component.py @@ -10,7 +10,7 @@ from pandapipes.component_models.component_toolbox import \ standard_branch_wo_internals_result_lookup, get_component_array from pandapipes.component_models.junction_component import Junction -from pandapipes.idx_branch import D, AREA, JAC_DERIV_DP, JAC_DERIV_DP1, JAC_DERIV_DM, MDOTINIT, LOAD_VEC_BRANCHES +from pandapipes.idx_branch import JAC_DERIV_DP, JAC_DERIV_DP1, JAC_DERIV_DM, MDOTINIT, LOAD_VEC_BRANCHES from pandapipes.pf.result_extraction import extract_branch_results_without_internals @@ -49,8 +49,6 @@ def create_pit_branch_entries(cls, net, branch_pit): :return: No Output. """ fc_branch_pit = super().create_pit_branch_entries(net, branch_pit) - fc_branch_pit[:, D] = net[cls.table_name()].diameter_m.values - fc_branch_pit[:, AREA] = fc_branch_pit[:, D] ** 2 * np.pi / 4 fc_branch_pit[:, MDOTINIT] = net[cls.table_name()].controlled_mdot_kg_per_s.values @classmethod @@ -105,7 +103,6 @@ def get_component_input(cls): ("from_junction", "u4"), ("to_junction", "u4"), ("controlled_mdot_kg_per_s", "f8"), - ("diameter_m", "f8"), ("control_active", "bool"), ("in_service", 'bool'), ("type", dtype(object))] @@ -123,12 +120,12 @@ def get_result_table(cls, net): :rtype: (list, bool) """ if get_fluid(net).is_gas: - output = ["v_from_m_per_s", "v_to_m_per_s", "v_mean_m_per_s", "p_from_bar", "p_to_bar", - "t_from_k", "t_to_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", + output = ["p_from_bar", "p_to_bar", + "t_from_k", "t_to_k", "t_outlet_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_norm_m3_per_s", "reynolds", "lambda", "normfactor_from", "normfactor_to"] else: - output = ["v_mean_m_per_s", "p_from_bar", "p_to_bar", "t_from_k", "t_to_k", - "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_norm_m3_per_s", "reynolds", + output = ["p_from_bar", "p_to_bar", "t_from_k", "t_to_k", "t_outlet_k", + "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_m3_per_s", "reynolds", "lambda"] return output, True diff --git a/src/pandapipes/component_models/heat_consumer_component.py b/src/pandapipes/component_models/heat_consumer_component.py index f2f4aaf71..2d7eac6a1 100644 --- a/src/pandapipes/component_models/heat_consumer_component.py +++ b/src/pandapipes/component_models/heat_consumer_component.py @@ -5,13 +5,24 @@ import numpy as np from numpy import dtype -from pandapipes.component_models import get_fluid, \ - BranchWZeroLengthComponent, get_component_array, standard_branch_wo_internals_result_lookup +from pandapipes.component_models import (get_fluid, BranchWZeroLengthComponent, get_component_array, + standard_branch_wo_internals_result_lookup) from pandapipes.component_models.junction_component import Junction -from pandapipes.idx_branch import D, AREA, MDOTINIT, QEXT, JAC_DERIV_DP1, \ - JAC_DERIV_DM, JAC_DERIV_DP, LOAD_VEC_BRANCHES +from pandapipes.idx_branch import (MDOTINIT, QEXT, JAC_DERIV_DP1, JAC_DERIV_DM, + JAC_DERIV_DP, LOAD_VEC_BRANCHES, TOUTINIT, JAC_DERIV_DT, + JAC_DERIV_DTOUT, LOAD_VEC_BRANCHES_T, ACTIVE) +from pandapipes.idx_node import TINIT +from pandapipes.pf.internals_toolbox import get_from_nodes_corrected +from pandapipes.pf.pipeflow_setup import get_lookup from pandapipes.pf.result_extraction import extract_branch_results_without_internals +from pandapipes.properties.properties_toolbox import get_branch_cp +try: + import pandaplan.core.pplog as logging +except ImportError: + import logging + +logger = logging.getLogger(__name__) class HeatConsumer(BranchWZeroLengthComponent): """ @@ -26,17 +37,11 @@ class HeatConsumer(BranchWZeroLengthComponent): internal_cols = 5 - # numbering of given parameters (for mdot, qext, deltat, treturn) - MF = 0 - QE = 1 - DT = 2 - TR = 3 - # heat consumer modes (sum of combinations of given parameters) - MF_QE = 1 - MF_DT = 2 - MF_TR = 4 - QE_DT = 3 + MF_DT = 1 + MF_TR = 2 + QE_MF = 3 + QE_DT = 4 QE_TR = 5 @classmethod @@ -65,12 +70,20 @@ def create_pit_branch_entries(cls, net, branch_pit): :type branch_pit: :return: No Output. """ - hs_pit = super().create_pit_branch_entries(net, branch_pit) - hs_pit[:, D] = net[cls.table_name()].diameter_m.values - hs_pit[:, AREA] = hs_pit[:, D] ** 2 * np.pi / 4 - hs_pit[:, MDOTINIT] = net[cls.table_name()].controlled_mdot_kg_per_s.values - hs_pit[:, QEXT] = net[cls.table_name()].qext_w.values - return hs_pit + hc_pit = super().create_pit_branch_entries(net, branch_pit) + qext = net[cls.table_name()].qext_w.values + hc_pit[~np.isnan(qext), QEXT] = qext[~np.isnan(qext)] + mdot = net[cls.table_name()].controlled_mdot_kg_per_s.values + hc_pit[~np.isnan(mdot), MDOTINIT] = mdot[~np.isnan(mdot)] + treturn = net[cls.table_name()].treturn_k.values + hc_pit[~np.isnan(treturn), TOUTINIT] = treturn[~np.isnan(treturn)] + mask_q0 = qext == 0 & np.isnan(mdot) + if np.any(mask_q0): + hc_pit[mask_q0, ACTIVE] = False + logger.warning(r'qext_w is equals to zero for heat consumers with index %s. ' + r'Therefore, the defined temperature control cannot be maintained.' \ + %net[cls.table_name()].index[mask_q0]) + return hc_pit @classmethod def create_component_array(cls, net, component_pits): @@ -87,17 +100,38 @@ def create_component_array(cls, net, component_pits): """ tbl = net[cls.table_name()] consumer_array = np.zeros(shape=(len(tbl), cls.internal_cols), dtype=np.float64) - consumer_array[:, cls.MASS] = tbl.controlled_mdot_kg_per_s.values - consumer_array[:, cls.QEXT] = tbl.qext_w.values consumer_array[:, cls.DELTAT] = tbl.deltat_k.values consumer_array[:, cls.TRETURN] = tbl.treturn_k.values - mf = ~np.isnan(consumer_array[:, cls.MASS]) - qe = ~np.isnan(consumer_array[:, cls.QEXT]) - dt = ~np.isnan(consumer_array[:, cls.DELTAT]) - tr = ~np.isnan(consumer_array[:, cls.TRETURN]) - consumer_array[:, cls.MODE] = np.sum([mf, qe, dt, tr], axis=0) + consumer_array[:, cls.QEXT] = tbl.qext_w.values + consumer_array[:, cls.MASS] = tbl.controlled_mdot_kg_per_s.values + mf = tbl.controlled_mdot_kg_per_s.values + tr = tbl.treturn_k.values + dt = tbl.deltat_k.values + qe = tbl.qext_w.values + mf = ~np.isnan(mf) + tr = ~np.isnan(tr) + dt = ~np.isnan(dt) + qe = ~np.isnan(qe) + consumer_array[mf & dt, cls.MODE] = cls.MF_DT + consumer_array[mf & tr, cls.MODE] = cls.MF_TR + consumer_array[qe & mf, cls.MODE] = cls.QE_MF + consumer_array[qe & dt, cls.MODE] = cls.QE_DT + consumer_array[qe & tr, cls.MODE] = cls.QE_TR component_pits[cls.table_name()] = consumer_array + @classmethod + def adaption_before_derivatives_hydraulic(cls, net, branch_pit, node_pit, idx_lookups, options): + f, t = idx_lookups[cls.table_name()] + hc_pit = branch_pit[f:t, :] + consumer_array = get_component_array(net, cls.table_name()) + + mask = consumer_array[:, cls.MODE] == cls.QE_DT + if np.any(mask): + cp = get_branch_cp(get_fluid(net), node_pit, hc_pit[mask]) + deltat = consumer_array[mask, cls.DELTAT] + mass = hc_pit[mask, QEXT] / (cp * deltat) + hc_pit[mask, MDOTINIT] = mass + @classmethod def adaption_after_derivatives_hydraulic(cls, net, branch_pit, node_pit, idx_lookups, options): """ @@ -119,50 +153,59 @@ def adaption_after_derivatives_hydraulic(cls, net, branch_pit, node_pit, idx_loo # set all pressure derivatives to 0 and velocity to 1; load vector must be 0, as no change # of velocity is allowed during the pipeflow iteration f, t = idx_lookups[cls.table_name()] - fc_branch_pit = branch_pit[f:t, :] - fc_array = get_component_array(net, cls.table_name()) - # TODO: this is more precise, but slower: - # np.isin(fc_array[:, cls.MODE], [cls.MF_QE, cls.MF_DT, cls.MF_TR]) - mdot_controlled = ~np.isnan(fc_array[:, cls.MASS]) - fc_branch_pit[mdot_controlled, JAC_DERIV_DP] = 0 - fc_branch_pit[mdot_controlled, JAC_DERIV_DP1] = 0 - fc_branch_pit[mdot_controlled, JAC_DERIV_DM] = 1 - fc_branch_pit[mdot_controlled, LOAD_VEC_BRANCHES] = 0 - - # @classmethod - # def adaption_before_derivatives_thermal(cls, net, branch_pit, node_pit, idx_lookups, options): - # f, t = idx_lookups[cls.table_name()] - # hs_pit = branch_pit[f:t, :] - # mask_t_return = ~np.isnan(hs_pit[:, TRETURN]) - # hs_pit[mask_t_return, TINIT_OUT] = (hs_pit[mask_t_return, TINIT_OUT] - # - hs_pit[mask_t_return, DELTAT]) - # - # - # @classmethod - # def adaption_after_derivatives_thermal(cls, net, branch_pit, node_pit, idx_lookups, options): - # """ - # - # :param net: - # :type net: - # :param branch_component_pit: - # :type branch_component_pit: - # :param node_pit: - # :type node_pit: - # :return: - # :rtype: - # """ - # # -(rho * area * cp * v_init * (-t_init_i + t_init_i1 - tl) - # # - alpha * (t_amb - t_m) * length + qext) - # - # f, t = idx_lookups[cls.table_name()] - # hs_pit = branch_pit[f:t, :] - # from_nodes = hs_pit[:, FROM_NODE_T].astype(np.int32) - # - # mask_qext = ~np.isnan(hs_pit[:, QEXT]) - # mask_deltat = ~np.isnan(hs_pit[:, DELTAT]) - # mask_t_return = ~np.isnan(hs_pit[:, TRETURN]) - # mask_mass = ~np.isnan(hs_pit[:, MASS]) - # hs_pit[mask_t_return | mask_deltat, JAC_DERIV_DT1] = 0 + consumer_array = get_component_array(net, cls.table_name()) + + hc_pit = branch_pit[f:t, :] + hc_pit[:, JAC_DERIV_DP] = 0 + hc_pit[:, JAC_DERIV_DP1] = 0 + hc_pit[:, JAC_DERIV_DM] = 1 + hc_pit[:, LOAD_VEC_BRANCHES] = 0 + + mask = consumer_array[:, cls.MODE] == cls.QE_TR + if np.any(mask): + cp = get_branch_cp(get_fluid(net), node_pit, hc_pit) + from_nodes = get_from_nodes_corrected(hc_pit) + t_in = node_pit[from_nodes, TINIT] + t_out = hc_pit[:, TOUTINIT] + + df_dm = - cp * (t_out - t_in) + hc_pit[mask, LOAD_VEC_BRANCHES] = - hc_pit[mask, QEXT] + df_dm[mask] * hc_pit[mask, MDOTINIT] + mask_equal = t_out == t_in + hc_pit[mask & mask_equal, MDOTINIT] = 0 + hc_pit[mask & ~mask_equal, JAC_DERIV_DM] = df_dm[mask & ~mask_equal] + + @classmethod + def adaption_before_derivatives_thermal(cls, net, branch_pit, node_pit, idx_lookups, options): + f, t = idx_lookups[cls.table_name()] + hc_pit = branch_pit[f:t, :] + consumer_array = get_component_array(net, cls.table_name(), mode='heat_transfer') + mask = consumer_array[:, cls.MODE] == cls.MF_DT + if np.any(mask): + cp = get_branch_cp(get_fluid(net), node_pit, hc_pit) + q_ext = cp[mask] * hc_pit[mask, MDOTINIT] * consumer_array[mask, cls.DELTAT] + hc_pit[mask, QEXT] = q_ext + + mask = consumer_array[:, cls.MODE] == cls.MF_TR + if np.any(mask): + cp = get_branch_cp(get_fluid(net), node_pit, hc_pit) + from_nodes = get_from_nodes_corrected(hc_pit[mask]) + t_in = node_pit[from_nodes, TINIT] + t_out = consumer_array[mask, cls.TRETURN] + q_ext = cp[mask] * hc_pit[mask, MDOTINIT] * (t_in - t_out) + hc_pit[mask, QEXT] = q_ext + + @classmethod + def adaption_after_derivatives_thermal(cls, net, branch_pit, node_pit, idx_lookups, options): + f, t = idx_lookups[cls.table_name()] + hc_pit = branch_pit[f:t, :] + consumer_array = get_component_array(net, cls.table_name(), mode='heat_transfer') + + # Any MODE where TRETURN is given + mask = consumer_array[:, cls.MODE] == cls.QE_TR + if np.any(mask): + hc_pit[mask, LOAD_VEC_BRANCHES_T] = 0 + hc_pit[mask, JAC_DERIV_DTOUT] = 1 + hc_pit[mask, JAC_DERIV_DT] = 0 @classmethod def get_component_input(cls): @@ -173,16 +216,9 @@ def get_component_input(cls): :return: :rtype: """ - return [("name", dtype(object)), - ("from_junction", "u4"), - ("to_junction", "u4"), - ("qext_w", "f8"), - ("controlled_mdot_kg_per_s", "f8"), - ("deltat_k", "f8"), - ("treturn_k", "f8"), - ("diameter_m", "f8"), - ("in_service", "bool"), - ("type", dtype(object))] + return [("name", dtype(object)), ("from_junction", "u4"), ("to_junction", "u4"), ("qext_w", "f8"), + ("controlled_mdot_kg_per_s", "f8"), ("deltat_k", "f8"), ("treturn_k", "f8"), + ("in_service", "bool"), ("type", dtype(object))] @classmethod def get_result_table(cls, net): @@ -197,14 +233,13 @@ def get_result_table(cls, net): :rtype: (list, bool) """ if get_fluid(net).is_gas: - output = ["v_from_m_per_s", "v_to_m_per_s", "v_mean_m_per_s", "p_from_bar", "p_to_bar", - "t_from_k", "t_to_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", - "vdot_norm_m3_per_s", "reynolds", "lambda", "normfactor_from", - "normfactor_to"] + output = ["p_from_bar", "p_to_bar", "t_from_k", + "t_to_k", "t_outlet_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_norm_m3_per_s", "reynolds", "lambda", + "normfactor_from", "normfactor_to"] else: - output = ["v_mean_m_per_s", "p_from_bar", "p_to_bar", "t_from_k", "t_to_k", - "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_norm_m3_per_s", "reynolds", - "lambda"] + output = ["p_from_bar", "p_to_bar", "t_from_k", "t_to_k", "t_outlet_k", "mdot_from_kg_per_s", + "mdot_to_kg_per_s", "vdot_m3_per_s", "reynolds", "lambda"] + output += ['deltat_k', 'qext_w'] return output, True @classmethod @@ -224,5 +259,18 @@ def extract_results(cls, net, options, branch_results, mode): """ required_results_hyd, required_results_ht = standard_branch_wo_internals_result_lookup(net) - extract_branch_results_without_internals(net, branch_results, required_results_hyd, - required_results_ht, cls.table_name(), mode) + extract_branch_results_without_internals(net, branch_results, required_results_hyd, required_results_ht, + cls.table_name(), mode) + + node_pit = net['_pit']['node'] + branch_pit = net['_pit']['branch'] + branch_lookups = get_lookup(net, "branch", "from_to") + f, t = branch_lookups[cls.table_name()] + + res_table = net["res_" + cls.table_name()] + + res_table['qext_w'].values[:] = branch_pit[f:t, QEXT] + from_nodes = get_from_nodes_corrected(branch_pit[f:t]) + t_from = node_pit[from_nodes, TINIT] + tout = branch_pit[f:t, TOUTINIT] + res_table['deltat_k'].values[:] = t_from - tout diff --git a/src/pandapipes/component_models/heat_exchanger_component.py b/src/pandapipes/component_models/heat_exchanger_component.py index cbcaef46f..4bc48aecb 100644 --- a/src/pandapipes/component_models/heat_exchanger_component.py +++ b/src/pandapipes/component_models/heat_exchanger_component.py @@ -52,8 +52,6 @@ def create_pit_branch_entries(cls, net, branch_pit): :return: No Output. """ heat_exchanger_pit = super().create_pit_branch_entries(net, branch_pit) - heat_exchanger_pit[:, D] = net[cls.table_name()].diameter_m.values - heat_exchanger_pit[:, AREA] = heat_exchanger_pit[:, D] ** 2 * np.pi / 4 heat_exchanger_pit[:, LC] = net[cls.table_name()].loss_coefficient.values heat_exchanger_pit[:, QEXT] = net[cls.table_name()].qext_w.values @@ -105,12 +103,12 @@ def get_result_table(cls, net): :rtype: (list, bool) """ if get_fluid(net).is_gas: - output = ["v_from_m_per_s", "v_to_m_per_s", "v_mean_m_per_s", "p_from_bar", "p_to_bar", - "t_from_k", "t_to_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", + output = ["p_from_bar", "p_to_bar", + "t_from_k", "t_to_k", "t_outlet_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_norm_m3_per_s", "reynolds", "lambda", "normfactor_from", "normfactor_to"] else: - output = ["v_mean_m_per_s", "p_from_bar", "p_to_bar", "t_from_k", "t_to_k", - "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_norm_m3_per_s", "reynolds", + output = ["p_from_bar", "p_to_bar", "t_from_k", "t_to_k", "t_outlet_k", + "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_m3_per_s", "reynolds", "lambda"] return output, True diff --git a/src/pandapipes/component_models/junction_component.py b/src/pandapipes/component_models/junction_component.py index 2f0f77ed5..67cbcd14a 100644 --- a/src/pandapipes/component_models/junction_component.py +++ b/src/pandapipes/component_models/junction_component.py @@ -107,7 +107,7 @@ def extract_results(cls, net, options, branch_results, mode): f, t = get_lookup(net, "node", "from_to")[cls.table_name()] junction_pit = net["_pit"]["node"][f:t, :] - if mode in ["hydraulics", "all"]: + if mode in ["hydraulics", "sequential", "bidirectional"]: junctions_connected_hydraulic = get_lookup(net, "node", "active_hydraulics")[f:t] if np.any(junction_pit[junctions_connected_hydraulic, PINIT] < 0): @@ -119,7 +119,7 @@ def extract_results(cls, net, options, branch_results, mode): # if mode == "hydraulics": # res_table["t_k"].values[junctions_connected_hydraulic] = junction_pit[:, TINIT] # - # if mode in ["heat", "all"]: + # if mode in ["heat", "sequential", "bidirectional]: # junctions_connected_ht = get_lookup(net, "node", "active_heat_transfer")[f:t] # res_table["t_k"].values[junctions_connected_ht] = junction_pit[:, TINIT] res_table["p_bar"].values[:] = junction_pit[:, PINIT] diff --git a/src/pandapipes/component_models/pipe_component.py b/src/pandapipes/component_models/pipe_component.py index 3492b6c79..facea584d 100644 --- a/src/pandapipes/component_models/pipe_component.py +++ b/src/pandapipes/component_models/pipe_component.py @@ -13,7 +13,7 @@ from pandapipes.idx_branch import FROM_NODE, TO_NODE, LENGTH, D, AREA, K, \ MDOTINIT, ALPHA, QEXT, TEXT, LOSS_COEFFICIENT as LC from pandapipes.idx_node import PINIT, TINIT as TINIT_NODE, PAMB -from pandapipes.pf.pipeflow_setup import get_fluid, get_lookup +from pandapipes.pf.pipeflow_setup import get_fluid, get_lookup, get_net_option from pandapipes.pf.result_extraction import extract_branch_results_with_internals, \ extract_branch_results_without_internals @@ -112,7 +112,7 @@ def create_pit_branch_entries(cls, net, branch_pit): set_entry_check_repeat( pipe_pit, K, net[tbl].k_mm.values / 1000, internal_pipe_number, has_internals) set_entry_check_repeat( - pipe_pit, ALPHA, net[tbl].alpha_w_per_m2k.values, internal_pipe_number, has_internals) + pipe_pit, ALPHA, net[tbl].u_w_per_m2k.values, internal_pipe_number, has_internals) set_entry_check_repeat( pipe_pit, QEXT, net[tbl].qext_w.values, internal_pipe_number, has_internals) set_entry_check_repeat( @@ -122,6 +122,8 @@ def create_pit_branch_entries(cls, net, branch_pit): set_entry_check_repeat( pipe_pit, LC, net[tbl].loss_coefficient.values, internal_pipe_number, has_internals) + nan_mask = np.isnan(pipe_pit[:, TEXT]) + pipe_pit[nan_mask, TEXT] = get_net_option(net, 'ambient_temperature') pipe_pit[:, AREA] = pipe_pit[:, D] ** 2 * np.pi / 4 pipe_pit[:, MDOTINIT] *= pipe_pit[:, AREA] * get_fluid(net).get_density(NORMAL_TEMPERATURE) @@ -131,26 +133,26 @@ def extract_results(cls, net, options, branch_results, mode): res_nodes_from_ht = [("t_from_k", "temp_from")] res_nodes_to_hyd = [("p_to_bar", "p_to"), ("mdot_to_kg_per_s", "mf_to")] res_nodes_to_ht = [("t_to_k", "temp_to")] - res_mean_hyd = [("vdot_norm_m3_per_s", "vf"), ("lambda", "lambda"), - ("reynolds", "reynolds")] + res_mean_hyd = [("lambda", "lambda"), ("reynolds", "reynolds")] + res_branch_ht = [("t_outlet_k", "t_outlet")] if get_fluid(net).is_gas: res_nodes_from_hyd.extend([("v_from_m_per_s", "v_gas_from"), ("normfactor_from", "normfactor_from")]) res_nodes_to_hyd.extend([("v_to_m_per_s", "v_gas_to"), ("normfactor_to", "normfactor_to")]) - res_mean_hyd.extend([("v_mean_m_per_s", "v_gas_mean")]) + res_mean_hyd.extend([("v_mean_m_per_s", "v_gas_mean"), ("vdot_norm_m3_per_s", "vf")]) else: - res_mean_hyd.extend([("v_mean_m_per_s", "v_mps")]) + res_mean_hyd.extend([("v_mean_m_per_s", "v_mps"), ("vdot_m3_per_s", "vf")]) if np.any(cls.get_internal_pipe_number(net) > 1): extract_branch_results_with_internals( net, branch_results, cls.table_name(), res_nodes_from_hyd, res_nodes_from_ht, - res_nodes_to_hyd, res_nodes_to_ht, res_mean_hyd, [], + res_nodes_to_hyd, res_nodes_to_ht, res_mean_hyd, res_branch_ht, [], cls.get_connected_node_type().table_name(), mode) else: required_results_hyd = res_nodes_from_hyd + res_nodes_to_hyd + res_mean_hyd - required_results_ht = res_nodes_from_ht + res_nodes_to_ht + required_results_ht = res_nodes_from_ht + res_nodes_to_ht + res_branch_ht extract_branch_results_without_internals( net, branch_results, required_results_hyd, required_results_ht, cls.table_name(), mode @@ -264,7 +266,7 @@ def get_component_input(cls): ("diameter_m", "f8"), ("k_mm", "f8"), ("loss_coefficient", "f8"), - ("alpha_w_per_m2k", 'f8'), + ("u_w_per_m2k", 'f8'), ("text_k", 'f8'), ("qext_w", 'f8'), ("sections", "u4"), @@ -292,12 +294,12 @@ def get_result_table(cls, net): """ if get_fluid(net).is_gas: output = ["v_from_m_per_s", "v_to_m_per_s", "v_mean_m_per_s", "p_from_bar", "p_to_bar", - "t_from_k", "t_to_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", + "t_from_k", "t_to_k", "t_outlet_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_norm_m3_per_s", "reynolds", "lambda", "normfactor_from", "normfactor_to"] else: - output = ["v_mean_m_per_s", "p_from_bar", "p_to_bar", "t_from_k", "t_to_k", - "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_norm_m3_per_s", "reynolds", + output = ["v_mean_m_per_s", "p_from_bar", "p_to_bar", "t_from_k", "t_to_k", "t_outlet_k", + "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_m3_per_s", "reynolds", "lambda"] return output, True diff --git a/src/pandapipes/component_models/pressure_control_component.py b/src/pandapipes/component_models/pressure_control_component.py index b2e5b3de1..20c5d2b3a 100644 --- a/src/pandapipes/component_models/pressure_control_component.py +++ b/src/pandapipes/component_models/pressure_control_component.py @@ -7,10 +7,11 @@ from pandapipes.component_models.abstract_models.branch_wzerolength_models import \ BranchWZeroLengthComponent +from pandapipes.component_models import standard_branch_wo_internals_result_lookup from pandapipes.component_models.junction_component import Junction from pandapipes.idx_branch import D, AREA, \ - JAC_DERIV_DP, JAC_DERIV_DP1, JAC_DERIV_DM, BRANCH_TYPE, LOSS_COEFFICIENT as LC -from pandapipes.idx_node import PINIT, NODE_TYPE, PC + JAC_DERIV_DP, JAC_DERIV_DP1, JAC_DERIV_DM, BRANCH_TYPE, LOSS_COEFFICIENT as LC, PC as PC_BRANCH +from pandapipes.idx_node import PINIT, NODE_TYPE, PC as PC_NODE from pandapipes.pf.pipeflow_setup import get_lookup from pandapipes.pf.result_extraction import extract_branch_results_without_internals from pandapipes.properties.fluids import get_fluid @@ -46,7 +47,7 @@ def create_pit_node_entries(cls, net, node_pit): junction_idx_lookups = get_lookup(net, "node", "index")[ cls.get_connected_node_type().table_name()] index_pc = junction_idx_lookups[juncts] - node_pit[index_pc, NODE_TYPE] = PC + node_pit[index_pc, NODE_TYPE] = PC_NODE node_pit[index_pc, PINIT] = press @classmethod @@ -60,9 +61,7 @@ def create_pit_branch_entries(cls, net, branch_pit): :return: No Output. """ pc_pit = super().create_pit_branch_entries(net, branch_pit) - pc_pit[:, D] = 0.1 - pc_pit[:, AREA] = pc_pit[:, D] ** 2 * np.pi / 4 - pc_pit[net[cls.table_name()].control_active.values, BRANCH_TYPE] = PC + pc_pit[net[cls.table_name()].control_active.values, BRANCH_TYPE] = PC_BRANCH pc_pit[:, LC] = net[cls.table_name()].loss_coefficient.values @classmethod @@ -74,7 +73,7 @@ def adaption_after_derivatives_hydraulic(cls, net, branch_pit, node_pit, idx_loo # set all PC branches to derivatives to 0 f, t = idx_lookups[cls.table_name()] press_pit = branch_pit[f:t, :] - pc_branch = press_pit[:, BRANCH_TYPE] == PC + pc_branch = press_pit[:, BRANCH_TYPE] == PC_BRANCH press_pit[pc_branch, JAC_DERIV_DP] = 0 press_pit[pc_branch, JAC_DERIV_DP1] = 0 press_pit[pc_branch, JAC_DERIV_DM] = 0 @@ -94,19 +93,8 @@ def extract_results(cls, net, options, branch_results, mode): :type options: :return: No Output. """ - required_results_hyd = [ - ("p_from_bar", "p_from"), ("p_to_bar", "p_to"), ("mdot_from_kg_per_s", "mf_from"), - ("mdot_to_kg_per_s", "mf_to"), ("vdot_norm_m3_per_s", "vf") - ] - required_results_ht = [("t_from_k", "temp_from"), ("t_to_k", "temp_to")] - if get_fluid(net).is_gas: - required_results_hyd.extend([ - ("v_from_m_per_s", "v_gas_from"), ("v_to_m_per_s", "v_gas_to"), - ("normfactor_from", "normfactor_from"), ("normfactor_to", "normfactor_to") - ]) - else: - required_results_hyd.extend([("v_mean_m_per_s", "v_mps")]) + required_results_hyd, required_results_ht = standard_branch_wo_internals_result_lookup(net) extract_branch_results_without_internals(net, branch_results, required_results_hyd, required_results_ht, cls.table_name(), mode) @@ -149,11 +137,11 @@ def get_result_table(cls, net): :rtype: (list, bool) """ if get_fluid(net).is_gas: - output = ["v_from_m_per_s", "v_to_m_per_s", "p_from_bar", "p_to_bar", - "t_from_k", "t_to_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", + output = ["p_from_bar", "p_to_bar", + "t_from_k", "t_to_k", "t_outlet_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_norm_m3_per_s", "normfactor_from", "normfactor_to"] else: - output = ["v_mean_m_per_s", "p_from_bar", "p_to_bar", "t_from_k", "t_to_k", - "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_norm_m3_per_s"] + output = ["p_from_bar", "p_to_bar", "t_from_k", "t_to_k", "t_outlet_k", + "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_m3_per_s"] output += ["deltap_bar"] return output, True diff --git a/src/pandapipes/component_models/pump_component.py b/src/pandapipes/component_models/pump_component.py index eeaa8938e..59cc44ae4 100644 --- a/src/pandapipes/component_models/pump_component.py +++ b/src/pandapipes/component_models/pump_component.py @@ -9,6 +9,7 @@ from pandapipes.component_models.abstract_models.branch_wzerolength_models import \ BranchWZeroLengthComponent +from pandapipes.component_models import standard_branch_wo_internals_result_lookup from pandapipes.component_models.component_toolbox import get_component_array from pandapipes.component_models.junction_component import Junction from pandapipes.constants import NORMAL_TEMPERATURE, NORMAL_PRESSURE, R_UNIVERSAL, P_CONVERSION @@ -61,8 +62,6 @@ def create_pit_branch_entries(cls, net, branch_pit): :return: No Output. """ pump_pit = super().create_pit_branch_entries(net, branch_pit) - pump_pit[:, D] = 0.1 - pump_pit[:, AREA] = pump_pit[:, D] ** 2 * np.pi / 4 pump_pit[:, LC] = 0 @classmethod @@ -134,25 +133,14 @@ def extract_results(cls, net, options, branch_results, mode): :type mode: :return: No Output. """ - calc_compr_pow = options['calc_compression_power'] - required_results_hyd = [ - ("p_from_bar", "p_from"), ("p_to_bar", "p_to"), ("mdot_to_kg_per_s", "mf_to"), - ("mdot_from_kg_per_s", "mf_from"), ("vdot_norm_m3_per_s", "vf"), ("deltap_bar", "pl"), - ] - required_results_ht = [("t_from_k", "temp_from"), ("t_to_k", "temp_to")] - - if get_fluid(net).is_gas: - required_results_hyd.extend([ - ("v_from_m_per_s", "v_gas_from"), ("v_to_m_per_s", "v_gas_to"), - ("normfactor_from", "normfactor_from"), ("normfactor_to", "normfactor_to") - ]) - else: - required_results_hyd.extend([("v_mean_m_per_s", "v_mps")]) + required_results_hyd, required_results_ht = standard_branch_wo_internals_result_lookup(net) + required_results_hyd.extend([("deltap_bar", "pl")]) extract_branch_results_without_internals(net, branch_results, required_results_hyd, required_results_ht, cls.table_name(), mode) + calc_compr_pow = options['calc_compression_power'] if calc_compr_pow: f, t = get_lookup(net, "branch", "from_to")[cls.table_name()] from_nodes = branch_results["from_nodes"][f:t] @@ -217,14 +205,12 @@ def get_result_table(cls, net): if get_fluid(net).is_gas: output = ["deltap_bar", - "v_from_m_per_s", "v_to_m_per_s", "p_from_bar", "p_to_bar", - "t_from_k", "t_to_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", + "t_from_k", "t_to_k", "t_outlet_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_norm_m3_per_s", "normfactor_from", "normfactor_to"] - # TODO: inwieweit sind diese Angaben bei imaginärem Durchmesser sinnvoll? else: - output = ["deltap_bar", "v_mean_m_per_s", "p_from_bar", "p_to_bar", "t_from_k", - "t_to_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_norm_m3_per_s"] + output = ["deltap_bar", "p_from_bar", "p_to_bar", "t_from_k", + "t_to_k", "t_outlet_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_m3_per_s"] if calc_compr_pow: output += ["compr_power_mw"] diff --git a/src/pandapipes/component_models/valve_component.py b/src/pandapipes/component_models/valve_component.py index b88403361..5932d7abf 100644 --- a/src/pandapipes/component_models/valve_component.py +++ b/src/pandapipes/component_models/valve_component.py @@ -71,6 +71,11 @@ def get_component_input(cls): def extract_results(cls, net, options, branch_results, mode): required_results_hyd, required_results_ht = standard_branch_wo_internals_result_lookup(net) + required_results_hyd.extend([("v_mean_m_per_s", "v_mps"), ("lambda", "lambda"), ("reynolds", "reynolds")]) + + if get_fluid(net).is_gas: + required_results_hyd.extend([("v_from_m_per_s", "v_gas_from"), ("v_to_m_per_s", "v_gas_to")]) + extract_branch_results_without_internals(net, branch_results, required_results_hyd, required_results_ht, cls.table_name(), mode) @@ -86,11 +91,11 @@ def get_result_table(cls, net): """ if get_fluid(net).is_gas: output = ["v_from_m_per_s", "v_to_m_per_s", "v_mean_m_per_s", "p_from_bar", "p_to_bar", - "t_from_k", "t_to_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", + "t_from_k", "t_to_k", "t_outlet_k", "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_norm_m3_per_s", "reynolds", "lambda", "normfactor_from", "normfactor_to"] else: - output = ["v_mean_m_per_s", "p_from_bar", "p_to_bar", "t_from_k", "t_to_k", - "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_norm_m3_per_s", "reynolds", + output = ["v_mean_m_per_s", "p_from_bar", "p_to_bar", "t_from_k", "t_to_k", "t_outlet_k", + "mdot_from_kg_per_s", "mdot_to_kg_per_s", "vdot_m3_per_s", "reynolds", "lambda"] return output, True diff --git a/src/pandapipes/converter/stanet/data_cleaning.py b/src/pandapipes/converter/stanet/data_cleaning.py index aa7389530..2aa6db04a 100644 --- a/src/pandapipes/converter/stanet/data_cleaning.py +++ b/src/pandapipes/converter/stanet/data_cleaning.py @@ -20,7 +20,7 @@ def sort_by_pos(group): def sort_by_flow(group): group["follower"] = group.FLUSSB.apply(lambda b: group.index[group.FLUSSA == b][0] - if b in group.FLUSSA.values else np.NaN) + if b in group.FLUSSA.values else np.nan) ls = list(group.loc[~group.FLUSSA.isin(group.FLUSSB)].index) assert len(ls) == 1 while len(ls) < len(group): diff --git a/src/pandapipes/converter/stanet/preparing_steps.py b/src/pandapipes/converter/stanet/preparing_steps.py index f3edbcb94..8ddde1917 100644 --- a/src/pandapipes/converter/stanet/preparing_steps.py +++ b/src/pandapipes/converter/stanet/preparing_steps.py @@ -182,7 +182,7 @@ def get_net_params(net, stored_data): net_params["t_sutherland"] = net_data.at[0, "TS"] net_params["t0_sutherland"] = net_data.at[0, "T0"] net_params["calculate_temp"] = str(net_data.at[0, "TEMPCALC"]) == "J" - pp_calc_mode = "all" if net_params["calculate_temp"] else "hydraulics" + pp_calc_mode = "sequential" if net_params["calculate_temp"] else "hydraulics" pandapipes.set_user_pf_options(net, mode=pp_calc_mode) net_params["medium_temp_C"] = net_data.at[0, "TEMP"] net_params["medium_temp_K"] = net_data.at[0, "TEMP"] + 273.15 @@ -241,7 +241,7 @@ def adapt_pipe_data_according_to_nodes(pipe_data, pipes_to_check, node_geo, pipe node_val = node_geo.loc[pipe_data.loc[pipes_to_check, node_nr].values, node_name].values if pipe_name not in pipe_data.columns: - pipe_data[pipe_name] = np.NaN + pipe_data[pipe_name] = np.nan pipe_data.loc[pipes_to_check, pipe_name] = node_val current_pipe_data = pipe_data.loc[pipes_to_check] if not np.allclose(node_val, current_pipe_data[pipe_name].values): @@ -401,9 +401,9 @@ def connection_pipe_section_table(stored_data, pipe_geodata, house_pipe_geodata, # but requires checks (e.g. positioning on pipe, max. 2 valves per pipe) c2 = stored_data["slider_valves"].loc[:, [c for c in required_columns if c not in ["PRECH", "VMA", "VMB"]]] - c2["PRECH"] = np.NaN - c2["VMA"] = np.NaN - c2["VMB"] = np.NaN + c2["PRECH"] = np.nan + c2["VMA"] = np.nan + c2["VMB"] = np.nan c2["type"] = "slider_valves" connections = pd.concat([connections, c2], ignore_index=True) diff --git a/src/pandapipes/converter/stanet/table_creation.py b/src/pandapipes/converter/stanet/table_creation.py index 280d3a64a..425705838 100644 --- a/src/pandapipes/converter/stanet/table_creation.py +++ b/src/pandapipes/converter/stanet/table_creation.py @@ -149,9 +149,9 @@ def create_valve_and_pipe(net, stored_data, index_mapping, net_params, stanet_li j_ref = net.junction.loc[node_mapping[from_stanet_nr], :] j_ref_geodata = net.junction_geodata.loc[node_mapping[from_stanet_nr], :] j_aux = pandapipes.create_junction( - net, np.NaN, tfluid_k=net_params["medium_temp_K"], height_m=j_ref['height_m'], + net, np.nan, tfluid_k=net_params["medium_temp_K"], height_m=j_ref['height_m'], name='aux_' + j_ref['stanet_id'], geodata=(j_ref_geodata.x, j_ref_geodata.y), - stanet_nr=-999, stanet_id='aux_' + j_ref['stanet_id'], p_stanet=np.NaN, + stanet_nr=-999, stanet_id='aux_' + j_ref['stanet_id'], p_stanet=np.nan, stanet_active=bool(row.ISACTIVE), **add_info ) text_k = 293 @@ -169,7 +169,7 @@ def create_valve_and_pipe(net, stored_data, index_mapping, net_params, stanet_li net, j_aux, node_mapping[to_stanet_nr], diameter_m=float(row.DM / 1000), opened=row.AUF == 'J', loss_coefficient=0, name="valve_%s_%s" % ('aux_' + str(row.ENDNAM), str(row.ENDNAM)), - stanet_nr=int(row.RECNO), stanet_id=str(row.STANETID), v_stanet=np.NaN, + stanet_nr=int(row.RECNO), stanet_id=str(row.STANETID), v_stanet=np.nan, stanet_active=bool(row.ISACTIVE), **add_info ) @@ -382,7 +382,7 @@ def create_control_components(net, stored_data, index_mapping, net_params, add_l drop_eg = net.ext_grid.loc[net.ext_grid.junction.isin(to_junctions[is_pc])].index net.ext_grid.drop(drop_eg, inplace=True) - net.junction.loc[to_junctions[is_pc], "pn_bar"] = np.NaN + net.junction.loc[to_junctions[is_pc], "pn_bar"] = np.nan pandapipes.reindex_elements(net, "ext_grid", np.arange(len(net.ext_grid))) if np.any(is_fc): @@ -463,7 +463,7 @@ def create_junctions_from_connections(net, connection_table, net_params, index_m continue stanet_ids = cons.STANETID.astype(str).values stanet_nrs = cons.RECNO.astype(np.int32).values - p_stanet = cons.PRECH.astype(np.float64).values if houses_in_calculation else np.NaN + p_stanet = cons.PRECH.astype(np.float64).values if houses_in_calculation else np.nan names = stanet_ids if con_type not in extend_from_to else \ stanet_ids + node_type.replace(con_type, "") geo = np.array([cons.geo.apply(lambda g: g[0]), cons.geo.apply(lambda g: g[1])]).transpose() @@ -475,7 +475,7 @@ def create_junctions_from_connections(net, connection_table, net_params, index_m if add_layers: add_info["stanet_layer"] = cons.LAYER.values.astype(str) pp_indices = pandapipes.create_junctions( - net, len(cons), np.NaN, net_params["medium_temp_K"], name=names, + net, len(cons), np.nan, net_params["medium_temp_K"], name=names, height_m=cons.GEOH.astype(np.float64).values, geodata=geo, type=cons.type.values, in_service=in_service, stanet_nr=stanet_nrs, stanet_id=stanet_ids, p_stanet=p_stanet, stanet_system=cons.CLIENTTYP.replace(CLIENT_TYPES_OF_PIPES).values, @@ -602,7 +602,7 @@ def create_geodata_sections(row): net, pipe_sections.fj.values, pipe_sections.tj.values, pipe_sections.length.values / 1000, pipes.DM.values / 1000, pipes.RAU.values, pipes.ZETA.values, type="main_pipe", stanet_std_type=pipes.ROHRTYP.values, in_service=pipes.ISACTIVE.values, text_k=text_k, - alpha_w_per_m2k=alpha, + u_w_per_m2k=alpha, name=["pipe_%s_%s_%s" % (nf, nt, sec) for nf, nt, sec in zip( pipes.ANFNAM.values, pipes.ENDNAM.values, pipe_sections.section_no.values)], stanet_nr=pipes.RECNO.values, stanet_id=pipes.STANETID.values, @@ -735,7 +735,7 @@ def create_pipes_from_remaining_pipe_table(net, stored_data, connection_table, i loss_coefficient=p_tbl.ZETA.values, stanet_std_type=p_tbl.ROHRTYP.values, k_mm=p_tbl.RAU.values, in_service=p_tbl.ISACTIVE.values.astype(np.bool_), name=["pipe_%s_%s" % (anf, end) for anf, end in zip(from_names[valid], to_names[valid])], - alpha_w_per_m2k=alpha, text_k=text_k, stanet_nr=p_tbl.RECNO.values.astype(np.int32), + u_w_per_m2k=alpha, text_k=text_k, stanet_nr=p_tbl.RECNO.values.astype(np.int32), stanet_id=p_tbl.STANETID.values.astype(str), v_stanet=p_tbl.VM.values, geodata=geodata, stanet_system=CLIENT_TYPES_OF_PIPES[MAIN_PIPE_TYPE], stanet_active=p_tbl.ISACTIVE.values.astype(np.bool_), @@ -798,13 +798,13 @@ def build_house_junctions(net, index_mapping, hh_types, hh_recno, house_table, m add_info["stanet_layer"] = connected_houses.LAYER.values.astype(str) # create junctions for houses that are directly connected via house pipes pp_ind = pandapipes.create_junctions( - net, len(connected_houses), np.NaN, tfluid_k=net_params["medium_temp_K"], + net, len(connected_houses), np.nan, tfluid_k=net_params["medium_temp_K"], height_m=heights_houses.astype(np.float64), geodata=geodata, in_service=houses_in_calculation, name=["house_%s" % hn for hn in connected_houses.RECNO.values], type="house", stanet_nr=connected_houses.RECNO.values, stanet_id=connected_houses.STANETID.values.astype(str), - p_stanet=connected_houses.PRECH.values if houses_in_calculation else np.NaN, + p_stanet=connected_houses.PRECH.values if houses_in_calculation else np.nan, stanet_system=CLIENT_TYPES_OF_PIPES[HOUSE_PIPE_TYPE], stanet_active=connected_houses.ISACTIVE.values.astype(np.bool_), stanet_valid=houses_in_calculation, **add_info @@ -827,13 +827,13 @@ def build_meter_junctions(net, index_mapping, hh_types, hh_recno, meter_table, n add_info["stanet_layer"] = connected_meters.LAYER.values.astype(str) # create junctions for meters that are directly connected via house pipes pp_ind = pandapipes.create_junctions( - net, len(connected_meters), np.NaN, tfluid_k=net_params["medium_temp_K"], + net, len(connected_meters), np.nan, tfluid_k=net_params["medium_temp_K"], height_m=connected_meters.GEOH.values.astype(np.float64), name=connected_meters.STANETID.values.astype(str), geodata=geodata, type="meter", stanet_nr=connected_meters.RECNO.values, stanet_id=connected_meters.STANETID.astype(str), in_service=houses_in_calculation, - p_stanet=connected_meters.PRECH.values if houses_in_calculation else np.NaN, + p_stanet=connected_meters.PRECH.values if houses_in_calculation else np.nan, stanet_system=CLIENT_TYPES_OF_PIPES[HOUSE_PIPE_TYPE], stanet_active=connected_meters.ISACTIVE.values.astype(np.bool_), stanet_valid=houses_in_calculation, **add_info @@ -853,12 +853,12 @@ def build_house_node_junctions(net, index_mapping, stored_data, net_params, hous if add_layers: add_info["stanet_layer"] = house_nodes.LAYER.values.astype(str) pp_ind = pandapipes.create_junctions( - net, len(house_node_nrs), np.NaN, tfluid_k=net_params["medium_temp_K"], + net, len(house_node_nrs), np.nan, tfluid_k=net_params["medium_temp_K"], height_m=house_nodes.GEOH.values.astype(np.float64), name=house_nodes.STANETID.values.astype(str), geodata=geodata, type="house_node", stanet_nr=house_node_nrs, stanet_id=house_nodes.STANETID.astype(str), in_service=houses_in_calculation, - p_stanet=house_nodes.PRECH.values if houses_in_calculation else np.NaN, + p_stanet=house_nodes.PRECH.values if houses_in_calculation else np.nan, stanet_system=CLIENT_TYPES_OF_PIPES[HOUSE_PIPE_TYPE], stanet_active=house_nodes.ISACTIVE.values.astype(np.bool_), stanet_valid=houses_in_calculation, **add_info @@ -1055,7 +1055,7 @@ def create_geodata_sections(row): net, hp_data.fj.values, hp_data.tj.values, hp_data.length.values / 1000, hp_data.DM.values / 1000, hp_data.RAU.values, hp_data.ZETA.values, type="house_pipe", in_service=hp_data.ISACTIVE.values if houses_in_calculation else False, text_k=text_k, - alpha_w_per_m2k=alpha, geodata=hp_data.section_geo.values, + u_w_per_m2k=alpha, geodata=hp_data.section_geo.values, name=["pipe_%s_%s_%s" % (nf, nt, sec) for nf, nt, sec in zip( hp_data.CLIENTID.values, hp_data.CLIENT2ID.values, hp_data.section_no.values)], stanet_std_type=hp_data.ROHRTYP.values, stanet_nr=hp_data.RECNO.values, @@ -1091,7 +1091,7 @@ def create_sinks_meters(net, meter_table, index_mapping, net_params, add_layers) assigned_node_nums = meter_table.KNONUM.astype(np.int32) meter_nrs = meter_table.RECNO.astype(np.int32) - junctions_assigned = pd.Series([node_mapping.get(nn, np.NaN) for nn in assigned_node_nums], + junctions_assigned = pd.Series([node_mapping.get(nn, np.nan) for nn in assigned_node_nums], index=meter_table.index, dtype=float) junctions_connected = pd.Series(index=meter_table.index, dtype=float) @@ -1110,7 +1110,7 @@ def create_sinks_meters(net, meter_table, index_mapping, net_params, add_layers) if np.any(junctions_connected.isnull()): junctions_connected.loc[junctions_connected.isnull()] = \ - [node_mapping.get(n, np.NaN) if not np.isnan(n) else np.NaN for n in + [node_mapping.get(n, np.nan) if not np.isnan(n) else np.nan for n in meter_table.KNONUM.loc[junctions_connected.isnull()].values] logger.warning("The meters %s cannot be mapped to a house connection node and will be " "assigned to nodes %s" diff --git a/src/pandapipes/converter/stanet/valve_pipe_component/create_valve_pipe.py b/src/pandapipes/converter/stanet/valve_pipe_component/create_valve_pipe.py index 8ab3fe6eb..b6c288540 100644 --- a/src/pandapipes/converter/stanet/valve_pipe_component/create_valve_pipe.py +++ b/src/pandapipes/converter/stanet/valve_pipe_component/create_valve_pipe.py @@ -11,7 +11,7 @@ def create_valve_pipe(net, from_junction, to_junction, std_type, length_km, k_mm=0.15e-3, - opened=True, loss_coefficient=0, sections=1, alpha_w_per_m2k=0., text_k=293, qext_w=0., + opened=True, loss_coefficient=0, sections=1, u_w_per_m2k=0., text_k=293, qext_w=0., name=None, index=None, geodata=None, in_service=True, type="valve_pipe", **kwargs): """ Creates a valve pipe element in net["valve_pipe"] from valve pipe parameters. In any case the @@ -42,8 +42,8 @@ def create_valve_pipe(net, from_junction, to_junction, std_type, length_km, k_mm :param sections: The number of internal pipe sections. Important for gas and temperature\ calculations, where variables are dependent on pipe length. :type sections: int, default 1 - :param alpha_w_per_m2k: Heat transfer coefficient in [W/(m^2*K)] - :type alpha_w_per_m2k: float, default 0 + :param u_w_per_m2k: Heat transfer coefficient in [W/(m^2*K)] + :type u_w_per_m2k: float, default 0 :param text_k: Ambient temperatures of pipes in [K] :type text_k: Iterable or float, default 293 :param qext_w: external heat feed-in to the pipe in [W] @@ -83,7 +83,7 @@ def create_valve_pipe(net, from_junction, to_junction, std_type, length_km, k_mm v = {"name": name, "from_junction": from_junction, "to_junction": to_junction, "std_type": std_type, "length_km": length_km, "diameter_m": pipe_parameter["inner_diameter_mm"] / 1000, "k_mm": k_mm, "opened": opened, "loss_coefficient": loss_coefficient, - "alpha_w_per_m2k": alpha_w_per_m2k, "sections": sections, "in_service": bool(in_service), "type": type, + "u_w_per_m2k": u_w_per_m2k, "sections": sections, "in_service": bool(in_service), "type": type, "qext_w": qext_w, "text_k": text_k} _set_entries(net, "valve_pipe", index, **v, **kwargs) @@ -95,7 +95,7 @@ def create_valve_pipe(net, from_junction, to_junction, std_type, length_km, k_mm def create_valve_pipe_from_parameters(net, from_junction, to_junction, length_km, diameter_m, k_mm=0.15e-3, - opened=True, loss_coefficient=0, sections=1, alpha_w_per_m2k=0., text_k=293, + opened=True, loss_coefficient=0, sections=1, u_w_per_m2k=0., text_k=293, qext_w=0., name=None, index=None, geodata=None, in_service=True, type="valve_pipe", **kwargs): """ @@ -126,8 +126,8 @@ def create_valve_pipe_from_parameters(net, from_junction, to_junction, length_km :param sections: The number of internal pipe sections. Important for gas and temperature\ calculations, where variables are dependent on pipe length. :type sections: int, default 1 - :param alpha_w_per_m2k: Heat transfer coefficient in [W/(m^2*K)] - :type alpha_w_per_m2k: float, default 0 + :param u_w_per_m2k: Heat transfer coefficient in [W/(m^2*K)] + :type u_w_per_m2k: float, default 0 :param text_k: Ambient temperatures of pipes in [K] :type text_k: Iterable or float, default 293 :param qext_w: external heat feed-in to the pipe in [W] @@ -165,7 +165,7 @@ def create_valve_pipe_from_parameters(net, from_junction, to_junction, length_km v = {"name": name, "from_junction": from_junction, "to_junction": to_junction, "length_km": length_km, "diameter_m": diameter_m, "k_mm": k_mm, "opened": opened, "loss_coefficient": loss_coefficient, - "alpha_w_per_m2k": alpha_w_per_m2k, "sections": sections, "in_service": bool(in_service), "type": type, + "u_w_per_m2k": u_w_per_m2k, "sections": sections, "in_service": bool(in_service), "type": type, "qext_w": qext_w, "text_k": text_k} _set_entries(net, "valve_pipe", index, **v, **kwargs) diff --git a/src/pandapipes/converter/stanet/valve_pipe_component/valve_pipe_component.py b/src/pandapipes/converter/stanet/valve_pipe_component/valve_pipe_component.py index 4dc085eb4..d691a68b6 100644 --- a/src/pandapipes/converter/stanet/valve_pipe_component/valve_pipe_component.py +++ b/src/pandapipes/converter/stanet/valve_pipe_component/valve_pipe_component.py @@ -69,7 +69,7 @@ def get_component_input(cls): ("max_vdot_m3_per_s", 'f8'), ("max_v_m_per_s", 'f8'), ("in_service", 'bool'), - ("alpha_w_per_m2k", 'f8'), + ("u_w_per_m2k", 'f8'), ("qext_w", 'f8'), ("type", dtype(object)), ('index', 'u4')] @@ -93,6 +93,7 @@ def get_result_table(cls, net): "p_to_bar", "t_from_k", "t_to_k", + "t_outlet_k", "p_from_mw", "p_to_mw", "mdot_from_kg_per_s", @@ -110,11 +111,12 @@ def get_result_table(cls, net): "p_to_bar", "t_from_k", "t_to_k", + "t_outlet_k", "p_from_mw", "p_to_mw", "mdot_from_kg_per_s", "mdot_to_kg_per_s", - "vdot_norm_m3_per_s", + "vdot_m3_per_s", "reynolds", "lambda", "loading_percent"] diff --git a/src/pandapipes/converter/stanet/valve_pipe_component/valve_pipe_plotting.py b/src/pandapipes/converter/stanet/valve_pipe_component/valve_pipe_plotting.py index 16592eda6..1711413d9 100644 --- a/src/pandapipes/converter/stanet/valve_pipe_component/valve_pipe_plotting.py +++ b/src/pandapipes/converter/stanet/valve_pipe_component/valve_pipe_plotting.py @@ -6,11 +6,11 @@ import numpy as np import pandas as pd -from pandapower.plotting.collections import _create_complex_branch_collection, \ - add_cmap_to_collection, coords_from_node_geodata -from pandapower.plotting.plotting_toolbox import get_index_array - from pandapipes.plotting.patch_makers import valve_patches +from pandapipes.plotting.plotting_toolbox import coords_from_node_geodata +from pandapower.plotting.collections import (_create_complex_branch_collection, + add_cmap_to_collection) +from pandapower.plotting.plotting_toolbox import get_index_array try: import pandaplan.core.pplog as logging diff --git a/src/pandapipes/create.py b/src/pandapipes/create.py index bf05b253a..dbf233f60 100644 --- a/src/pandapipes/create.py +++ b/src/pandapipes/create.py @@ -1,16 +1,18 @@ # Copyright (c) 2020-2024 by Fraunhofer Institute for Energy Economics # and Energy System Technology (IEE), Kassel, and University of Kassel. All rights reserved. # Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. +from typing import Iterable import numpy as np import pandas as pd +from pandapower.auxiliary import _preserve_dtypes +import warnings from pandapower.create import _get_multiple_index_with_check, _get_index_with_check, _set_entries, \ _check_node_element, _check_multiple_node_elements, _set_multiple_entries, \ - _add_multiple_branch_geodata, _check_branch_element, _check_multiple_branch_elements + _check_branch_element, _check_multiple_branch_elements -from pandapipes.component_models import Junction, Sink, Source, Pump, Pipe, ExtGrid, \ - HeatExchanger, Valve, CirculationPumpPressure, CirculationPumpMass, PressureControlComponent, \ - Compressor, MassStorage +from pandapipes.component_models import Junction, Sink, Source, Pump, Pipe, ExtGrid, HeatExchanger, Valve, \ + CirculationPumpPressure, CirculationPumpMass, PressureControlComponent, Compressor, MassStorage from pandapipes.component_models.component_toolbox import add_new_component from pandapipes.component_models.flow_control_component import FlowControlComponent from pandapipes.component_models.heat_consumer_component import HeatConsumer @@ -18,8 +20,7 @@ from pandapipes.properties import call_lib from pandapipes.properties.fluids import Fluid, _add_fluid_to_net from pandapipes.std_types.std_type_class import regression_function, PumpStdType -from pandapipes.std_types.std_types import add_basic_std_types, create_pump_std_type, \ - load_std_type +from pandapipes.std_types.std_types import add_basic_std_types, create_pump_std_type, load_std_type try: import pandaplan.core.pplog as logging @@ -67,8 +68,8 @@ def create_empty_network(name="", fluid=None, add_stdtypes=True): return net -def create_junction(net, pn_bar, tfluid_k, height_m=0, name=None, index=None, in_service=True, - type="junction", geodata=None, **kwargs): +def create_junction(net, pn_bar, tfluid_k, height_m=0, name=None, index=None, in_service=True, type="junction", + geodata=None, **kwargs): """ Adds one junction in table net["junction"]. Junctions are the nodes of the network that all other elements connect to. @@ -119,8 +120,8 @@ def create_junction(net, pn_bar, tfluid_k, height_m=0, name=None, index=None, in return index -def create_sink(net, junction, mdot_kg_per_s, scaling=1., name=None, index=None, in_service=True, - type='sink', **kwargs): +def create_sink(net, junction, mdot_kg_per_s, scaling=1., name=None, index=None, in_service=True, type='sink', + **kwargs): """ Adds one sink in table net["sink"]. @@ -162,8 +163,8 @@ def create_sink(net, junction, mdot_kg_per_s, scaling=1., name=None, index=None, return index -def create_source(net, junction, mdot_kg_per_s, scaling=1., name=None, index=None, in_service=True, - type='source', **kwargs): +def create_source(net, junction, mdot_kg_per_s, scaling=1., name=None, index=None, in_service=True, type='source', + **kwargs): """ Adds one source in table net["source"]. @@ -206,9 +207,8 @@ def create_source(net, junction, mdot_kg_per_s, scaling=1., name=None, index=Non return index -def create_mass_storage(net, junction, mdot_kg_per_s, init_m_stored_kg=0, min_m_stored_kg=0., - max_m_stored_kg=np.inf, scaling=1., name=None, index=None, - in_service=True, type="mass_storage", **kwargs): +def create_mass_storage(net, junction, mdot_kg_per_s, init_m_stored_kg=0, min_m_stored_kg=0., max_m_stored_kg=np.inf, + scaling=1., name=None, index=None, in_service=True, type="mass_storage", **kwargs): """ Adds one storage entry in table net["mass_storage"]. Not suitable for thermal storage tanks. @@ -262,17 +262,16 @@ def create_mass_storage(net, junction, mdot_kg_per_s, init_m_stored_kg=0, min_m_ index = _get_index_with_check(net, "mass_storage", index) - cols = ["name", "junction", "mdot_kg_per_s", "scaling", "init_m_stored_kg", "min_m_stored_kg", - "max_m_stored_kg", "in_service", "type"] - vals = [name, junction, mdot_kg_per_s, scaling, init_m_stored_kg, min_m_stored_kg, - max_m_stored_kg, bool(in_service), type] + cols = ["name", "junction", "mdot_kg_per_s", "scaling", "init_m_stored_kg", "min_m_stored_kg", "max_m_stored_kg", + "in_service", "type"] + vals = [name, junction, mdot_kg_per_s, scaling, init_m_stored_kg, min_m_stored_kg, max_m_stored_kg, + bool(in_service), type] _set_entries(net, "mass_storage", index, **dict(zip(cols, vals)), **kwargs) return index -def create_ext_grid(net, junction, p_bar=None, t_k=None, type="auto", name=None, in_service=True, - index=None, **kwargs): +def create_ext_grid(net, junction, p_bar=None, t_k=None, type="auto", name=None, in_service=True, index=None, **kwargs): """ Creates an external grid and adds it to the table net["ext_grid"]. It transfers the junction that it is connected to into a node with fixed value for either pressure, temperature or both @@ -326,8 +325,8 @@ def create_ext_grid(net, junction, p_bar=None, t_k=None, type="auto", name=None, return index -def create_heat_exchanger(net, from_junction, to_junction, diameter_m, qext_w, loss_coefficient=0, - name=None, index=None, in_service=True, type="heat_exchanger", **kwargs): +def create_heat_exchanger(net, from_junction, to_junction, qext_w, loss_coefficient=0, name=None, + index=None, in_service=True, type="heat_exchanger", **kwargs): """ Creates a heat exchanger element in net["heat_exchanger"] from heat exchanger parameters. @@ -339,8 +338,6 @@ def create_heat_exchanger(net, from_junction, to_junction, diameter_m, qext_w, l :param to_junction: ID of the junction on the other side which the heat exchanger will be\ connected with :type to_junction: int - :param diameter_m: The heat exchanger inner diameter in [m] - :type diameter_m: float :param qext_w: External heat flux in [W]. If positive, heat is derived from the network. If negative, heat is being fed into the network from a heat source. :type qext_w: float @@ -361,24 +358,26 @@ def create_heat_exchanger(net, from_junction, to_junction, diameter_m, qext_w, l :rtype: int :Example: - >>> create_heat_exchanger(net, from_junction=0, to_junction=1, - >>> diameter_m=40e-3, qext_w=2000) + >>> create_heat_exchanger(net, from_junction=0, to_junction=1, qext_w=2000) """ + if 'diameter_m' in kwargs: + logger.warning(r'diameter_m is deprecated as it has no effect on the calculation and results. Nonetheless, ' + r'it will be stored in the compoent table for postprocessing purposes by you if required.') + add_new_component(net, HeatExchanger) index = _get_index_with_check(net, "heat_exchanger", index, "heat exchanger") _check_branch(net, "Heat exchanger", index, from_junction, to_junction) v = {"name": name, "from_junction": from_junction, "to_junction": to_junction, - "diameter_m": diameter_m, "qext_w": qext_w, "loss_coefficient": loss_coefficient, - "in_service": bool(in_service), "type": type} + "qext_w": qext_w, "loss_coefficient": loss_coefficient, "in_service": bool(in_service), "type": type} _set_entries(net, "heat_exchanger", index, **v, **kwargs) return index def create_pipe(net, from_junction, to_junction, std_type, length_km, k_mm=0.2, loss_coefficient=0, - sections=1, alpha_w_per_m2k=0., text_k=293, qext_w=0., name=None, index=None, + sections=1, text_k=0, qext_w=0., name=None, index=None, geodata=None, in_service=True, type="pipe", **kwargs): """ Creates a pipe element in net["pipe"] from pipe parameters. @@ -401,10 +400,8 @@ def create_pipe(net, from_junction, to_junction, std_type, length_km, k_mm=0.2, :param sections: The number of internal pipe sections. Important for gas and temperature\ calculations, where variables are dependent on pipe length. :type sections: int, default 1 - :param alpha_w_per_m2k: Heat transfer coefficient in [W/(m^2*K)] - :type alpha_w_per_m2k: float, default 0 :param text_k: Ambient temperature of pipe in [K] - :type text_k: float, default 293 + :type text_k: float, default None, will be set equal to the net ambient temperature :param qext_w: External heat feed-in to the pipe in [W] :type qext_w: float, default 0 :param name: A name tag for this pipe @@ -436,13 +433,15 @@ def create_pipe(net, from_junction, to_junction, std_type, length_km, k_mm=0.2, _check_branch(net, "Pipe", index, from_junction, to_junction) _check_std_type(net, std_type, "pipe", "create_pipe") + if "alpha_w_per_m2k" in kwargs: + warnings.warn("The parameter alpha_w_per_m2k has been renamed to u_w_per_m2k. U is extracted from the std_type" + , DeprecationWarning) + pipe_parameter = load_std_type(net, std_type, "pipe") - v = {"name": name, "from_junction": from_junction, "to_junction": to_junction, - "std_type": std_type, "length_km": length_km, - "diameter_m": pipe_parameter["inner_diameter_mm"] / 1000, "k_mm": k_mm, - "loss_coefficient": loss_coefficient, "alpha_w_per_m2k": alpha_w_per_m2k, - "sections": sections, "in_service": bool(in_service), "type": type, "qext_w": qext_w, - "text_k": text_k} + v = {"name": name, "from_junction": from_junction, "to_junction": to_junction, "std_type": std_type, + "length_km": length_km, "diameter_m": pipe_parameter["inner_diameter_mm"] / 1000, "k_mm": k_mm, + "loss_coefficient": loss_coefficient, "u_w_per_m2k": pipe_parameter['u_w_per_m2k'], "sections": sections, + "in_service": bool(in_service), "type": type, "qext_w": qext_w, "text_k": text_k} _set_entries(net, "pipe", index, **v, **kwargs) if geodata is not None: @@ -451,10 +450,9 @@ def create_pipe(net, from_junction, to_junction, std_type, length_km, k_mm=0.2, return index -def create_pipe_from_parameters(net, from_junction, to_junction, length_km, diameter_m, k_mm=0.2, - loss_coefficient=0, sections=1, alpha_w_per_m2k=0., text_k=293, - qext_w=0., name=None, index=None, geodata=None, in_service=True, - type="pipe", **kwargs): +def create_pipe_from_parameters(net, from_junction, to_junction, length_km, diameter_m, k_mm=0.2, loss_coefficient=0, + sections=1, u_w_per_m2k=0., text_k=None, qext_w=0., name=None, index=None, + geodata=None, in_service=True, type="pipe", **kwargs): """ Creates a pipe element in net["pipe"] from pipe parameters. @@ -478,10 +476,10 @@ def create_pipe_from_parameters(net, from_junction, to_junction, length_km, diam :type sections: int, default 1 :param alpha_w_per_m2k: Heat transfer coefficient in [W/(m^2*K)] :type alpha_w_per_m2k: float, default 0 + :param text_k: Ambient temperature of pipe in [K] + :type text_k: float, default None, will be set equal to the net ambient temperature :param qext_w: external heat feed-in to the pipe in [W] :type qext_w: float, default 0 - :param text_k: Ambient temperature of pipe in [K] - :type text_k: float, default 293 :param name: A name tag for this pipe :type name: str, default None :param index: Force a specified ID if it is available. If None, the index one higher than the\ @@ -501,8 +499,7 @@ def create_pipe_from_parameters(net, from_junction, to_junction, length_km, diam :rtype: int :Example: - >>> create_pipe_from_parameters(net, from_junction=0, to_junction=1, - >>> length_km=1, diameter_m=40e-3) + >>> create_pipe_from_parameters(net, from_junction=0, to_junction=1, length_km=1, diameter_m=40e-3) """ add_new_component(net, Pipe) @@ -510,11 +507,22 @@ def create_pipe_from_parameters(net, from_junction, to_junction, length_km, diam index = _get_index_with_check(net, "pipe", index) _check_branch(net, "Pipe", index, from_junction, to_junction) + + #Check if alpha parameter was declared (Alpha has been changed to U) + if 'alpha_w_per_m2k' in kwargs: + + if u_w_per_m2k == 0: + u_w_per_m2k = kwargs['alpha_w_per_m2k'] + + warnings.warn("The parameter alpha_w_per_m2k has been renamed to u_w_per_m2k." "It will be removed in future.", + DeprecationWarning) + v = {"name": name, "from_junction": from_junction, "to_junction": to_junction, "std_type": None, "length_km": length_km, "diameter_m": diameter_m, "k_mm": k_mm, - "loss_coefficient": loss_coefficient, "alpha_w_per_m2k": alpha_w_per_m2k, + "loss_coefficient": loss_coefficient, "u_w_per_m2k": u_w_per_m2k, "sections": sections, "in_service": bool(in_service), "type": type, "qext_w": qext_w, "text_k": text_k} + if 'std_type' in kwargs: raise UserWarning('you have defined a std_type, however, using this function you can only ' 'create a pipe setting specific, individual parameters. If you want to ' @@ -527,8 +535,8 @@ def create_pipe_from_parameters(net, from_junction, to_junction, length_km, diam return index -def create_valve(net, from_junction, to_junction, diameter_m, opened=True, loss_coefficient=0, - name=None, index=None, type='valve', **kwargs): +def create_valve(net, from_junction, to_junction, diameter_m, opened=True, loss_coefficient=0, name=None, index=None, + type='valve', **kwargs): """ Creates a valve element in net["valve"] from valve parameters. @@ -566,16 +574,15 @@ def create_valve(net, from_junction, to_junction, diameter_m, opened=True, loss_ index = _get_index_with_check(net, "valve", index) _check_branch(net, "Valve", index, from_junction, to_junction) - v = {"name": name, "from_junction": from_junction, "to_junction": to_junction, - "diameter_m": diameter_m, "opened": opened, "loss_coefficient": loss_coefficient, - "type": type} + v = {"name": name, "from_junction": from_junction, "to_junction": to_junction, "diameter_m": diameter_m, + "opened": opened, "loss_coefficient": loss_coefficient, "type": type} _set_entries(net, "valve", index, **v, **kwargs) return index -def create_pump(net, from_junction, to_junction, std_type, name=None, index=None, in_service=True, - type="pump", **kwargs): +def create_pump(net, from_junction, to_junction, std_type, name=None, index=None, in_service=True, type="pump", + **kwargs): """ Adds one pump in table net["pump"]. @@ -614,17 +621,16 @@ def create_pump(net, from_junction, to_junction, std_type, name=None, index=None _check_branch(net, "Pump", index, from_junction, to_junction) _check_std_type(net, std_type, "pump", "create_pump") - v = {"name": name, "from_junction": from_junction, "to_junction": to_junction, - "std_type": std_type, "in_service": bool(in_service), "type": type} + v = {"name": name, "from_junction": from_junction, "to_junction": to_junction, "std_type": std_type, + "in_service": bool(in_service), "type": type} _set_entries(net, "pump", index, **v, **kwargs) return index -def create_pump_from_parameters(net, from_junction, to_junction, new_std_type_name, - pressure_list=None, flowrate_list=None, reg_polynomial_degree=None, - poly_coefficents=None, name=None, index=None, in_service=True, - type="pump", **kwargs): +def create_pump_from_parameters(net, from_junction, to_junction, new_std_type_name, pressure_list=None, + flowrate_list=None, reg_polynomial_degree=None, poly_coefficents=None, name=None, + index=None, in_service=True, type="pump", **kwargs): """ Adds one pump in table net["pump"]. @@ -685,8 +691,7 @@ def create_pump_from_parameters(net, from_junction, to_junction, new_std_type_na index = _get_index_with_check(net, "pump", index) _check_branch(net, "Pump", index, from_junction, to_junction) - if pressure_list is not None and flowrate_list is not None \ - and reg_polynomial_degree is not None: + if pressure_list is not None and flowrate_list is not None and reg_polynomial_degree is not None: reg_par = regression_function(flowrate_list, pressure_list, reg_polynomial_degree) pump = PumpStdType(new_std_type_name, reg_par) create_pump_std_type(net, new_std_type_name, pump) @@ -694,16 +699,15 @@ def create_pump_from_parameters(net, from_junction, to_junction, new_std_type_na pump = PumpStdType(new_std_type_name, poly_coefficents) create_pump_std_type(net, new_std_type_name, pump) - v = {"name": name, "from_junction": from_junction, "to_junction": to_junction, - "std_type": new_std_type_name, "in_service": bool(in_service), "type": type} + v = {"name": name, "from_junction": from_junction, "to_junction": to_junction, "std_type": new_std_type_name, + "in_service": bool(in_service), "type": type} _set_entries(net, "pump", index, **v, **kwargs) return index -def create_circ_pump_const_pressure(net, return_junction, flow_junction, p_flow_bar, plift_bar, - t_flow_k=None, type="auto", name=None, index=None, - in_service=True, **kwargs): +def create_circ_pump_const_pressure(net, return_junction, flow_junction, p_flow_bar, plift_bar, t_flow_k=None, + type="auto", name=None, index=None, in_service=True, **kwargs): """ Adds one circulation pump with a constant pressure lift in table net["circ_pump_pressure"]. \n A circulation pump is a component that sets the pressure at its outlet (flow junction) and @@ -755,24 +759,20 @@ def create_circ_pump_const_pressure(net, return_junction, flow_junction, p_flow_ add_new_component(net, CirculationPumpPressure) - index = _get_index_with_check(net, "circ_pump_pressure", index, - name="circulation pump with constant pressure") - _check_branch(net, "circulation pump with constant pressure", index, return_junction, - flow_junction) + index = _get_index_with_check(net, "circ_pump_pressure", index, name="circulation pump with constant pressure") + _check_branch(net, "circulation pump with constant pressure", index, return_junction, flow_junction) type = _auto_ext_grid_type(p_flow_bar, t_flow_k, type, CirculationPumpPressure) - v = {"name": name, "return_junction": return_junction, "flow_junction": flow_junction, - "p_flow_bar": p_flow_bar, "t_flow_k": t_flow_k, "plift_bar": plift_bar, "type": type, - "in_service": bool(in_service)} + v = {"name": name, "return_junction": return_junction, "flow_junction": flow_junction, "p_flow_bar": p_flow_bar, + "t_flow_k": t_flow_k, "plift_bar": plift_bar, "type": type, "in_service": bool(in_service)} _set_entries(net, "circ_pump_pressure", index, **v, **kwargs) return index -def create_circ_pump_const_mass_flow(net, return_junction, flow_junction, p_flow_bar, - mdot_flow_kg_per_s, t_flow_k=None, type="auto", name=None, - index=None, in_service=True, **kwargs): +def create_circ_pump_const_mass_flow(net, return_junction, flow_junction, p_flow_bar, mdot_flow_kg_per_s, t_flow_k=None, + type="auto", name=None, index=None, in_service=True, **kwargs): """ Adds one circulation pump with a constant mass flow in table net["circ_pump_mass"].\n A circulation pump is a component that sets the pressure at its outlet (flow junction) and @@ -823,23 +823,20 @@ def create_circ_pump_const_mass_flow(net, return_junction, flow_junction, p_flow add_new_component(net, CirculationPumpMass) - index = _get_index_with_check(net, "circ_pump_mass", index, - name="circulation pump with constant mass flow") - _check_branch(net, "circulation pump with constant mass flow", index, return_junction, - flow_junction) + index = _get_index_with_check(net, "circ_pump_mass", index, name="circulation pump with constant mass flow") + _check_branch(net, "circulation pump with constant mass flow", index, return_junction, flow_junction) type = _auto_ext_grid_type(p_flow_bar, t_flow_k, type, CirculationPumpMass) - v = {"name": name, "return_junction": return_junction, "flow_junction": flow_junction, - "p_flow_bar": p_flow_bar, "t_flow_k": t_flow_k, "mdot_flow_kg_per_s": mdot_flow_kg_per_s, - "type": type, "in_service": bool(in_service)} + v = {"name": name, "return_junction": return_junction, "flow_junction": flow_junction, "p_flow_bar": p_flow_bar, + "t_flow_k": t_flow_k, "mdot_flow_kg_per_s": mdot_flow_kg_per_s, "type": type, "in_service": bool(in_service)} _set_entries(net, "circ_pump_mass", index, **v, **kwargs) return index -def create_compressor(net, from_junction, to_junction, pressure_ratio, name=None, index=None, - in_service=True, **kwargs): +def create_compressor(net, from_junction, to_junction, pressure_ratio, name=None, index=None, in_service=True, + **kwargs): """Adds a compressor with relative pressure lift to net["compressor"]. The outlet (absolute) pressure is calculated by (p_in + p_ambient) * pressure_ratio. For @@ -876,16 +873,16 @@ def create_compressor(net, from_junction, to_junction, pressure_ratio, name=None index = _get_index_with_check(net, "compressor", index) _check_branch(net, "Compressor", index, from_junction, to_junction) - v = {"name": name, "from_junction": from_junction, "to_junction": to_junction, - "pressure_ratio": pressure_ratio, "in_service": bool(in_service)} + v = {"name": name, "from_junction": from_junction, "to_junction": to_junction, "pressure_ratio": pressure_ratio, + "in_service": bool(in_service)} _set_entries(net, "compressor", index, **v, **kwargs) return index -def create_pressure_control(net, from_junction, to_junction, controlled_junction, controlled_p_bar, - control_active=True, loss_coefficient=0., name=None, index=None, - in_service=True, type="pressure_control", **kwargs): +def create_pressure_control(net, from_junction, to_junction, controlled_junction, controlled_p_bar, control_active=True, + loss_coefficient=0., name=None, index=None, in_service=True, type="pressure_control", + **kwargs): """Adds one pressure control that enforces a pressure at a specific junction. The pressure control unit creates a pressure drop / lift between the 'from' and the 'to' @@ -949,11 +946,10 @@ def create_pressure_control(net, from_junction, to_junction, controlled_junction # check if junctions exist to attach the pump to _check_branch(net, "PressureControl", index, from_junction, to_junction) - _set_entries(net, "press_control", index, name=name, from_junction=from_junction, - to_junction=to_junction, controlled_junction=controlled_junction, - control_active=bool(control_active), loss_coefficient=loss_coefficient, - controlled_p_bar=controlled_p_bar, in_service=bool(in_service), type=type, - **kwargs) + _set_entries(net, "press_control", index, name=name, from_junction=from_junction, to_junction=to_junction, + controlled_junction=controlled_junction, control_active=bool(control_active), + loss_coefficient=loss_coefficient, controlled_p_bar=controlled_p_bar, in_service=bool(in_service), + type=type, **kwargs) if controlled_junction != from_junction and controlled_junction != to_junction: logger.warning("The pressure controller %d controls the pressure at a junction that it is " @@ -964,9 +960,8 @@ def create_pressure_control(net, from_junction, to_junction, controlled_junction return index -def create_flow_control(net, from_junction, to_junction, controlled_mdot_kg_per_s, diameter_m, - control_active=True, name=None, index=None, in_service=True, type="fc", - **kwargs): +def create_flow_control(net, from_junction, to_junction, controlled_mdot_kg_per_s, control_active=True, + name=None, index=None, in_service=True, type="fc", **kwargs): """ Adds one flow control with a constant mass flow in table net["flow_control"]. @@ -980,9 +975,6 @@ def create_flow_control(net, from_junction, to_junction, controlled_mdot_kg_per_ :type to_junction: int :param controlled_mdot_kg_per_s: Mass flow set point :type controlled_mdot_kg_per_s: float - :param diameter_m: Measure of the diameter to derive the cross-sectional area (important for \ - the velocity calculation) - :type diameter_m: float :param control_active: Variable to state whether the flow control is active (otherwise \ similar to open valve) :type control_active: bool, default True @@ -1004,6 +996,9 @@ def create_flow_control(net, from_junction, to_junction, controlled_mdot_kg_per_ >>> create_flow_control(net, 0, 1, 0.5, 0.8) """ + if 'diameter_m' in kwargs: + logger.warning(r'diameter_m is deprecated as it has no effect on the calculation and results. Nonetheless, ' + r'it will be stored in the compoent table for postprocessing purposes by you if required.') add_new_component(net, FlowControlComponent) @@ -1012,17 +1007,16 @@ def create_flow_control(net, from_junction, to_junction, controlled_mdot_kg_per_ # check if junctions exist to attach the pump to _check_branch(net, "FlowControl", index, from_junction, to_junction) - _set_entries(net, "flow_control", index, name=name, from_junction=from_junction, - to_junction=to_junction, controlled_mdot_kg_per_s=controlled_mdot_kg_per_s, - diameter_m=diameter_m, control_active=bool(control_active), - in_service=bool(in_service), type=type, **kwargs) + _set_entries(net, "flow_control", index, name=name, from_junction=from_junction, to_junction=to_junction, + controlled_mdot_kg_per_s=controlled_mdot_kg_per_s, + control_active=bool(control_active), in_service=bool(in_service), type=type, **kwargs) return index -def create_heat_consumer(net, from_junction, to_junction, diameter_m, qext_w=None, - controlled_mdot_kg_per_s=None, deltat_k=None, treturn_k=None, name=None, - index=None, in_service=True, type="heat_consumer", **kwargs): +def create_heat_consumer(net, from_junction, to_junction, qext_w=None, controlled_mdot_kg_per_s=None, + deltat_k=None, treturn_k=None, name=None, index=None, in_service=True, type="heat_consumer", + **kwargs): """ Creates a heat consumer element in net["heat_consumer"] from heat consumer parameters. @@ -1034,8 +1028,6 @@ def create_heat_consumer(net, from_junction, to_junction, diameter_m, qext_w=Non :param to_junction: ID of the junction on the other side which the heat consumer will be \ connected with :type to_junction: int - :param diameter_m: The heat consumer inner diameter in [m] - only for result calculation - :type diameter_m: float :param qext_w: External heat flux in [W]. If positive, heat is extracted from the network. If \ negative, heat is being fed into the network from a heat source. :type qext_w: float, default None @@ -1064,33 +1056,32 @@ def create_heat_consumer(net, from_junction, to_junction, diameter_m, qext_w=Non >>> create_heat_consumer(net,from_junction=0, to_junction=1, diameter_m=40e-3, qext_w=20000, >>> controlled_mdot_kg_per_s=0.4, name="heat_consumer1") """ - if deltat_k is not None or treturn_k is not None: - raise NotImplementedError("The models for consumers with fixed temperature difference or " - "fixed return temperature are not implemented yet.") - if ((controlled_mdot_kg_per_s is None) + (qext_w is None) + (deltat_k is None) - + (treturn_k is None) != 2): + if 'diameter_m' in kwargs: + logger.warning(r'diameter_m is deprecated as it has no effect on the calculation and results. Nonetheless, ' + r'it will be stored in the compoent table for postprocessing purposes by you if required.') + + if ((controlled_mdot_kg_per_s is None) + (qext_w is None) + (deltat_k is None) + (treturn_k is None) != 2): raise AttributeError(r"Define exactly two varibales from 'controlled_mdot_kg_per_s', " - r"'qext_w' and 'deltat_k' or 'treturn_k' different from None") + r"'qext_w' and 'deltat_k' or 'treturn_k' different from None.") + if deltat_k is not None and treturn_k is not None: raise AttributeError(r"It is not possible to set both 'deltat_k' and 'treturn_k', as the " r"flow temperature is independent of the heat consumer model.") - add_new_component(net, HeatConsumer) index = _get_index_with_check(net, "heat_consumer", index, "heat consumer") _check_branch(net, "Heat consumer", index, from_junction, to_junction) v = {"name": name, "from_junction": from_junction, "to_junction": to_junction, - "diameter_m": diameter_m, "qext_w": qext_w, - "controlled_mdot_kg_per_s": controlled_mdot_kg_per_s, "deltat_k": deltat_k, + "qext_w": qext_w, "controlled_mdot_kg_per_s": controlled_mdot_kg_per_s, "deltat_k": deltat_k, "treturn_k": treturn_k, "in_service": bool(in_service), "type": type} _set_entries(net, "heat_consumer", index, **v, **kwargs) return index -def create_junctions(net, nr_junctions, pn_bar, tfluid_k, height_m=0, name=None, index=None, - in_service=True, type="junction", geodata=None, **kwargs): +def create_junctions(net, nr_junctions, pn_bar, tfluid_k, height_m=0, name=None, index=None, in_service=True, + type="junction", geodata=None, **kwargs): """ Convenience function for creating many junctions at once. Parameter 'nr_junctions' specifies \ the number of junctions created. Other parameters may be either arrays of length 'nr_junctions'\ @@ -1131,8 +1122,8 @@ def create_junctions(net, nr_junctions, pn_bar, tfluid_k, height_m=0, name=None, add_new_component(net, Junction) index = _get_multiple_index_with_check(net, "junction", index, nr_junctions) - entries = {"pn_bar": pn_bar, "type": type, "tfluid_k": tfluid_k, "height_m": height_m, - "in_service": in_service, "name": name} + entries = {"pn_bar": pn_bar, "type": type, "tfluid_k": tfluid_k, "height_m": height_m, "in_service": in_service, + "name": name} _set_multiple_entries(net, "junction", index, **entries, **kwargs) if geodata is not None: @@ -1146,8 +1137,8 @@ def create_junctions(net, nr_junctions, pn_bar, tfluid_k, height_m=0, name=None, return index -def create_sinks(net, junctions, mdot_kg_per_s, scaling=1., name=None, index=None, in_service=True, - type='sink', **kwargs): +def create_sinks(net, junctions, mdot_kg_per_s, scaling=1., name=None, index=None, in_service=True, type='sink', + **kwargs): """ Convenience function for creating many sinks at once. Parameter 'junctions' must be an array \ of the desired length. Other parameters may be either arrays of the same length or single \ @@ -1184,15 +1175,15 @@ def create_sinks(net, junctions, mdot_kg_per_s, scaling=1., name=None, index=Non _check_multiple_junction_elements(net, junctions) index = _get_multiple_index_with_check(net, "sink", index, len(junctions)) - entries = {"junction": junctions, "mdot_kg_per_s": mdot_kg_per_s, "scaling": scaling, - "in_service": in_service, "name": name, "type": type} + entries = {"junction": junctions, "mdot_kg_per_s": mdot_kg_per_s, "scaling": scaling, "in_service": in_service, + "name": name, "type": type} _set_multiple_entries(net, "sink", index, **entries, **kwargs) return index -def create_sources(net, junctions, mdot_kg_per_s, scaling=1., name=None, index=None, - in_service=True, type='source', **kwargs): +def create_sources(net, junctions, mdot_kg_per_s, scaling=1., name=None, index=None, in_service=True, type='source', + **kwargs): """ Convenience function for creating many sources at once. Parameter 'junctions' must be an array \ of the desired length. Other parameters may be either arrays of the same length or single \ @@ -1229,15 +1220,14 @@ def create_sources(net, junctions, mdot_kg_per_s, scaling=1., name=None, index=N _check_multiple_junction_elements(net, junctions) index = _get_multiple_index_with_check(net, "source", index, len(junctions)) - entries = {"junction": junctions, "mdot_kg_per_s": mdot_kg_per_s, "scaling": scaling, - "in_service": in_service, "name": name, "type": type} + entries = {"junction": junctions, "mdot_kg_per_s": mdot_kg_per_s, "scaling": scaling, "in_service": in_service, + "name": name, "type": type} _set_multiple_entries(net, "source", index, **entries, **kwargs) return index -def create_ext_grids(net, junctions, p_bar, t_k, name=None, in_service=True, index=None, - type="auto", **kwargs): +def create_ext_grids(net, junctions, p_bar, t_k, name=None, in_service=True, index=None, type="auto", **kwargs): """ Convenience function for creating many external grids at once. Parameter 'junctions' must be an\ array of the desired length. Other parameters may be either arrays of the same length or single\ @@ -1286,15 +1276,14 @@ def create_ext_grids(net, junctions, p_bar, t_k, name=None, in_service=True, ind type = _auto_ext_grid_types(p_bar, t_k, type, ExtGrid) - entries = {"junction": junctions, "p_bar": p_bar, "t_k": t_k, - "in_service": in_service, "name": name, "type": type} + entries = {"junction": junctions, "p_bar": p_bar, "t_k": t_k, "in_service": in_service, "name": name, "type": type} _set_multiple_entries(net, "ext_grid", index, **entries, **kwargs) return index def create_pipes(net, from_junctions, to_junctions, std_type, length_km, k_mm=0.2, - loss_coefficient=0, sections=1, alpha_w_per_m2k=0., text_k=293, qext_w=0., + loss_coefficient=0, sections=1, u_w_per_m2k=0., text_k=None, qext_w=0., name=None, index=None, geodata=None, in_service=True, type="pipe", **kwargs): """ Convenience function for creating many pipes at once. Parameters 'from_junctions' and \ @@ -1321,10 +1310,10 @@ def create_pipes(net, from_junctions, to_junctions, std_type, length_km, k_mm=0. :param sections: The number of internal pipe sections. Important for gas and temperature\ calculations, where variables are dependent on pipe length. :type sections: Iterable or int, default 1 - :param alpha_w_per_m2k: Heat transfer coefficients in [W/(m^2*K)] - :type alpha_w_per_m2k: Iterable or float, default 0 + :param u_w_per_m2k: Heat transfer coefficients in [W/(m^2*K)] + :type u_w_per_m2k: Iterable or float, default 0 :param text_k: Ambient temperatures of pipes in [K] - :type text_k: Iterable or float, default 293 + :type text_k: Iterable or float, default None, will be set equal to the net ambient temperature :param qext_w: External heat feed-in to the pipes in [W] :type qext_w: Iterable or float, default 0 :param name: Name tags for these pipes @@ -1364,7 +1353,7 @@ def create_pipes(net, from_junctions, to_junctions, std_type, length_km, k_mm=0. entries = {"name": name, "from_junction": from_junctions, "to_junction": to_junctions, "std_type": std_type, "length_km": length_km, "diameter_m": pipe_parameters["inner_diameter_mm"] / 1000, "k_mm": k_mm, - "loss_coefficient": loss_coefficient, "alpha_w_per_m2k": alpha_w_per_m2k, + "loss_coefficient": loss_coefficient, "u_w_per_m2k": u_w_per_m2k, "sections": sections, "in_service": in_service, "type": type, "qext_w": qext_w, "text_k": text_k} _set_multiple_entries(net, "pipe", index, **entries, **kwargs) @@ -1375,7 +1364,7 @@ def create_pipes(net, from_junctions, to_junctions, std_type, length_km, k_mm=0. def create_pipes_from_parameters(net, from_junctions, to_junctions, length_km, diameter_m, k_mm=0.2, - loss_coefficient=0, sections=1, alpha_w_per_m2k=0., text_k=293, + loss_coefficient=0, sections=1, u_w_per_m2k=0., text_k=None, qext_w=0., name=None, index=None, geodata=None, in_service=True, type="pipe", **kwargs): """ @@ -1402,10 +1391,10 @@ def create_pipes_from_parameters(net, from_junctions, to_junctions, length_km, d :param sections: The number of internal pipe sections. Important for gas and temperature\ calculations, where variables are dependent on pipe length. :type sections: Iterable or int, default 1 - :param alpha_w_per_m2k: Heat transfer coefficients in [W/(m^2*K)] - :type alpha_w_per_m2k: Iterable or float, default 0 + :param u_w_per_m2k: Heat transfer coefficients in [W/(m^2*K)] + :type u_w_per_m2k: Iterable or float, default 0 :param text_k: Ambient temperatures of pipes in [K] - :type text_k: Iterable or float, default 293 + :type text_k: Iterable or float, default None, will be set equal to the net ambient temperature :param qext_w: External heat feed-in to the pipes in [W] :type qext_w: Iterable or float, default 0 :param name: Name tags for these pipes @@ -1439,11 +1428,25 @@ def create_pipes_from_parameters(net, from_junctions, to_junctions, length_km, d index = _get_multiple_index_with_check(net, "pipe", index, len(from_junctions)) _check_branches(net, from_junctions, to_junctions, "pipe") + if 'alpha_w_per_m2k' in kwargs: + + if (not isinstance(u_w_per_m2k, Iterable) and isinstance(u_w_per_m2k, float) + and u_w_per_m2k == 0.): + u_w_per_m2k = kwargs['alpha_w_per_m2k'] + + warnings.warn("The parameter alpha_w_per_m2k has been renamed to u_w_per_m2k." + "It will be removed in future.", DeprecationWarning) + entries = {"name": name, "from_junction": from_junctions, "to_junction": to_junctions, "std_type": None, "length_km": length_km, "diameter_m": diameter_m, "k_mm": k_mm, - "loss_coefficient": loss_coefficient, "alpha_w_per_m2k": alpha_w_per_m2k, + "loss_coefficient": loss_coefficient, "u_w_per_m2k": u_w_per_m2k, "sections": sections, "in_service": in_service, "type": type, "qext_w": qext_w, "text_k": text_k} + + if 'std_type' in kwargs: + raise UserWarning('you have defined a std_type, however, using this function you can only ' + 'create a pipe setting specific, individual parameters. If you want to ' + 'create a pipe from net.std_types, please use `create_pipe`') _set_multiple_entries(net, "pipe", index, **entries, **kwargs) if geodata is not None: @@ -1451,8 +1454,8 @@ def create_pipes_from_parameters(net, from_junctions, to_junctions, length_km, d return index -def create_valves(net, from_junctions, to_junctions, diameter_m, opened=True, loss_coefficient=0, - name=None, index=None, type='valve', **kwargs): +def create_valves(net, from_junctions, to_junctions, diameter_m, opened=True, loss_coefficient=0, name=None, index=None, + type='valve', **kwargs): """ Convenience function for creating many valves at once. Parameters 'from_junctions' and \ 'to_junctions' must be arrays of equal length. Other parameters may be either arrays of the \ @@ -1495,17 +1498,16 @@ def create_valves(net, from_junctions, to_junctions, diameter_m, opened=True, lo index = _get_multiple_index_with_check(net, "valve", index, len(from_junctions)) _check_branches(net, from_junctions, to_junctions, "valve") - entries = {"name": name, "from_junction": from_junctions, "to_junction": to_junctions, - "diameter_m": diameter_m, "opened": opened, "loss_coefficient": loss_coefficient, - "type": type} + entries = {"name": name, "from_junction": from_junctions, "to_junction": to_junctions, "diameter_m": diameter_m, + "opened": opened, "loss_coefficient": loss_coefficient, "type": type} _set_multiple_entries(net, "valve", index, **entries, **kwargs) return index -def create_pressure_controls(net, from_junctions, to_junctions, controlled_junctions, - controlled_p_bar, control_active=True, loss_coefficient=0., name=None, - index=None, in_service=True, type="pressure_control", **kwargs): +def create_pressure_controls(net, from_junctions, to_junctions, controlled_junctions, controlled_p_bar, + control_active=True, loss_coefficient=0., name=None, index=None, in_service=True, + type="pressure_control", **kwargs): """ Convenience function for creating many pressure controls at once. Parameters 'from_junctions'\ and 'to_junctions' must be arrays of equal length. Other parameters may be either arrays of the\ @@ -1568,12 +1570,11 @@ def create_pressure_controls(net, from_junctions, to_junctions, controlled_junct entries = {"name": name, "from_junction": from_junctions, "to_junction": to_junctions, "controlled_junction": controlled_junctions, "controlled_p_bar": controlled_p_bar, - "control_active": control_active, "loss_coefficient": loss_coefficient, - "in_service": in_service, "type": type} + "control_active": control_active, "loss_coefficient": loss_coefficient, "in_service": in_service, + "type": type} _set_multiple_entries(net, "press_control", index, **entries, **kwargs) - controlled_elsewhere = (controlled_junctions != from_junctions) \ - & (controlled_junctions != to_junctions) + controlled_elsewhere = (controlled_junctions != from_junctions) & (controlled_junctions != to_junctions) if np.any(controlled_elsewhere): controllers_warn = index[controlled_elsewhere] logger.warning("The pressure controllers %s control the pressure at junctions that they are" @@ -1584,9 +1585,8 @@ def create_pressure_controls(net, from_junctions, to_junctions, controlled_junct return index -def create_flow_controls(net, from_junctions, to_junctions, controlled_mdot_kg_per_s, diameter_m, - control_active=True, name=None, index=None, in_service=True, type="fc", - **kwargs): +def create_flow_controls(net, from_junctions, to_junctions, controlled_mdot_kg_per_s, control_active=True, + name=None, index=None, in_service=True, type="fc", **kwargs): """ Convenience function for creating many flow controls at once. Parameters 'from_junctions'\ and 'to_junctions' must be arrays of equal length. Other parameters may be either arrays of the\ @@ -1602,9 +1602,6 @@ def create_flow_controls(net, from_junctions, to_junctions, controlled_mdot_kg_p :type to_junctions: Iterable(int) :param controlled_mdot_kg_per_s: Mass flow set points :type controlled_mdot_kg_per_s: Iterable or float - :param diameter_m: Measure of the diameter to derive the cross-sectional area (important for \ - the velocity calculation) - :type diameter_m: Iterable or float :param control_active: Variable to state whether the flow control is active (otherwise \ similar to open valve) :type control_active: bool, default True @@ -1623,12 +1620,15 @@ def create_flow_controls(net, from_junctions, to_junctions, controlled_mdot_kg_p :rtype: array(int) :Example: - Create two flow controllers with 0.8 m diameter between junction 0 and 1 with 0.5 kg/s and + Create two flow controllers between junction 0 and 1 with 0.5 kg/s and junction 2 and 4 with 0.9 kg/s, respectively. - >>> create_flow_controls(net, [0, 2], [1, 4], [0.5, 0.9], [0.8, 0.8]) + >>> create_flow_controls(net, [0, 2], [1, 4], [0.5, 0.9]) """ + if 'diameter_m' in kwargs: + logger.warning(r'diameter_m is deprecated as it has no effect on the calculation and results. Nonetheless, ' + r'it will be stored in the compoent table for postprocessing purposes by you if required.') add_new_component(net, FlowControlComponent) @@ -1636,16 +1636,15 @@ def create_flow_controls(net, from_junctions, to_junctions, controlled_mdot_kg_p _check_branches(net, from_junctions, to_junctions, "flow_control") entries = {"name": name, "from_junction": from_junctions, "to_junction": to_junctions, - "controlled_mdot_kg_per_s": controlled_mdot_kg_per_s, "diameter_m": diameter_m, + "controlled_mdot_kg_per_s": controlled_mdot_kg_per_s, "control_active": control_active, "in_service": in_service, "type": type} _set_multiple_entries(net, "flow_control", index, **entries, **kwargs) return index -def create_heat_exchangers(net, from_junctions, to_junctions, diameter_m, qext_w, - loss_coefficient=0, name=None, index=None, in_service=True, - type="heat_exchanger", **kwargs): +def create_heat_exchangers(net, from_junctions, to_junctions, qext_w, loss_coefficient=0, name=None, + index=None, in_service=True, type="heat_exchanger", **kwargs): """ Convenience function for creating many heat exchangers at once. Parameters 'from_junctions'\ and 'to_junctions' must be arrays of equal length. Other parameters may be either arrays of the\ @@ -1659,8 +1658,6 @@ def create_heat_exchangers(net, from_junctions, to_junctions, diameter_m, qext_w :param to_junctions: IDs of the junctions on the other side the heat exchangers will be\ connected with :type to_junctions: Iterable(int) - :param diameter_m: The heat exchangers inner diameter in [m] - :type diameter_m: Iterable(float) or float :param qext_w: External heat flux in [W]. If positive, heat is derived from the network. If negative, heat is being fed into the network from a heat source. :type qext_w: Iterable(float) or float @@ -1683,25 +1680,27 @@ def create_heat_exchangers(net, from_junctions, to_junctions, diameter_m, qext_w :rtype: Iterable(int), default None :Example: - >>> create_heat_exchangers(net, from_junctions=[0,1], to_junctions=[2,3], - >>> diameter_m=40e-3, qext_w=2000) + >>> create_heat_exchangers(net, from_junctions=[0,1], to_junctions=[2,3], qext_w=2000) """ + if 'diameter_m' in kwargs: + logger.warning(r'diameter_m is deprecated as it has no effect on the calculation and results. Nonetheless, ' + r'it will be stored in the component table for postprocessing purposes by you if required.') + add_new_component(net, HeatExchanger) index = _get_multiple_index_with_check(net, "heat_exchanger", index, len(from_junctions)) _check_branches(net, from_junctions, to_junctions, "heat_exchanger") entries = {"name": name, "from_junction": from_junctions, "to_junction": to_junctions, - "diameter_m": diameter_m, "qext_w": qext_w, "loss_coefficient": loss_coefficient, - "in_service": bool(in_service), "type": type} + "qext_w": qext_w, "loss_coefficient": loss_coefficient, "in_service": bool(in_service), "type": type} _set_multiple_entries(net, "heat_exchanger", index, **entries, **kwargs) return index -def create_heat_consumers(net, from_junctions, to_junctions, diameter_m, qext_w=None, - controlled_mdot_kg_per_s=None, deltat_k=None, treturn_k=None, - name=None, index=None, in_service=True, type="heat_consumer", **kwargs): +def create_heat_consumers(net, from_junctions, to_junctions, qext_w=None, controlled_mdot_kg_per_s=None, + deltat_k=None, treturn_k=None, name=None, index=None, in_service=True, type="heat_consumer", + **kwargs): """ Creates several heat consumer elements in net["heat_consumer"] from heat consumer parameters. @@ -1713,8 +1712,6 @@ def create_heat_consumers(net, from_junctions, to_junctions, diameter_m, qext_w= :param to_junctions: IDs of the junctions on the other side which the heat consumers will be \ connected with :type to_junctions: Iterable(int) - :param diameter_m: The heat consumers' inner diameter in [m] - only for result calculation - :type diameter_m: Iterable(float) or float :param qext_w: External heat flux in [W]. If positive, heat is extracted from the network. If \ negative, heat is being fed into the network from a heat source. :type qext_w: Iterable(float) or float, default None @@ -1741,12 +1738,12 @@ def create_heat_consumers(net, from_junctions, to_junctions, diameter_m, qext_w= :rtype: int :Example: - >>> create_heat_consumers(net,from_junctions=[0, 3], to_junctions=[1, 5], diameter_m=40e-3, + >>> create_heat_consumers(net,from_junctions=[0, 3], to_junctions=[1, 5], >>> qext_w=20000, controlled_mdot_kg_per_s=[0.5, 0.9]) """ - if np.any(pd.notnull(deltat_k)) or np.any(pd.notnull(treturn_k)): - raise NotImplementedError("The models for consumers with fixed temperature difference or " - "fixed return temperature are not implemented yet.") + if 'diameter_m' in kwargs: + logger.warning(r'diameter_m is deprecated as it has no effect on the calculation and results. Nonetheless, ' + r'it will be stored in the compoent table for postprocessing purposes by you if required.') check_vars = [controlled_mdot_kg_per_s, qext_w, deltat_k, treturn_k] var_sums = np.zeros([4, len(from_junctions)]) for i, cv in enumerate(check_vars): @@ -1765,8 +1762,7 @@ def create_heat_consumers(net, from_junctions, to_junctions, diameter_m, qext_w= _check_branches(net, from_junctions, to_junctions, "heat_consumer") entries = {"name": name, "from_junction": from_junctions, "to_junction": to_junctions, - "diameter_m": diameter_m, "qext_w": qext_w, - "controlled_mdot_kg_per_s": controlled_mdot_kg_per_s, "deltat_k": deltat_k, + "qext_w": qext_w, "controlled_mdot_kg_per_s": controlled_mdot_kg_per_s, "deltat_k": deltat_k, "treturn_k": treturn_k, "in_service": bool(in_service), "type": type} _set_multiple_entries(net, "heat_consumer", index, **entries, **kwargs) return index @@ -1802,13 +1798,11 @@ def _check_junction_element(net, junction): def _check_branch(net, element_name, index, from_junction, to_junction): - return _check_branch_element(net, element_name, index, from_junction, to_junction, - node_name="junction", plural="s") + return _check_branch_element(net, element_name, index, from_junction, to_junction, node_name="junction", plural="s") def _check_branches(net, from_junctions, to_junctions, table): - return _check_multiple_branch_elements(net, from_junctions, to_junctions, table, - node_name="junction", plural="s") + return _check_multiple_branch_elements(net, from_junctions, to_junctions, table, node_name="junction", plural="s") def _check_std_type(net, std_type, table, function_name): @@ -1821,6 +1815,23 @@ def _check_std_type(net, std_type, table, function_name): 'one' % (std_type, table)) +def _add_multiple_branch_geodata(net, table, geodata, index): + geo_table = f"{table}_geodata" + dtypes = net[geo_table].dtypes + df = pd.DataFrame(index=index, columns=net[geo_table].columns) + # works with single or multiple lists of coordinates + if len(geodata[0]) == 2 and not hasattr(geodata[0][0], "__iter__"): + # geodata is a single list of coordinates + df["coords"] = [geodata] * len(index) + else: + # geodata is multiple lists of coordinates + df["coords"] = geodata + + net[geo_table] = pd.concat([net[geo_table],df], sort=False) + + _preserve_dtypes(net[geo_table], dtypes) + + ALLOWED_EG_TYPES = ["auto", "t", "p", "pt", "tp"] @@ -1843,30 +1854,25 @@ def _auto_ext_grid_type(p_bar, t_k, typ, comp): p_null, t_null = p_bar is None or np.isnan(p_bar), t_k is None or np.isnan(t_k) if p_null and t_null: - raise UserWarning("For component %s, either pressure or temperature must be defined!" - % comp.__name__) + raise UserWarning("For component %s, either pressure or temperature must be defined!" % comp.__name__) if typ not in ALLOWED_EG_TYPES: logger.warning("The type for component %s was %s, but must be one of the following for " "correct model implementation: %s." % (comp.__name__, typ, ALLOWED_EG_TYPES)) if typ not in ["t", "auto"] and p_null: - raise UserWarning("The type %s for component %s requires a pressure as input!" - % (typ, comp.__name__)) + raise UserWarning("The type %s for component %s requires a pressure as input!" % (typ, comp.__name__)) if typ not in ["p", "auto"] and t_null: - raise UserWarning("The type %s for component %s requires a temperature as input!" - % (typ, comp.__name__)) + raise UserWarning("The type %s for component %s requires a temperature as input!" % (typ, comp.__name__)) if typ != "auto" and "p" not in typ and not p_null: logger.warning("For component %s you gave a value for p, although the component is not of " - "'p'-type (type is %s), i.e. this value is probably neglected internally." - % (comp, typ)) + "'p'-type (type is %s), i.e. this value is probably neglected internally." % (comp, typ)) if typ != "auto" and "t" not in typ and not t_null: logger.warning("For component %s you gave a value for t, although the component is not of " - "'t'-type (type is %s), i.e. this value is probably neglected internally." - % (comp, typ)) + "'t'-type (type is %s), i.e. this value is probably neglected internally." % (comp, typ)) if typ == "tp": logger.warning("The type 'tp' is replaced by type 'pt' (might be mistaken internally).") @@ -1910,8 +1916,7 @@ def _auto_ext_grid_types(p_bar, t_k, typ, comp): if not any([p_arr, t_arr, typ_arr]): return _auto_ext_grid_type(p_bar, t_k, typ, comp) else: - lengths = np.array([len(arr) for arr, it in zip([p_bar, t_k, typ], [p_arr, t_arr, typ_arr]) - if it]) + lengths = np.array([len(arr) for arr, it in zip([p_bar, t_k, typ], [p_arr, t_arr, typ_arr]) if it]) if not np.array_equal(lengths[1:], lengths[:-1]): raise UserWarning("The arrays for p_bar, t_k and type must have equal length!") length = lengths[0] @@ -1940,8 +1945,8 @@ def _auto_ext_grid_types(p_bar, t_k, typ, comp): pos_not_allowed_types = np.where(not_allowed_types) overview = pd.DataFrame({"Position": pos_not_allowed_types, "Type": typ_not_allowed_types}) logger.warning("Please check the following types for component %s, as they must be one of " - "the following for correct model implementation: %s. \n%s" - % (comp.__name__, ALLOWED_EG_TYPES, overview)) + "the following for correct model implementation: %s. \n%s" % ( + comp.__name__, ALLOWED_EG_TYPES, overview)) p_types = np.isin(typ, [tp for tp in ALLOWED_EG_TYPES if tp not in ["t", "auto"]]) t_types = np.isin(typ, [tp for tp in ALLOWED_EG_TYPES if tp not in ["p", "auto"]]) @@ -1964,8 +1969,7 @@ def _auto_ext_grid_types(p_bar, t_k, typ, comp): ununsed_p = ~auto_types & ~p_null & ~p_types if np.any(ununsed_p): - overview = pd.DataFrame({"Positions": np.where(ununsed_p)[0], - "Type": np.array(typ)[ununsed_p], + overview = pd.DataFrame({"Positions": np.where(ununsed_p)[0], "Type": np.array(typ)[ununsed_p], "p_value": np.array(p_bar)[ununsed_p]}) logger.warning("For component %s you gave a value for p in some cases, although the " "respective components are not of 'p'-type, i.e. the given values are " @@ -1973,8 +1977,7 @@ def _auto_ext_grid_types(p_bar, t_k, typ, comp): ununsed_t = ~auto_types & ~t_null & ~t_types if np.any(ununsed_t): - overview = pd.DataFrame({"Positions": np.where(ununsed_t)[0], - "Type": np.array(typ)[ununsed_t], + overview = pd.DataFrame({"Positions": np.where(ununsed_t)[0], "Type": np.array(typ)[ununsed_t], "t_value": np.array(p_bar)[ununsed_t]}) logger.warning("For component %s you gave a value for t in some cases, although the " "respective components are not of 't'-type, i.e. the given values are " diff --git a/src/pandapipes/idx_branch.py b/src/pandapipes/idx_branch.py index eab984599..58cc0f9ff 100644 --- a/src/pandapipes/idx_branch.py +++ b/src/pandapipes/idx_branch.py @@ -3,42 +3,50 @@ # Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. # branch types -# no types defined +CIRC = 1 # Circ pump branch +PC = 2 # Pressure controller branch # branch indices TABLE_IDX = 0 # number of the table that this branch belongs to ELEMENT_IDX = 1 # index of the element that this branch belongs to (within the given table) -FROM_NODE = 2 # f, from bus number -TO_NODE = 3 # t, to bus number -ACTIVE = 4 -LENGTH = 5 # Pipe length in [m] -D = 6 # Diameter in [m] -AREA = 7 # Area in [m²] -K = 8 # Pipe roughness in [m] -MDOTINIT = 9 # mass in [m/s] -RE = 10 # Reynolds number -LAMBDA = 11 # Lambda -JAC_DERIV_DM = 12 # Slot for the derivative by mass -JAC_DERIV_DP = 13 # Slot for the derivative by pressure from_node -JAC_DERIV_DP1 = 14 # Slot for the derivative by pressure to_node -LOAD_VEC_BRANCHES = 15 # Slot for the load vector for the branches -JAC_DERIV_DM_NODE = 16 # Slot for the derivative by mass for the nodes connected to branch -LOAD_VEC_NODES = 17 # Slot for the load vector of the nodes connected to branch -LOSS_COEFFICIENT = 18 -ALPHA = 19 # Slot for heat transfer coefficient -JAC_DERIV_DT = 20 -JAC_DERIV_DTOUT = 21 -LOAD_VEC_BRANCHES_T = 22 -TOUTINIT = 23 # Internal slot for outlet pipe temperature -JAC_DERIV_DT_NODE = 24 # Slot for the derivative fpr T for the nodes connected to branch -LOAD_VEC_NODES_T = 25 -MDOTINIT_T = 26 -FROM_NODE_T = 27 -TO_NODE_T = 28 -QEXT = 29 # heat input in [W] -TEXT = 30 -PL = 31 -TL = 32 # Temperature lift [K] -BRANCH_TYPE = 33 # branch type relevant for the pressure controller +BRANCH_TYPE = 2 # branch type relevant for the pressure controller +PUMP_TYPE = 3 +FROM_NODE = 4 # f, from bus number +TO_NODE = 5 # t, to bus number +ACTIVE = 6 +LENGTH = 7 # Pipe length in [m] +D = 8 # Diameter in [m] +AREA = 9 # Area in [m²] +K = 10 # Pipe roughness in [m] +RE = 11 # Reynolds number +LAMBDA = 12 # Lambda +LOSS_COEFFICIENT = 13 +ALPHA = 14 # Slot for heat transfer coefficient +QEXT = 15 # heat input into the branch [W] +TEXT = 16 # temperature of surrounding [K] +PL = 17 # Pressure lift [bar] +TL = 18 # Temperature lift [K] -branch_cols = 34 +MDOTINIT = 19 # mass in [m/s] +MDOTINIT_T = 20 +FROM_NODE_T_SWITCHED = 21 # flag to indicate if the from and to node are switched in the thermal calculation +TOUTINIT = 22 # Internal slot for outlet pipe temperature + +JAC_DERIV_DM = 23 # Slot for the derivative by mass +JAC_DERIV_DP = 24 # Slot for the derivative by pressure from_node +JAC_DERIV_DP1 = 25 # Slot for the derivative by pressure to_node +JAC_DERIV_DM_NODE = 26 # Slot for the derivative by mass for the nodes connected to branch +LOAD_VEC_BRANCHES = 27 # Slot for the load vector for the branches +LOAD_VEC_NODES_FROM = 28 # Slot for the load vector of the from nodes connected to branch +LOAD_VEC_NODES_TO = 29 # Slot for the load vector of the to nodes connected to branch + + +JAC_DERIV_DT = 30 +JAC_DERIV_DTOUT = 31 +JAC_DERIV_DT_NODE = 32 # Slot for the node equation derivative of T for the nodes branch is connected to +JAC_DERIV_DTOUT_NODE = 33 # Slot for the node equation derivative of T for the corresponding branch +LOAD_VEC_BRANCHES_T = 34 +LOAD_VEC_NODES_FROM_T = 35 # Slot for the load vector of the from nodes connected to branch +LOAD_VEC_NODES_TO_T = 36 # Slot for the load vector of the to nodes connected to branch + +branch_cols = 37 diff --git a/src/pandapipes/idx_node.py b/src/pandapipes/idx_node.py index c4394f80b..194fbba91 100644 --- a/src/pandapipes/idx_node.py +++ b/src/pandapipes/idx_node.py @@ -5,23 +5,28 @@ # node types P = 1 # Reference node, pressure is fixed L = 2 # All other nodes -T = 10 # Reference node with fixed temperature, otherwise 0 -PC = 20 # Controlled node with fixed pressure p -NONE = 3 # None +T = 3 # Reference node with fixed temperature, otherwise 0 +PC = 4 # Controlled node with fixed pressure p # node indices TABLE_IDX = 0 # number of the table that this node belongs to ELEMENT_IDX = 1 # index of the element that this node belongs to (within the given table) NODE_TYPE = 2 # junction type -ACTIVE = 3 -PINIT = 4 -LOAD = 5 -HEIGHT = 6 -TINIT = 7 -PAMB = 8 # Ambient pressure in [bar] -LOAD_T = 9 # Heat power drawn in [W] -NODE_TYPE_T = 10 -EXT_GRID_OCCURENCE = 11 -EXT_GRID_OCCURENCE_T = 12 +NODE_TYPE_T = 3 +ACTIVE = 4 +HEIGHT = 5 +PAMB = 6 # Ambient pressure in [bar] +LOAD = 7 +LOAD_T = 8 # Heat power drawn in [W] +EXT_GRID_OCCURENCE = 9 +EXT_GRID_OCCURENCE_T = 10 +INFEED = 11 +VAR_MASS_SLACK = 12 #required as slack do not necesseraly allow mass different from zero -node_cols = 13 +PINIT = 13 +MDOTSLACKINIT = 14 +TINIT = 15 + +JAC_DERIV_MSL = 16 + +node_cols = 17 \ No newline at end of file diff --git a/src/pandapipes/io/convert_format.py b/src/pandapipes/io/convert_format.py index 07136dc08..becd8ffc1 100644 --- a/src/pandapipes/io/convert_format.py +++ b/src/pandapipes/io/convert_format.py @@ -45,6 +45,9 @@ def _rename_columns(net): else: net['controller'].drop('controller', inplace=True, axis=1) net["controller"].rename(columns={"controller": "object"}, inplace=True) + if "pipe" in net: + if "u_w_per_m2k" not in net["pipe"].columns: + net["pipe"].rename(columns={"alpha_w_per_m2k": "u_w_per_m2k"}, inplace=True) for comp in [CirculationPumpMass, CirculationPumpPressure]: cp_tbl = comp.table_name() if cp_tbl in net: diff --git a/src/pandapipes/io/file_io.py b/src/pandapipes/io/file_io.py index d50b59f10..40ab3b5b4 100644 --- a/src/pandapipes/io/file_io.py +++ b/src/pandapipes/io/file_io.py @@ -5,17 +5,16 @@ import json import os import pickle -from functools import partial from pandapower.io_utils import PPJSONEncoder, to_dict_with_coord_transform, \ get_raw_data_from_pickle, transform_net_with_df_and_geo, PPJSONDecoder -from pandapower.io_utils import pp_hook, encrypt_string, decrypt_string +from pandapower.io_utils import encrypt_string, decrypt_string from pandapipes.io.convert_format import convert_format from pandapipes.io.io_utils import isinstance_partial, FromSerializableRegistryPpipe from pandapipes.pandapipes_net import pandapipesNet from pandapipes.multinet import MultiNet -from pandapower import pandapowerNet +from pandapower.auxiliary import pandapowerNet from pandapower.convert_format import convert_format as convert_format_pandapower diff --git a/src/pandapipes/multinet/control/run_control_multinet.py b/src/pandapipes/multinet/control/run_control_multinet.py index a68c94c21..1d69ed775 100644 --- a/src/pandapipes/multinet/control/run_control_multinet.py +++ b/src/pandapipes/multinet/control/run_control_multinet.py @@ -6,7 +6,7 @@ import pandas as pd import pandapipes as ppipes -import pandapower as pp +from pandapower.auxiliary import pandapowerNet from pandapipes.control.run_control import prepare_run_ctrl as prepare_run_ctrl_ppipes from pandapower.control.run_control import prepare_run_ctrl as prepare_run_ctrl_pp, \ net_initialization, get_recycle, control_initialization, control_finalization, \ @@ -219,7 +219,7 @@ def prepare_ctrl_variables_for_net(multinet, net_name, ctrl_variables, **kwargs) net = multinet['nets'][net_name] if isinstance(net, ppipes.pandapipesNet): ctrl_variables_net = prepare_run_ctrl_ppipes(net, None, **kwargs) - elif isinstance(net, pp.pandapowerNet): + elif isinstance(net, pandapowerNet): ctrl_variables_net = prepare_run_ctrl_pp(net, None, **kwargs) else: raise ValueError('the given nets are neither pandapipes nor pandapower nets') diff --git a/src/pandapipes/multinet/multinet.py b/src/pandapipes/multinet/multinet.py index 6468bb5f6..cc50fa448 100644 --- a/src/pandapipes/multinet/multinet.py +++ b/src/pandapipes/multinet/multinet.py @@ -6,8 +6,7 @@ import pandas as pd from numpy import dtype -from pandapower import pandapowerNet -from pandapower.auxiliary import ADict +from pandapower.auxiliary import ADict, pandapowerNet from pandapipes import __version__ from pandapipes import pandapipesNet diff --git a/src/pandapipes/pf/build_system_matrix.py b/src/pandapipes/pf/build_system_matrix.py index 1ca2b272c..5f0217e1b 100644 --- a/src/pandapipes/pf/build_system_matrix.py +++ b/src/pandapipes/pf/build_system_matrix.py @@ -3,15 +3,19 @@ # Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. import numpy as np -from pandapipes.idx_branch import FROM_NODE, TO_NODE, JAC_DERIV_DM, JAC_DERIV_DP, JAC_DERIV_DP1, \ - JAC_DERIV_DM_NODE, LOAD_VEC_NODES, LOAD_VEC_BRANCHES, JAC_DERIV_DT, JAC_DERIV_DTOUT, \ - JAC_DERIV_DT_NODE, LOAD_VEC_NODES_T, LOAD_VEC_BRANCHES_T, FROM_NODE_T, TO_NODE_T, BRANCH_TYPE -from pandapipes.idx_node import LOAD, TINIT -from pandapipes.idx_node import P, PC, NODE_TYPE, T, NODE_TYPE_T -from pandapipes.pf.internals_toolbox import _sum_by_group_sorted, _sum_by_group -from pandapipes.pf.pipeflow_setup import get_net_option from scipy.sparse import csr_matrix +from pandapipes.idx_branch import (FROM_NODE, TO_NODE, JAC_DERIV_DM, JAC_DERIV_DP, JAC_DERIV_DP1, \ + JAC_DERIV_DM_NODE, LOAD_VEC_NODES_FROM, LOAD_VEC_NODES_TO, LOAD_VEC_BRANCHES, JAC_DERIV_DT, JAC_DERIV_DTOUT, + CIRC, PC as PC_BRANCH, JAC_DERIV_DT_NODE, JAC_DERIV_DTOUT_NODE, LOAD_VEC_NODES_FROM_T, LOAD_VEC_NODES_TO_T, \ + LOAD_VEC_BRANCHES_T, BRANCH_TYPE) + +from pandapipes.idx_node import (P, PC as PC_NODE, NODE_TYPE, T, NODE_TYPE_T, LOAD, LOAD_T, INFEED, + MDOTSLACKINIT, JAC_DERIV_MSL) +from pandapipes.pf.internals_toolbox import _sum_by_group_sorted, _sum_by_group, \ + get_from_nodes_corrected, get_to_nodes_corrected +from pandapipes.pf.pipeflow_setup import get_net_option + def build_system_matrix(net, branch_pit, node_pit, heat_mode): """ @@ -30,128 +34,185 @@ def build_system_matrix(net, branch_pit, node_pit, heat_mode): """ update_option = get_net_option(net, "only_update_hydraulic_matrix") update_only = update_option and "hydraulic_data_sorting" in net["_internal_data"] \ - and "hydraulic_matrix" in net["_internal_data"] + and "hydraulic_matrix" in net["_internal_data"] use_numba = get_net_option(net, "use_numba") len_b = len(branch_pit) len_n = len(node_pit) branch_matrix_indices = np.arange(len_b) + len_n - fn_col, tn_col, ntyp_col, slack_type, pc_type, num_der = \ - (FROM_NODE, TO_NODE, NODE_TYPE, P, PC, 3) \ - if not heat_mode else (FROM_NODE_T, TO_NODE_T, NODE_TYPE_T, T, PC, 2) - pc_nodes = np.where(node_pit[:, ntyp_col] == pc_type)[0] - fn = branch_pit[:, fn_col].astype(np.int32) - tn = branch_pit[:, tn_col].astype(np.int32) - not_slack_fn_branch_mask = node_pit[fn, ntyp_col] != slack_type - not_slack_tn_branch_mask = node_pit[tn, ntyp_col] != slack_type - pc_branch_mask = branch_pit[:, BRANCH_TYPE] == pc_type + ntyp_col, slack_type, pcn_type, pcb_type, branch_type, num_der = \ + (NODE_TYPE, P, PC_NODE, PC_BRANCH, BRANCH_TYPE, 3) \ + if not heat_mode else (NODE_TYPE_T, T, None, None, BRANCH_TYPE, 2) + pc_nodes = np.where(node_pit[:, ntyp_col] == pcn_type)[0] + + if not heat_mode: + fn = branch_pit[:, FROM_NODE].astype(np.int32) + tn = branch_pit[:, TO_NODE].astype(np.int32) + else: + fn = get_from_nodes_corrected(branch_pit) + tn = get_to_nodes_corrected(branch_pit) + pc_branch_mask = branch_pit[:, branch_type] == pcb_type slack_nodes = np.where(node_pit[:, ntyp_col] == slack_type)[0] pc_matrix_indices = branch_matrix_indices[pc_branch_mask] + # size of the matrix if not heat_mode: + len_sl = len(slack_nodes) + slack_mass_matrix_indices = np.arange(len_sl) + len_b + len_n + slack_masses_from, slack_branches_from = np.where(branch_pit[:, FROM_NODE] == slack_nodes[:, None]) + slack_masses_to, slack_branches_to = np.where(branch_pit[:, TO_NODE] == slack_nodes[:, None]) + not_slack_fn_branch_mask = node_pit[fn, ntyp_col] != slack_type + not_slack_tn_branch_mask = node_pit[tn, ntyp_col] != slack_type len_fn_not_slack = np.sum(not_slack_fn_branch_mask) len_tn_not_slack = np.sum(not_slack_tn_branch_mask) len_fn1 = num_der * len_b + len_fn_not_slack len_tn1 = len_fn1 + len_tn_not_slack len_pc = len_tn1 + pc_nodes.shape[0] - full_len = len_pc + slack_nodes.shape[0] + len_slack = len_pc + slack_nodes.shape[0] + len_fsb = len_slack + len(slack_branches_from) + len_tsb = len_fsb + len(slack_branches_to) + full_len = len_tsb + slack_nodes.shape[0] else: - inc_flow_sum = np.zeros(len(node_pit[:, LOAD])) - tn_unique_der, tn_sums_der = _sum_by_group(use_numba, tn, branch_pit[:, JAC_DERIV_DT_NODE]) - inc_flow_sum[tn_unique_der] += tn_sums_der - len_fn1 = num_der * len_b + len(tn_unique_der) - len_tn1 = len_fn1 + len_b - full_len = len_tn1 + slack_nodes.shape[0] + len_sl = 0 + not_slack_branch_mask = branch_pit[:, branch_type] != CIRC + len_tn_not_slack = np.sum(not_slack_branch_mask) + infeed_node = np.arange(len_n)[node_pit[:, INFEED].astype(np.bool_)] + len_tn1 = num_der * len_b + len_tn_not_slack + len_tn2 = len_tn1 + len_tn_not_slack + full_len = len_tn2 + slack_nodes.shape[0] system_data = np.zeros(full_len, dtype=np.float64) + # entries in the matrix if not heat_mode: - # pdF_dv + + # branch equations + # ---------------- + # branch_dF_dm system_data[:len_b] = branch_pit[:, JAC_DERIV_DM] - # pdF_dpi + # branch_dF_dp_from system_data[len_b:2 * len_b] = branch_pit[:, JAC_DERIV_DP] - # pdF_dpi1 + # branch_dF_dp_to system_data[2 * len_b:3 * len_b] = branch_pit[:, JAC_DERIV_DP1] - # jdF_dv_from_nodes + + # node equations + # -------------- + # from_node_dF_dm system_data[3 * len_b:len_fn1] = branch_pit[not_slack_fn_branch_mask, JAC_DERIV_DM_NODE] * (-1) - # jdF_dv_to_nodes + # to_node_dF_dm system_data[len_fn1:len_tn1] = branch_pit[not_slack_tn_branch_mask, JAC_DERIV_DM_NODE] - # pc_nodes and p_nodes - system_data[len_tn1:] = 1 + + # fixed pressure equations + # ------------------------ + # pc_nodes and slack_nodes + system_data[len_tn1:len_slack] = 1 + + # mass flow slack equation + # -------------- + # from_slack_dF_dm + system_data[len_slack:len_fsb] = branch_pit[slack_branches_from, JAC_DERIV_DM_NODE] * (-1) + # to_slack_dF_dm + system_data[len_fsb:len_tsb] = branch_pit[slack_branches_to, JAC_DERIV_DM_NODE] + # slackmass_dF_dmslack + system_data[len_tsb:] = node_pit[slack_nodes, JAC_DERIV_MSL] else: + + # branch equations + # ---------------- + # branch_dF_dT_from system_data[:len_b] = branch_pit[:, JAC_DERIV_DT] - # pdF_dpi1 + # branch_dF_dT_out system_data[len_b:2 * len_b] = branch_pit[:, JAC_DERIV_DTOUT] - # jdF_dv_from_nodes - system_data[2 * len_b:len_fn1] = inc_flow_sum[tn_unique_der] - # jdF_dv_to_nodes - data = branch_pit[:, JAC_DERIV_DT_NODE] * (-1) - rows = tn - index = np.argsort(rows) - data = data[index] - system_data[len_fn1:len_fn1 + len_b] = data - system_data[len_fn1 + len_b:] = 1 + # node equations + # -------------- + # node_dF_dT_to + system_data[2 * len_b:len_tn1] = branch_pit[not_slack_branch_mask, JAC_DERIV_DT_NODE] + # node_dF_dT_out + system_data[len_tn1:len_tn2] = branch_pit[not_slack_branch_mask, JAC_DERIV_DTOUT_NODE] + + # fixed temperature equations + # --------------------------- + # t_nodes + system_data[len_tn2:] = 1 + + # position in the matrix if not update_only: system_cols = np.zeros(full_len, dtype=np.int32) system_rows = np.zeros(full_len, dtype=np.int32) if not heat_mode: - # pdF_dv + + # branch equations + # ---------------- + # branch_dF_dm system_cols[:len_b] = branch_matrix_indices system_rows[:len_b] = branch_matrix_indices - - # pdF_dpi + # branch_dF_dp_from system_cols[len_b:2 * len_b] = fn system_rows[len_b:2 * len_b] = branch_matrix_indices - - # pdF_dpi1 + # branch_dF_dp_to system_cols[2 * len_b:3 * len_b] = tn system_rows[2 * len_b:3 * len_b] = branch_matrix_indices - # jdF_dv_from_nodes + # node equations + # -------------- + # from_node_dF_dm system_cols[3 * len_b:len_fn1] = branch_matrix_indices[not_slack_fn_branch_mask] system_rows[3 * len_b:len_fn1] = fn[not_slack_fn_branch_mask] - - # jdF_dv_to_nodes + # to_node_dF_dm system_cols[len_fn1:len_tn1] = branch_matrix_indices[not_slack_tn_branch_mask] system_rows[len_fn1:len_tn1] = tn[not_slack_tn_branch_mask] + # fixed pressure equations + # ----------------------- # pc_nodes system_cols[len_tn1:len_pc] = pc_nodes system_rows[len_tn1:len_pc] = pc_matrix_indices + # slack_nodes + system_cols[len_pc:len_slack] = slack_nodes + system_rows[len_pc:len_slack] = slack_nodes + + # mass flow slack equation + # -------------- + # from_slack_dF_dm + system_cols[len_slack:len_fsb] = branch_matrix_indices[slack_branches_from] + system_rows[len_slack:len_fsb] = slack_mass_matrix_indices[slack_masses_from] + # to_slack_dF_dm + system_cols[len_fsb:len_tsb] = branch_matrix_indices[slack_branches_to] + system_rows[len_fsb:len_tsb] = slack_mass_matrix_indices[slack_masses_to] + # slackmass_dF_dmslack + system_cols[len_tsb:] = slack_mass_matrix_indices + system_rows[len_tsb:] = slack_mass_matrix_indices - # p_nodes - system_cols[len_pc:] = slack_nodes - system_rows[len_pc:] = slack_nodes else: - # pdF_dTfromnode + # branch equations + # ---------------- + # branch_dF_dT_from system_cols[:len_b] = fn system_rows[:len_b] = branch_matrix_indices - - # pdF_dTout + # branch_dF_dT_out system_cols[len_b:2 * len_b] = branch_matrix_indices system_rows[len_b:2 * len_b] = branch_matrix_indices - # t_nodes - system_cols[len_fn1 + len_b:] = slack_nodes - system_rows[len_fn1 + len_b:] = np.arange(0, len(slack_nodes)) - - # jdF_dTnode_ - tn_unique_idx = np.unique(tn, return_index=True) - system_cols[2 * len_b:len_fn1] = tn_unique_idx[0] - system_rows[2 * len_b:len_fn1] = len(slack_nodes) + np.arange(0, len(tn_unique_der)) + # node equations + # -------------- + # node_dF_dT_to + system_cols[2 * len_b:len_tn1] = tn[not_slack_branch_mask] + system_rows[2 * len_b:len_tn1] = tn[not_slack_branch_mask] + # node_dF_dT_out + system_cols[len_tn1:len_tn2] = branch_matrix_indices[not_slack_branch_mask] + system_rows[len_tn1:len_tn2] = tn[not_slack_branch_mask] - # jdF_dTout - branch_order = np.argsort(tn) - tn_uni, tn_uni_counts = np.unique(tn[branch_order], return_counts=True) - row_index = np.repeat(np.arange(len(tn_uni)), tn_uni_counts) - system_cols[len_fn1:len_fn1 + len_b] = branch_matrix_indices[branch_order] - system_rows[len_fn1:len_fn1 + len_b] = len(slack_nodes) + row_index + # fixed temperature equations + # --------------------------- + # t_nodes (overwrites only infeeding nodes' equation) + system_cols[len_tn2:] = slack_nodes + system_rows[len_tn2:] = infeed_node if not update_option: system_matrix = csr_matrix((system_data, (system_rows, system_cols)), - shape=(len_n + len_b, len_n + len_b)) + shape=(len_n + len_b + len_sl, len_n + len_b + len_sl)) else: data_order = np.lexsort([system_cols, system_rows]) @@ -159,12 +220,12 @@ def build_system_matrix(net, branch_pit, node_pit, heat_mode): system_cols = system_cols[data_order] system_rows = system_rows[data_order] - row_counter = np.zeros(len_b + len_n + 1, dtype=np.int32) + row_counter = np.zeros(len_b + len_n + len_sl + 1, dtype=np.int32) unique_rows, row_counts = _sum_by_group_sorted(system_rows, np.ones_like(system_rows)) row_counter[unique_rows + 1] += row_counts ptr = row_counter.cumsum() system_matrix = csr_matrix((system_data, system_cols, ptr), - shape=(len_n + len_b, len_n + len_b)) + shape=(len_n + len_b + len_sl, len_n + len_b + len_sl)) net["_internal_data"]["hydraulic_data_sorting"] = data_order net["_internal_data"]["hydraulic_matrix"] = system_matrix else: @@ -173,24 +234,36 @@ def build_system_matrix(net, branch_pit, node_pit, heat_mode): system_matrix = net["_internal_data"]["hydraulic_matrix"] system_matrix.data = system_data + # load vector on the right side if not heat_mode: - load_vector = np.empty(len_n + len_b) - load_vector[len_n:] = branch_pit[:, LOAD_VEC_BRANCHES] + load_vector = np.empty(len_n + len_b + len_sl) + load_vector[len_n:len_b + len_n] = branch_pit[:, LOAD_VEC_BRANCHES] load_vector[:len_n] = node_pit[:, LOAD] * (-1) - fn_unique, fn_sums = _sum_by_group(use_numba, fn, branch_pit[:, LOAD_VEC_NODES]) - tn_unique, tn_sums = _sum_by_group(use_numba, tn, branch_pit[:, LOAD_VEC_NODES]) + fn_unique, fn_sums = _sum_by_group(use_numba, fn, branch_pit[:, LOAD_VEC_NODES_FROM]) + tn_unique, tn_sums = _sum_by_group(use_numba, tn, branch_pit[:, LOAD_VEC_NODES_TO]) load_vector[fn_unique] -= fn_sums load_vector[tn_unique] += tn_sums load_vector[slack_nodes] = 0 load_vector[pc_matrix_indices] = 0 + + load_vector[slack_mass_matrix_indices] = node_pit[slack_nodes, LOAD] * (-1) + fsb_unique, fsb_sums = _sum_by_group(use_numba, slack_masses_from, + branch_pit[slack_branches_from, LOAD_VEC_NODES_FROM]) + tsb_unique, tsb_sums = _sum_by_group(use_numba, slack_masses_to, + branch_pit[slack_branches_to, LOAD_VEC_NODES_TO]) + load_vector[slack_mass_matrix_indices[fsb_unique]] -= fsb_sums + load_vector[slack_mass_matrix_indices[tsb_unique]] += tsb_sums + load_vector[slack_mass_matrix_indices] -= node_pit[slack_nodes, MDOTSLACKINIT] else: - tn_unique, tn_sums = _sum_by_group(use_numba, tn, branch_pit[:, LOAD_VEC_NODES_T]) load_vector = np.zeros(len_n + len_b) - load_vector[len(slack_nodes) + np.arange(0, len(tn_unique_der))] += tn_sums - load_vector[len(slack_nodes) + np.arange(0, len(tn_unique_der))] -= tn_sums_der * node_pit[ - tn_unique_der, TINIT] - load_vector[0:len(slack_nodes)] = 0. - load_vector[len_n:] = branch_pit[:, LOAD_VEC_BRANCHES_T] + load_vector[:len_n] = node_pit[:, LOAD_T] * (-1) + # This approach can be used if you consider the effect of sources with given temperature + # fn_unique, fn_sums = _sum_by_group(use_numba, fn, branch_pit[:, LOAD_VEC_NODES_FROM_T]) + fn_unique, fn_sums = _sum_by_group(use_numba, tn, branch_pit[:, LOAD_VEC_NODES_FROM_T]) + tn_unique, tn_sums = _sum_by_group(use_numba, tn, branch_pit[:, LOAD_VEC_NODES_TO_T]) + load_vector[fn_unique] -= fn_sums + load_vector[tn_unique] += tn_sums + load_vector[infeed_node] = 0 return system_matrix, load_vector diff --git a/src/pandapipes/pf/derivative_calculation.py b/src/pandapipes/pf/derivative_calculation.py index 1d006c4e8..922f5b09b 100644 --- a/src/pandapipes/pf/derivative_calculation.py +++ b/src/pandapipes/pf/derivative_calculation.py @@ -1,13 +1,16 @@ import numpy as np +from pandapipes.constants import NORMAL_TEMPERATURE from pandapipes.idx_branch import LENGTH, D, K, RE, LAMBDA, LOAD_VEC_BRANCHES, \ - JAC_DERIV_DM, JAC_DERIV_DP, JAC_DERIV_DP1, LOAD_VEC_NODES, JAC_DERIV_DM_NODE, \ - FROM_NODE, TO_NODE, FROM_NODE_T, TOUTINIT, TEXT, AREA, ALPHA, TL, QEXT, LOAD_VEC_NODES_T, \ - LOAD_VEC_BRANCHES_T, JAC_DERIV_DT, JAC_DERIV_DTOUT, JAC_DERIV_DT_NODE, MDOTINIT, MDOTINIT_T -from pandapipes.idx_node import TINIT as TINIT_NODE + JAC_DERIV_DM, JAC_DERIV_DP, JAC_DERIV_DP1, LOAD_VEC_NODES_FROM, LOAD_VEC_NODES_TO, JAC_DERIV_DM_NODE, \ + FROM_NODE, TO_NODE, TOUTINIT, TEXT, AREA, ALPHA, TL, QEXT, LOAD_VEC_NODES_FROM_T, LOAD_VEC_NODES_TO_T,\ + LOAD_VEC_BRANCHES_T, JAC_DERIV_DT, JAC_DERIV_DTOUT, JAC_DERIV_DTOUT_NODE, \ + JAC_DERIV_DT_NODE, MDOTINIT, BRANCH_TYPE, CIRC +from pandapipes.idx_node import TINIT as TINIT_NODE, INFEED +from pandapipes.pf.internals_toolbox import get_from_nodes_corrected, get_to_nodes_corrected from pandapipes.properties.fluids import get_fluid -from pandapipes.constants import NORMAL_TEMPERATURE -from pandapipes.properties.properties_toolbox import get_branch_real_density, get_branch_real_eta, get_branch_cp +from pandapipes.properties.properties_toolbox import get_branch_real_density, get_branch_real_eta, \ + get_branch_cp def calculate_derivatives_hydraulic(net, branch_pit, node_pit, options): @@ -29,7 +32,6 @@ def calculate_derivatives_hydraulic(net, branch_pit, node_pit, options): friction_model = options["friction_model"] rho = get_branch_real_density(fluid, node_pit, branch_pit) eta = get_branch_real_eta(fluid, node_pit, branch_pit) - rho_n = fluid.get_density([NORMAL_TEMPERATURE] * len(branch_pit)) lambda_, re = calc_lambda( branch_pit[:, MDOTINIT], eta, branch_pit[:, D], @@ -51,8 +53,9 @@ def calculate_derivatives_hydraulic(net, branch_pit, node_pit, options): from pandapipes.pf.derivative_toolbox import derivatives_hydraulic_incomp_np \ as derivatives_hydraulic_incomp - load_vec, load_vec_nodes, df_dm, df_dm_nodes, df_dp, df_dp1 = derivatives_hydraulic_incomp( - branch_pit, der_lambda, p_init_i_abs, p_init_i1_abs, height_difference, rho, rho_n) + load_vec, load_vec_nodes_from, load_vec_nodes_to, df_dm, df_dm_nodes, df_dp, df_dp1 = ( + derivatives_hydraulic_incomp( + branch_pit, der_lambda, p_init_i_abs, p_init_i1_abs, height_difference, rho)) else: if options["use_numba"]: from pandapipes.pf.derivative_toolbox_numba import derivatives_hydraulic_comp_numba \ @@ -63,44 +66,70 @@ def calculate_derivatives_hydraulic(net, branch_pit, node_pit, options): as derivatives_hydraulic_comp, calc_medium_pressure_with_derivative_np as \ calc_medium_pressure_with_derivative p_m, der_p_m, der_p_m1 = calc_medium_pressure_with_derivative(p_init_i_abs, p_init_i1_abs) + rho_n = np.full(len(branch_pit), fluid.get_density(NORMAL_TEMPERATURE)) comp_fact = fluid.get_compressibility(p_m) # TODO: this might not be required der_comp = fluid.get_der_compressibility() * der_p_m der_comp1 = fluid.get_der_compressibility() * der_p_m1 - load_vec, load_vec_nodes, df_dm, df_dm_nodes, df_dp, df_dp1 = derivatives_hydraulic_comp( + load_vec, load_vec_nodes_from, load_vec_nodes_to, df_dm, df_dm_nodes, df_dp, df_dp1 = ( + derivatives_hydraulic_comp( node_pit, branch_pit, lambda_, der_lambda, p_init_i_abs, p_init_i1_abs, height_difference, - comp_fact, der_comp, der_comp1, rho, rho_n) + comp_fact, der_comp, der_comp1, rho, rho_n)) branch_pit[:, LOAD_VEC_BRANCHES] = load_vec branch_pit[:, JAC_DERIV_DM] = df_dm branch_pit[:, JAC_DERIV_DP] = df_dp branch_pit[:, JAC_DERIV_DP1] = df_dp1 - branch_pit[:, LOAD_VEC_NODES] = load_vec_nodes + branch_pit[:, LOAD_VEC_NODES_FROM] = load_vec_nodes_from + branch_pit[:, LOAD_VEC_NODES_TO] = load_vec_nodes_to branch_pit[:, JAC_DERIV_DM_NODE] = df_dm_nodes -def calculate_derivatives_thermal(net, branch_pit, node_pit, options): +def calculate_derivatives_thermal(net, branch_pit, node_pit, _): + node_pit[:, INFEED] = False fluid = get_fluid(net) - cp = get_branch_cp(net, fluid, node_pit, branch_pit) - m_init = branch_pit[:, MDOTINIT_T] - from_nodes = branch_pit[:, FROM_NODE_T].astype(np.int32) + cp = get_branch_cp(fluid, node_pit, branch_pit) + m_init_i = np.abs(branch_pit[:, MDOTINIT]) + m_init_i1 = np.abs(branch_pit[:, MDOTINIT]) + from_nodes = get_from_nodes_corrected(branch_pit) + to_nodes = get_to_nodes_corrected(branch_pit) t_init_i = node_pit[from_nodes, TINIT_NODE] t_init_i1 = branch_pit[:, TOUTINIT] + t_init_n = node_pit[to_nodes, TINIT_NODE] + cp_n = fluid.get_heat_capacity(t_init_n) + cp_i1 = fluid.get_heat_capacity(t_init_i1) t_amb = branch_pit[:, TEXT] length = branch_pit[:, LENGTH] alpha = branch_pit[:, ALPHA] * np.pi * branch_pit[:, D] tl = branch_pit[:, TL] qext = branch_pit[:, QEXT] t_m = (t_init_i1 + t_init_i) / 2 + m_m = (m_init_i + m_init_i1) / 2 + no_cp = branch_pit[:, BRANCH_TYPE] != CIRC + infeed_node = np.setdiff1d(from_nodes[no_cp], to_nodes[no_cp]) + + branch_pit[:, JAC_DERIV_DT] = - cp * m_m + alpha / 2 * length + branch_pit[:, JAC_DERIV_DTOUT] = cp * m_m + alpha / 2 * length + branch_pit[:, LOAD_VEC_BRANCHES_T] = cp * m_m * (-t_init_i + t_init_i1 - tl) - alpha * ( + t_amb - t_m) * length + qext + + branch_pit[:, JAC_DERIV_DT_NODE] = - m_init_i * cp_n + branch_pit[:, JAC_DERIV_DTOUT_NODE] = m_init_i1 * cp_i1 + branch_pit[:, LOAD_VEC_NODES_FROM_T] = m_init_i1 * t_init_n * cp_n + branch_pit[:, LOAD_VEC_NODES_TO_T] = m_init_i1 * t_init_i1 * cp_i1 - branch_pit[:, LOAD_VEC_BRANCHES_T] = \ - -(cp * m_init * (-t_init_i + t_init_i1 - tl) - alpha * (t_amb - t_m) * length + qext) + # This approach can be used if you consider the effect of sources with given temperature (checkout issue #656) - branch_pit[:, JAC_DERIV_DT] = - cp * m_init + alpha / 2 * length - branch_pit[:, JAC_DERIV_DTOUT] = cp * m_init + alpha / 2 * length + # branch_pit[:, LOAD_VEC_NODES_FROM_T] = m_init_i * t_init_i * cp_i + # --> cp_i is calculated by fluid.get_heat_capacity(t_init_i) + # branch_pit[:, LOAD_VEC_NODES_TO_T] = m_init_i1 * t_init_i1 * cp_i1 + # --> still missing is the derivative of loads + # t_init = node_pit[:, TINIT_NODE] + # cp_n = fluid.get_heat_capacity(t_init) + # node_pit[:, LOAD_T] = cp_n * node_pit[:, LOAD] * t_init - branch_pit[:, JAC_DERIV_DT_NODE] = m_init - branch_pit[:, LOAD_VEC_NODES_T] = m_init * t_init_i1 + node_pit[:, INFEED] = False + node_pit[infeed_node, INFEED] = True def get_derived_values(node_pit, from_nodes, to_nodes, use_numba): diff --git a/src/pandapipes/pf/derivative_toolbox.py b/src/pandapipes/pf/derivative_toolbox.py index 394078198..d627560f3 100644 --- a/src/pandapipes/pf/derivative_toolbox.py +++ b/src/pandapipes/pf/derivative_toolbox.py @@ -13,13 +13,16 @@ def derivatives_hydraulic_incomp_np(branch_pit, der_lambda, p_init_i_abs, p_init_i1_abs, - height_difference, rho, rho_n): + height_difference, rho): + # Formulas for pressure loss in incompressible flow + # Use medium density ((rho_from + rho_to) / 2) for Darcy Weisbach according to + # https://www.schweizer-fn.de/rohr/rohrleitung/rohrleitung.php#fluessigkeiten m_init_abs = np.abs(branch_pit[:, MDOTINIT]) m_init2 = m_init_abs * branch_pit[:, MDOTINIT] p_diff = p_init_i_abs - p_init_i1_abs const_height = rho * GRAVITATION_CONSTANT * height_difference / P_CONVERSION friction_term = np.divide(branch_pit[:, LENGTH] * branch_pit[:, LAMBDA], branch_pit[:, D]) + branch_pit[:, LC] - const_term = np.divide(1, branch_pit[:, AREA] ** 2 * rho_n * P_CONVERSION * 2) + const_term = np.divide(1, branch_pit[:, AREA] ** 2 * rho * P_CONVERSION * 2) df_dm = - const_term * (2 * m_init_abs * friction_term + der_lambda * np.divide(branch_pit[:, LENGTH], branch_pit[:, D]) * m_init2) @@ -31,9 +34,10 @@ def derivatives_hydraulic_incomp_np(branch_pit, der_lambda, p_init_i_abs, p_init df_dm_nodes = np.ones_like(der_lambda) - load_vec_nodes = branch_pit[:, MDOTINIT] + load_vec_nodes_from = branch_pit[:, MDOTINIT] + load_vec_nodes_to = branch_pit[:, MDOTINIT] - return load_vec, load_vec_nodes, df_dm, df_dm_nodes, df_dp, df_dp1 + return load_vec, load_vec_nodes_from, load_vec_nodes_to, df_dm, df_dm_nodes, df_dp, df_dp1 def derivatives_hydraulic_comp_np(node_pit, branch_pit, lambda_, der_lambda, p_init_i_abs, p_init_i1_abs, @@ -62,8 +66,11 @@ def derivatives_hydraulic_comp_np(node_pit, branch_pit, lambda_, der_lambda, p_i - normal_term * comp_fact * m_init2 * friction_term * p_sum_div * tm df_dm_nodes = np.ones_like(lambda_) - load_vec_nodes = branch_pit[:, MDOTINIT] - return load_vec, load_vec_nodes, df_dm, df_dm_nodes, df_dp, df_dp1 + + load_vec_nodes_from = branch_pit[:, MDOTINIT] + load_vec_nodes_to = branch_pit[:, MDOTINIT] + + return load_vec, load_vec_nodes_from, load_vec_nodes_to, df_dm, df_dm_nodes, df_dp, df_dp1 def calc_lambda_nikuradse_incomp_np(m, d, k, eta, area): diff --git a/src/pandapipes/pf/derivative_toolbox_numba.py b/src/pandapipes/pf/derivative_toolbox_numba.py index 5cadb5524..69be5c7fd 100644 --- a/src/pandapipes/pf/derivative_toolbox_numba.py +++ b/src/pandapipes/pf/derivative_toolbox_numba.py @@ -4,7 +4,7 @@ from pandapipes.constants import P_CONVERSION, GRAVITATION_CONSTANT, NORMAL_PRESSURE, \ NORMAL_TEMPERATURE from pandapipes.idx_branch import LENGTH, LAMBDA, D, LOSS_COEFFICIENT as LC, PL, AREA, \ - MDOTINIT, FROM_NODE, TO_NODE + MDOTINIT, FROM_NODE, TO_NODE, TOUTINIT from pandapipes.idx_node import HEIGHT, PAMB, PINIT, TINIT as TINIT_NODE try: @@ -15,15 +15,16 @@ from numpy import int32, float64, int64 -@jit((float64[:, :], float64[:], float64[:], float64[:], float64[:], float64[:], float64[:]), nopython=True, cache=False) +@jit((float64[:, :], float64[:], float64[:], float64[:], float64[:], float64[:]), nopython=True, cache=False) def derivatives_hydraulic_incomp_numba(branch_pit, der_lambda, p_init_i_abs, p_init_i1_abs, - height_difference, rho, rho_n): + height_difference, rho): le = der_lambda.shape[0] load_vec = np.zeros_like(der_lambda) df_dm = np.zeros_like(der_lambda) df_dp = np.ones_like(der_lambda) df_dp1 = np.ones_like(der_lambda) * (-1) - load_vec_nodes = np.zeros_like(der_lambda) + load_vec_nodes_from = np.zeros_like(der_lambda) + load_vec_nodes_to = np.zeros_like(der_lambda) df_dm_nodes = np.ones_like(der_lambda) for i in range(le): @@ -33,15 +34,16 @@ def derivatives_hydraulic_incomp_numba(branch_pit, der_lambda, p_init_i_abs, p_i const_height = rho[i] * GRAVITATION_CONSTANT * height_difference[i] / P_CONVERSION friction_term = np.divide(branch_pit[i][LENGTH] * branch_pit[i][LAMBDA], branch_pit[i][D]) \ + branch_pit[i][LC] - const_term = np.divide(1, branch_pit[i][AREA] ** 2 * rho_n[i] * P_CONVERSION * 2) + const_term = np.divide(1, branch_pit[i][AREA] ** 2 * rho[i] * P_CONVERSION * 2) df_dm[i] = -1. * const_term * (2 * m_init_abs * friction_term + der_lambda[i] * np.divide(branch_pit[i][LENGTH], branch_pit[i][D]) * m_init2) load_vec[i] = p_diff + branch_pit[i][PL] + const_height - const_term * m_init2 * friction_term - load_vec_nodes[i] = branch_pit[i][MDOTINIT] - return load_vec, load_vec_nodes, df_dm, df_dm_nodes, df_dp, df_dp1 + load_vec_nodes_from[i] = branch_pit[i][MDOTINIT] + load_vec_nodes_to[i] = branch_pit[i][MDOTINIT] + return load_vec, load_vec_nodes_from, load_vec_nodes_to, df_dm, df_dm_nodes, df_dp, df_dp1 @jit((float64[:, :], float64[:, :], float64[:], float64[:], float64[:], float64[:], float64[:], float64[:], @@ -53,10 +55,10 @@ def derivatives_hydraulic_comp_numba(node_pit, branch_pit, lambda_, der_lambda, df_dm = np.zeros_like(lambda_) df_dp = np.zeros_like(lambda_) df_dp1 = np.zeros_like(lambda_) - load_vec_nodes = np.zeros_like(der_lambda) + load_vec_nodes_from = np.zeros_like(der_lambda) + load_vec_nodes_to = np.zeros_like(der_lambda) df_dm_nodes = np.ones_like(der_lambda) from_nodes = branch_pit[:, FROM_NODE].astype(np.int32) - to_nodes = branch_pit[:, TO_NODE].astype(np.int32) # Formulas for gas pressure loss according to laminar version for i in range(le): @@ -67,8 +69,7 @@ def derivatives_hydraulic_comp_numba(node_pit, branch_pit, lambda_, der_lambda, p_sum = p_init_i_abs[i] + p_init_i1_abs[i] p_sum_div = np.divide(1, p_sum) fn = from_nodes[i] - tn = to_nodes[i] - tm = (node_pit[fn, TINIT_NODE] + node_pit[tn, TINIT_NODE]) / 2 + tm = (node_pit[fn, TINIT_NODE] + branch_pit[i][TOUTINIT]) / 2 const_height = rho[i] * GRAVITATION_CONSTANT * height_difference[i] / P_CONVERSION friction_term = np.divide(lambda_[i] * branch_pit[i][LENGTH], branch_pit[i][D]) + \ @@ -86,8 +87,9 @@ def derivatives_hydraulic_comp_numba(node_pit, branch_pit, lambda_, der_lambda, df_dm[i] = -1. * normal_term * comp_fact[i] * p_sum_div * tm * (2 * m_init_abs * friction_term \ + np.divide(der_lambda[i] * branch_pit[i][LENGTH] * m_init2, branch_pit[i][D])) - load_vec_nodes[i] = branch_pit[i][MDOTINIT] - return load_vec, load_vec_nodes, df_dm, df_dm_nodes, df_dp, df_dp1 + load_vec_nodes_from[i] = branch_pit[i][MDOTINIT] + load_vec_nodes_to[i] = branch_pit[i][MDOTINIT] + return load_vec, load_vec_nodes_from, load_vec_nodes_to, df_dm, df_dm_nodes, df_dp, df_dp1 @jit((float64[:], float64[:], float64[:], float64[:], float64[:]), nopython=True) diff --git a/src/pandapipes/pf/internals_toolbox.py b/src/pandapipes/pf/internals_toolbox.py index 8e094476f..ddc7e3d08 100644 --- a/src/pandapipes/pf/internals_toolbox.py +++ b/src/pandapipes/pf/internals_toolbox.py @@ -4,6 +4,9 @@ import numpy as np import logging + +from pandapipes.idx_branch import FROM_NODE_T_SWITCHED, TO_NODE, FROM_NODE + try: from numba import jit numba_installed = True @@ -44,7 +47,7 @@ def _sum_by_group_sorted(indices, *values): val[i] = val[i][index] still_na = nans[index] val[i][1:] = val[i][1:] - val[i][:-1] - val[i][still_na] = np.NaN + val[i][still_na] = np.nan else: np.cumsum(val[i], out=val[i]) val[i] = val[i][index] @@ -154,3 +157,47 @@ def _sum_values_by_index(indices, value_arr, max_ind, le, n_vals): @jit(nopython=True) def max_nb(arr): return np.max(arr) + + +def get_from_nodes_corrected(branch_pit, switch_from_to_col=None): + """ + Function to get corrected from nodes from the branch pit. + + Usually, this should be used if the velocity in a branch is negative, so that the\ + flow goes from the to_node to the from_node. The parameter switch_from_to_col indicates\ + whether the two columns shall be switched (for each row) or not. + + :param branch_pit: The branch pit + :type branch_pit: np.ndarray + :param switch_from_to_col: Indicates for each branch, whether to use the from (True) or \ + to (False) node. If None, the column FROM_NODE_T_SWITCHED is used. + :type switch_from_to_col: np.ndarray, default None + :return: + :rtype: + """ + if switch_from_to_col is None: + switch_from_to_col = branch_pit[:, FROM_NODE_T_SWITCHED] + from_node_col = switch_from_to_col.astype(np.int32) * (TO_NODE - FROM_NODE) + FROM_NODE + return branch_pit[np.arange(len(branch_pit)), from_node_col].astype(np.int32) + + +def get_to_nodes_corrected(branch_pit, switch_from_to_col=None): + """ + Function to get corrected to nodes from the branch pit. + + Usually, this should be used if the velocity in a branch is negative, so that the\ + flow goes from the to_node to the from_node. The parameter switch_from_to_col indicates\ + whether the two columns shall be switched (for each row) or not. + + :param branch_pit: The branch pit + :type branch_pit: np.ndarray + :param switch_from_to_col: Indicates for each branch, whether to use the from (False) or \ + to (True) node. If set to None, the column FROM_NODE_T_SWITCHED is used. + :type switch_from_to_col: np.ndarray, default None + :return: + :rtype: + """ + if switch_from_to_col is None: + switch_from_to_col = branch_pit[:, FROM_NODE_T_SWITCHED] + to_node_col = switch_from_to_col.astype(np.int32) * (FROM_NODE - TO_NODE) + TO_NODE + return branch_pit[np.arange(len(branch_pit)), to_node_col].astype(np.int32) diff --git a/src/pandapipes/pf/pipeflow_setup.py b/src/pandapipes/pf/pipeflow_setup.py index 78d33e2e8..fe1e7dcd4 100644 --- a/src/pandapipes/pf/pipeflow_setup.py +++ b/src/pandapipes/pf/pipeflow_setup.py @@ -9,10 +9,10 @@ from pandapower.auxiliary import ppException from scipy.sparse import coo_matrix, csgraph -from pandapipes.idx_branch import FROM_NODE, TO_NODE, branch_cols, \ - ACTIVE as ACTIVE_BR, MDOTINIT, FROM_NODE_T, TO_NODE_T +from pandapipes.idx_branch import FROM_NODE, TO_NODE, branch_cols, MDOTINIT, \ + ACTIVE as ACTIVE_BR from pandapipes.idx_node import NODE_TYPE, P, NODE_TYPE_T, node_cols, T, ACTIVE as ACTIVE_ND, \ - TABLE_IDX as TABLE_IDX_ND, ELEMENT_IDX as ELEMENT_IDX_ND + TABLE_IDX as TABLE_IDX_ND, ELEMENT_IDX as ELEMENT_IDX_ND, INFEED from pandapipes.pf.internals_toolbox import _sum_by_group from pandapipes.properties.fluids import get_fluid @@ -34,10 +34,10 @@ logger = logging.getLogger(__name__) default_options = {"friction_model": "nikuradse", "tol_p": 1e-5, "tol_m": 1e-5, - "tol_T": 1e-3, "tol_res": 1e-3, "max_iter_hyd": 10, "max_iter_therm": 10, + "tol_T": 1e-3, "tol_res": 1e-3, "max_iter_hyd": 10, "max_iter_therm": 10, "max_iter_bidirect": 10, "error_flag": False, "alpha": 1, "nonlinear_method": "constant", "mode": "hydraulics", - "ambient_temperature": 293, "check_connectivity": True, + "ambient_temperature": 293.15, "check_connectivity": True, "max_iter_colebrook": 10, "only_update_hydraulic_matrix": False, "reuse_internal_data": False, "use_numba": True, "quit_on_inconsistency_connectivity": False, "calc_compression_power": True} @@ -247,8 +247,8 @@ def init_options(net, local_parameters): automatically with respect to the convergence behaviour. - **mode** (str): "hydraulics" - Define the calculation mode: what shall be calculated - \ - solely hydraulics ('hydraulics'), solely heat transfer('heat') or both combined \ - ('all'). + solely hydraulics ('hydraulics'), solely heat transfer('heat') or both combined sequentially \ + ('sequential') or bidirectionally ('bidirectional'). - **only_update_hydraulic_matrix** (bool): False - If True, the system matrix is not \ created in every iteration, but only the data is updated according to a lookup that\ @@ -292,6 +292,7 @@ def init_options(net, local_parameters): # the third layer is the user defined pipeflow options if "user_pf_options" in net and len(net.user_pf_options) > 0: opts = _iteration_check(net.user_pf_options) + opts = _check_mode(opts) net["_options"].update(opts) @@ -305,6 +306,7 @@ def init_options(net, local_parameters): params[k] = v opts = _iteration_check(local_parameters["kwargs"]) + opts = _check_mode(opts) params.update(opts) net["_options"].update(params) net["_options"]["fluid"] = get_fluid(net).name @@ -322,7 +324,7 @@ def _iteration_check(opts): iter_defined = False params = dict() if 'iter' in opts: - params['max_iter_hyd'] = params['max_iter_therm'] = opts["iter"] + params['max_iter_hyd'] = params['max_iter_therm'] = params['max_iter_bidirect'] = opts["iter"] iter_defined = True if 'max_iter_hyd' in opts: max_iter_hyd = opts["max_iter_hyd"] @@ -334,9 +336,22 @@ def _iteration_check(opts): if iter_defined: logger.info("You defined 'iter' and 'max_iter_therm. " "'max_iter_therm' will overwrite 'iter'") params['max_iter_therm'] = max_iter_therm + if 'max_iter_bidirect' in opts: + max_iter_bidirect = opts["max_iter_bidirect"] + if iter_defined: logger.info("You defined 'iter' and 'max_iter_bidirect. " + "'max_iter_bidirect' will overwrite 'iter'") + params['max_iter_bidirect'] = max_iter_bidirect opts.update(params) return opts +def _check_mode(opts): + opts = copy.deepcopy(opts) + if 'mode' in opts and opts['mode'] == 'all': + logger.warning("mode 'all' is deprecated and will be removed in a future release. " + "Use 'sequential' or 'bidirectional' instead. " + "For now 'all' is set equal to 'sequential'.") + opts['mode'] = 'sequential' + return opts def create_internal_results(net): """ @@ -383,8 +398,12 @@ def initialize_pit(net): comp.create_pit_node_entries(net, pit["node"]) comp.create_pit_branch_entries(net, pit["branch"]) comp.create_component_array(net, pit["components"]) - return pit["node"], pit["branch"] + if len(pit["node"]) == 0: + logger.warning("There are no nodes defined. " + "You need at least one node! " + "Without any nodes, you are not able to conduct a pipeflow!") + return def create_empty_pit(net): """ @@ -469,7 +488,7 @@ def create_lookups(net): "internal_nodes_lookup": internal_nodes_lookup} -def identify_active_nodes_branches(net, branch_pit, node_pit, hydraulic=True): +def identify_active_nodes_branches(net, hydraulic=True): """ Function that creates the connectivity lookup for nodes and branches. If the option \ "check_connectivity" is set, a full connectivity check is performed based on a sparse matrix \ @@ -493,6 +512,10 @@ def identify_active_nodes_branches(net, branch_pit, node_pit, hydraulic=True): :type hydraulic: bool, default True :return: No output """ + + node_pit = net["_pit"]["node"] + branch_pit = net["_pit"]["branch"] + if hydraulic: # connectivity check for hydraulic simulation if get_net_option(net, "check_connectivity"): @@ -673,7 +696,7 @@ def get_table_index_list(net, pit_array, pit_indices, pit_type="node"): for tbl in tables] -def reduce_pit(net, node_pit, branch_pit, mode="hydraulics"): +def reduce_pit(net, mode="hydraulics"): """ Create an internal ("active") pit with all nodes and branches that are actually in_service. This is also done for different lookups (e.g. the from_to indices for this pit and the node index @@ -691,6 +714,10 @@ def reduce_pit(net, node_pit, branch_pit, mode="hydraulics"): :type mode: str, default "hydraulics" :return: No output """ + + node_pit = net["_pit"]["node"] + branch_pit = net["_pit"]["branch"] + active_pit = dict() els = dict() reduced_node_lookup = None @@ -730,10 +757,8 @@ def reduce_pit(net, node_pit, branch_pit, mode="hydraulics"): if reduced_node_lookup is not None: active_pit["branch"][:, FROM_NODE] = reduced_node_lookup[ branch_pit[branches_connected, FROM_NODE].astype(np.int32)] - active_pit["branch"][:, FROM_NODE_T] = active_pit["branch"][:, FROM_NODE] active_pit["branch"][:, TO_NODE] = reduced_node_lookup[ branch_pit[branches_connected, TO_NODE].astype(np.int32)] - active_pit["branch"][:, TO_NODE_T] = active_pit["branch"][:, TO_NODE] net["_active_pit"] = active_pit for el, connected_els in els.items(): @@ -748,6 +773,15 @@ def reduce_pit(net, node_pit, branch_pit, mode="hydraulics"): net["_lookups"]["%s_from_to_active_%s" % (el, mode)] = from_to_active_lookup +def check_infeed_number(node_pit): + slack_nodes = node_pit[:, NODE_TYPE_T] == T + if len(node_pit) == 1: + node_pit[slack_nodes, INFEED] = True + infeed_nodes = node_pit[:, INFEED] + if np.sum(infeed_nodes) != np.sum(slack_nodes): + raise PipeflowNotConverged(r'The number of infeeding nodes and slacks do not match') + + class PipeflowNotConverged(ppException): """ Exception being raised in case pipeflow did not converge. diff --git a/src/pandapipes/pf/result_extraction.py b/src/pandapipes/pf/result_extraction.py index 5e277608f..19e6faf06 100644 --- a/src/pandapipes/pf/result_extraction.py +++ b/src/pandapipes/pf/result_extraction.py @@ -2,11 +2,12 @@ from pandapipes.constants import NORMAL_PRESSURE, NORMAL_TEMPERATURE from pandapipes.idx_branch import ELEMENT_IDX, FROM_NODE, TO_NODE, MDOTINIT, RE, \ - LAMBDA, FROM_NODE_T, TO_NODE_T, PL, TOUTINIT, AREA + LAMBDA, PL, TOUTINIT, AREA, TEXT from pandapipes.idx_node import TABLE_IDX as TABLE_IDX_NODE, PINIT, PAMB, TINIT as TINIT_NODE from pandapipes.pf.internals_toolbox import _sum_by_group from pandapipes.pf.pipeflow_setup import get_table_number, get_lookup, get_net_option from pandapipes.properties.fluids import get_fluid +from pandapipes.properties.properties_toolbox import get_branch_real_density try: from numba import jit @@ -21,32 +22,29 @@ def extract_all_results(net, calculation_mode): :param net: pandapipes net for which to extract results into net.res_xy :type net: pandapipesNet - :param net: mode of the simulation (e.g. "hydraulics" or "heat" or "all") + :param net: mode of the simulation (e.g. "hydraulics" or "heat" or "sequential" or "bidirectional") :type net: str :return: No output """ branch_pit = net["_pit"]["branch"] node_pit = net["_pit"]["node"] - v_mps, mf, vf, from_nodes, to_nodes, temp_from, temp_to, reynolds, _lambda, p_from, p_to, pl = \ - get_basic_branch_results(net, branch_pit, node_pit) - branch_results = {"v_mps": v_mps, "mf_from": mf, "mf_to": -mf, "vf": vf, "p_from": p_from, - "p_to": p_to, "from_nodes": from_nodes, "to_nodes": to_nodes, - "temp_from": temp_from, "temp_to": temp_to, "reynolds": reynolds, - "lambda": _lambda, "pl": pl} + branch_results = get_basic_branch_results(net, branch_pit, node_pit) if get_fluid(net).is_gas: if get_net_option(net, "use_numba"): v_gas_from, v_gas_to, v_gas_mean, p_abs_from, p_abs_to, p_abs_mean, normfactor_from, \ normfactor_to, normfactor_mean = get_branch_results_gas_numba( - net, branch_pit, node_pit, from_nodes, to_nodes, v_mps, p_from, p_to) + net, branch_pit, node_pit, branch_results['from_nodes'], branch_results['to_nodes'], + branch_results['v_mps'], branch_results['p_from'], branch_results['p_to']) else: v_gas_from, v_gas_to, v_gas_mean, p_abs_from, p_abs_to, p_abs_mean, normfactor_from, \ normfactor_to, normfactor_mean = get_branch_results_gas( - net, branch_pit, node_pit, from_nodes, to_nodes, v_mps, p_from, p_to) + net, branch_pit, node_pit, branch_results['from_nodes'], branch_results['to_nodes'], + branch_results['v_mps'], branch_results['p_from'], branch_results['p_to']) gas_branch_results = { "v_gas_from": v_gas_from, "v_gas_to": v_gas_to, "v_gas_mean": v_gas_mean, - "p_from": p_from, "p_to": p_to, "p_abs_from": p_abs_from, "p_abs_to": p_abs_to, - "p_abs_mean": p_abs_mean, "normfactor_from": normfactor_from, + "p_from": branch_results['p_from'], "p_to": branch_results['p_to'], "p_abs_from": p_abs_from, + "p_abs_to": p_abs_to, "p_abs_mean": p_abs_mean, "normfactor_from": normfactor_from, "normfactor_to": normfactor_to, "normfactor_mean": normfactor_mean } branch_results.update(gas_branch_results) @@ -57,14 +55,21 @@ def extract_all_results(net, calculation_mode): def get_basic_branch_results(net, branch_pit, node_pit): from_nodes = branch_pit[:, FROM_NODE].astype(np.int32) to_nodes = branch_pit[:, TO_NODE].astype(np.int32) - fluid = get_fluid(net) t0 = node_pit[from_nodes, TINIT_NODE] t1 = node_pit[to_nodes, TINIT_NODE] - vf = branch_pit[:, MDOTINIT] / get_fluid(net).get_density(NORMAL_TEMPERATURE) - v = branch_pit[:, MDOTINIT] / fluid.get_density(NORMAL_TEMPERATURE) / branch_pit[:, AREA] - return v, branch_pit[:, MDOTINIT], vf, from_nodes, to_nodes, t0, t1, branch_pit[:, RE], \ - branch_pit[:, LAMBDA], node_pit[from_nodes, PINIT], node_pit[to_nodes, PINIT], \ - branch_pit[:, PL] + fluid = get_fluid(net) + if fluid.is_gas: + vf = branch_pit[:, MDOTINIT] / fluid.get_density(NORMAL_TEMPERATURE) + else: + vf = branch_pit[:, MDOTINIT] / get_branch_real_density(fluid, node_pit, branch_pit) + v = vf / branch_pit[:, AREA] + t_outlet = branch_pit[:, TOUTINIT] + branch_results = {"v_mps": v, "mf_from": branch_pit[:, MDOTINIT], "mf_to": -branch_pit[:, MDOTINIT], + "vf": vf, "p_from": node_pit[from_nodes, PINIT], "p_to": node_pit[to_nodes, PINIT], + "from_nodes": from_nodes, "to_nodes": to_nodes, "temp_from": t0, "temp_to": t1, + "reynolds": branch_pit[:, RE], "lambda": branch_pit[:, LAMBDA], "pl": branch_pit[:, PL], + "t_outlet": t_outlet} + return branch_results def get_branch_results_gas(net, branch_pit, node_pit, from_nodes, to_nodes, v_mps, p_from, p_to): @@ -155,7 +160,7 @@ def get_gas_vel_numba(node_pit, branch_pit, comp_from, comp_to, comp_mean, p_abs def extract_branch_results_with_internals(net, branch_results, table_name, res_nodes_from_hydraulics, res_nodes_from_heat, res_nodes_to_hydraulics, res_nodes_to_heat, - res_mean_hydraulics, res_mean_heat, node_name, + res_mean_hydraulics, res_branch_ht, res_mean_heat, node_name, simulation_mode): # the result table to write results to res_table = net["res_" + table_name] @@ -175,14 +180,14 @@ def extract_branch_results_with_internals(net, branch_results, table_name, # the id of the external node table inside the node_pit (mostly this is "junction": 0) ext_node_tbl_idx = get_table_number(get_lookup(net, "node", "table"), node_name) - for (result_mode, res_nodes_from, res_nodes_to, res_mean) in [ - ("hydraulics", res_nodes_from_hydraulics, res_nodes_to_hydraulics, res_mean_hydraulics), - ("heat", res_nodes_from_heat, res_nodes_to_heat, res_mean_heat) + for (result_mode, res_nodes_from, res_nodes_to, res_mean, res_branch) in [ + ("hydraulics", res_nodes_from_hydraulics, res_nodes_to_hydraulics, res_mean_hydraulics, []), + ("heat", res_nodes_from_heat, res_nodes_to_heat, res_mean_heat, res_branch_ht) ]: if result_mode == "hydraulics" and simulation_mode == "heat": continue lookup_name = "hydraulics" - if result_mode == "heat" and simulation_mode in ["heat", "all"]: + if result_mode == "heat" and simulation_mode in ["heat", "sequential", "bidirectional"]: lookup_name = "heat_transfer" comp_connected = get_lookup(net, "branch", "active_" + lookup_name)[f:t] for (res_ext, node_name) in ((res_nodes_from, "from_nodes"), (res_nodes_to, "to_nodes")): @@ -212,6 +217,17 @@ def extract_branch_results_with_internals(net, branch_results, table_name, for i, (res_name, entry) in enumerate(res_mean_hydraulics): res_table[res_name].values[pt] = res[i + 3][connected_ind] / num_internals + if len(res_branch) > 0: + use_numba = get_net_option(net, "use_numba") + _, sections, connected_sum = _sum_by_group(use_numba, idx_pit, np.ones_like(idx_pit), + comp_connected.astype(np.int32)) + connected_ind = connected_sum > 0.99 + indices_last_section = (np.cumsum(sections) - 1).astype(int)[connected_ind] + # hint: idx_pit[placement_table] should result in the indices as ordered in the table + pt = placement_table[connected_ind] + + for i, (res_name, entry) in enumerate(res_branch): + res_table[res_name].values[pt] = branch_results[entry][indices_last_section] def extract_branch_results_without_internals(net, branch_results, required_results_hydraulic, @@ -233,7 +249,7 @@ def extract_branch_results_without_internals(net, branch_results, required_resul :type required_results_heat: list[tuple] :param table_name: The name of the table that the results should be written to :type table_name: str - :param simulation_mode: simulation mode (e.g. "hydraulics", "heat", "all"); defines whether results from \ + :param simulation_mode: simulation mode (e.g. "hydraulics", "heat", "sequential", "bidirectional"); defines whether results from \ hydraulic or temperature calculation are transferred :type simulation_mode: str :return: No output @@ -243,7 +259,7 @@ def extract_branch_results_without_internals(net, branch_results, required_resul f, t = get_lookup(net, "branch", "from_to")[table_name] # extract hydraulic results - if simulation_mode in ["hydraulics", "all"]: + if simulation_mode in ["hydraulics", 'sequential', "bidirectional"]: # lookup for connected branch elements (hydraulic results) comp_connected_hyd = get_lookup(net, "branch", "active_hydraulics")[f:t] for res_name, entry in required_results_hydraulic: @@ -255,7 +271,7 @@ def extract_branch_results_without_internals(net, branch_results, required_resul branch_results[entry][f:t][comp_connected_hyd] # extract heat transfer results - if simulation_mode in ["heat", "all"]: + if simulation_mode in ["heat", 'sequential', "bidirectional"]: # lookup for connected branch elements (heat transfer results) comp_connected_ht = get_lookup(net, "branch", "active_heat_transfer")[f:t] for res_name, entry in required_results_heat: @@ -286,20 +302,23 @@ def extract_results_active_pit(net, mode="hydraulics"): result_branch_col = MDOTINIT if mode == "hydraulics" else TOUTINIT not_affected_branch_col = TOUTINIT if mode == "hydraulics" else MDOTINIT copied_branch_cols = np.array([i for i in range(net["_pit"]["branch"].shape[1]) - if i not in [FROM_NODE, TO_NODE, FROM_NODE_T, TO_NODE_T, + if i not in [FROM_NODE, TO_NODE, not_affected_branch_col]]) rows_branches = np.arange(net["_pit"]["branch"].shape[0])[branches_connected] - net["_pit"]["node"][~nodes_connected, result_node_col] = np.NaN + amb = get_net_option(net, 'ambient_temperature') + + net["_pit"]["node"][~nodes_connected, result_node_col] = np.nan if mode == "hydraulics" else amb net["_pit"]["node"][rows_nodes[:, np.newaxis], copied_node_cols[np.newaxis, :]] = \ net["_active_pit"]["node"][:, copied_node_cols] - net["_pit"]["branch"][~branches_connected, result_branch_col] = np.NaN + net["_pit"]["branch"][~branches_connected, result_branch_col] = np.nan if mode == "hydraulics" else \ + net["_pit"]["branch"][~branches_connected, TEXT] net["_pit"]["branch"][rows_branches[:, np.newaxis], copied_branch_cols[np.newaxis, :]] = \ net["_active_pit"]["branch"][:, copied_branch_cols] def consider_heat(mode, results=None): - consider_ = mode in ["heat", "all"] + consider_ = mode in ["heat", 'sequential', 'bidirectional'] if results is None: return consider_ return consider_ and any(r[2] for r in results) diff --git a/src/pandapipes/pipeflow.py b/src/pandapipes/pipeflow.py index 629c1cd0f..4ab146848 100644 --- a/src/pandapipes/pipeflow.py +++ b/src/pandapipes/pipeflow.py @@ -6,14 +6,17 @@ from numpy import linalg from scipy.sparse.linalg import spsolve -from pandapipes.idx_branch import FROM_NODE, TO_NODE, FROM_NODE_T, TO_NODE_T, MDOTINIT, TOUTINIT, MDOTINIT_T -from pandapipes.idx_node import PINIT, TINIT +from pandapipes.idx_branch import MDOTINIT, TOUTINIT, FROM_NODE_T_SWITCHED +from pandapipes.idx_node import PINIT, TINIT, MDOTSLACKINIT, NODE_TYPE, P from pandapipes.pf.build_system_matrix import build_system_matrix -from pandapipes.pf.derivative_calculation import calculate_derivatives_hydraulic, calculate_derivatives_thermal -from pandapipes.pf.pipeflow_setup import get_net_option, get_net_options, set_net_option, \ - init_options, create_internal_results, write_internal_results, get_lookup, create_lookups, \ - initialize_pit, reduce_pit, set_user_pf_options, init_all_result_tables, \ - identify_active_nodes_branches, PipeflowNotConverged +from pandapipes.pf.derivative_calculation import (calculate_derivatives_hydraulic, + calculate_derivatives_thermal) +from pandapipes.pf.pipeflow_setup import ( + get_net_option, get_net_options, set_net_option, init_options, create_internal_results, + write_internal_results, get_lookup, create_lookups, initialize_pit, reduce_pit, + set_user_pf_options, init_all_result_tables, identify_active_nodes_branches, check_infeed_number, + PipeflowNotConverged +) from pandapipes.pf.result_extraction import extract_all_results, extract_results_active_pit try: @@ -68,136 +71,152 @@ def pipeflow(net, sol_vec=None, **kwargs): init_all_result_tables(net) create_lookups(net) - node_pit, branch_pit = initialize_pit(net) - if len(node_pit) == 0: - logger.warning("There are no nodes defined. " - "You need at least one node! " - "Without any nodes, you are not able to conduct a pipeflow!") - return + initialize_pit(net) calculation_mode = get_net_option(net, "mode") - calculate_hydraulics = calculation_mode in ["hydraulics", "all"] - calculate_heat = calculation_mode in ["heat", "all"] - - # cannot be moved to calculate_hydraulics as the active node/branch hydraulics lookup is also required to - # determine the active node/branch heat transfer lookup - identify_active_nodes_branches(net, branch_pit, node_pit) - - if calculation_mode == "heat": - if not net.user_pf_options["hyd_flag"]: - raise UserWarning("Converged flag not set. Make sure that hydraulic calculation " - "results are available.") - else: - net["_pit"]["node"][:, PINIT] = sol_vec[:len(node_pit)] - net["_pit"]["branch"][:, MDOTINIT] = sol_vec[len(node_pit):] - - if calculate_hydraulics: - reduce_pit(net, node_pit, branch_pit, mode="hydraulics") - hydraulics(net) - if not net.converged: - raise PipeflowNotConverged("The hydraulic calculation did not converge to a solution.") - extract_results_active_pit(net, mode="hydraulics") - - if calculate_heat: - node_pit, branch_pit = net["_pit"]["node"], net["_pit"]["branch"] - identify_active_nodes_branches(net, branch_pit, node_pit, False) - reduce_pit(net, node_pit, branch_pit, mode="heat_transfer") - heat_transfer(net) - if not net.converged: - raise PipeflowNotConverged("The heat transfer calculation did not converge to a " - "solution.") - extract_results_active_pit(net, mode="heat_transfer") - elif not calculate_hydraulics: + calculate_hydraulics = calculation_mode in ["hydraulics", 'sequential'] + calculate_heat = calculation_mode in ["heat", 'sequential'] + calculate_bidrect = calculation_mode == "bidirectional" + + # cannot be moved to calculate_hydraulics as the active node/branch hydraulics lookup is also + # required to determine the active node/branch heat transfer lookup + identify_active_nodes_branches(net) + + if calculation_mode == 'heat': + use_given_hydraulic_results(net, sol_vec) + + if not (calculate_hydraulics | calculate_heat | calculate_bidrect): raise UserWarning("No proper calculation mode chosen.") + elif calculate_bidrect: + bidirectional(net) + else: + if calculate_hydraulics: + hydraulics(net) + if calculate_heat: + heat_transfer(net) extract_all_results(net, calculation_mode) -def hydraulics(net): - max_iter, nonlinear_method, tol_p, tol_m, tol_res = get_net_options( - net, "max_iter_hyd", "nonlinear_method", "tol_p", "tol_m", "tol_res") +def use_given_hydraulic_results(net, sol_vec): + node_pit = net["_pit"]["node"] + branch_pit = net["_pit"]["branch"] - # Start of nonlinear loop - # --------------------------------------------------------------------------------------------- - niter = 0 - create_internal_results(net) - if not get_net_option(net, "reuse_internal_data") or "_internal_data" not in net: - net["_internal_data"] = dict() + if not net.user_pf_options["hyd_flag"]: + raise UserWarning("Converged flag not set. Make sure that hydraulic calculation " + "results are available.") + else: + node_pit[:, PINIT] = sol_vec[:len(node_pit)] + branch_pit[:, MDOTINIT] = sol_vec[len(node_pit):] - # This branch is used to stop the solver after a specified error tolerance is reached - error_m, error_p, residual_norm = [], [], None +def newton_raphson(net, funct, mode, solver_vars, tols, pit_names, iter_name): + max_iter, nonlinear_method, tol_res = get_net_options( + net, iter_name, "nonlinear_method", "tol_res" + ) + niter = 0 + # This branch is used to stop the solver after a specified error tolerance is reached + errors = {var: [] for var in solver_vars} + create_internal_results(net) + residual_norm = None # This loop is left as soon as the solver converged while not net.converged and niter < max_iter: logger.debug("niter %d" % niter) # solve_hydraulics is where the calculation takes place - m_init, p_init, m_init_old, p_init_old, epsilon = solve_hydraulics(net) + results, residual = funct(net) + residual_norm = linalg.norm(residual / len(residual)) + logger.debug("residual: %s" % residual_norm.round(4)) + pos = np.arange(len(solver_vars) * 2) + results = np.array(results, object) + vals_new = results[pos[::2]] + vals_old = results[pos[1::2]] + for var, val_new, val_old in zip(solver_vars, vals_new, vals_old): + dval = val_new - val_old + errors[var].append(linalg.norm(dval) / len(dval) if len(dval) else 0) + finalize_iteration( + net, niter, residual_norm, nonlinear_method, errors=errors, tols=tols, tol_res=tol_res, + vals_old=vals_old, solver_vars=solver_vars, pit_names=pit_names + ) + niter += 1 + write_internal_results(net, **errors) + kwargs = dict() + kwargs['residual_norm_%s' % mode] = residual_norm + kwargs['iterations_%s' % mode] = niter + write_internal_results(net, **kwargs) + log_final_results(net, mode, niter, residual_norm, solver_vars, tols) - # Error estimation & convergence plot - dm_init = np.abs(m_init - m_init_old) - dp_init = np.abs(p_init - p_init_old) - residual_norm = linalg.norm(epsilon) / len(epsilon) - error_m.append(linalg.norm(dm_init) / len(dm_init) if len(dm_init) else 0) - error_p.append(linalg.norm(dp_init / len(dp_init))) +def bidirectional(net): + net.converged = False + if not get_net_option(net, "reuse_internal_data") or "_internal_data" not in net: + net["_internal_data"] = dict() + solver_vars = ['mdot', 'p', 'TOUT', 'T'] + tol_m, tol_p, tol_T = get_net_options(net, 'tol_m', 'tol_p', 'tol_T') + newton_raphson( + net, solve_bidirectional, 'bidirectional', solver_vars, [tol_m, tol_p, tol_T, tol_T], + ['branch', 'node', 'branch', 'node'], 'max_iter_bidirect' + ) + if net.converged: + set_user_pf_options(net, hyd_flag=True) + if not get_net_option(net, "reuse_internal_data"): + net.pop("_internal_data", None) + if not net.converged: + raise PipeflowNotConverged("The bidrectional calculation did not converge to a solution.") - finalize_iteration(net, niter, error_p, error_m, residual_norm, nonlinear_method, tol_p, - tol_m, tol_res, p_init_old, m_init_old) - niter += 1 - write_internal_results(net, iterations=niter, error_p=error_p[niter - 1], - error_m=error_m[niter - 1], residual_norm=residual_norm) +def hydraulics(net): + # Start of nonlinear loop + # --------------------------------------------------------------------------------------------- + net.converged = False + reduce_pit(net, mode="hydraulics") + if not get_net_option(net, "reuse_internal_data") or "_internal_data" not in net: + net["_internal_data"] = dict() + solver_vars = ['mdot', 'p', 'mdotslack'] + tol_p, tol_m, tol_msl = get_net_options(net, 'tol_m', 'tol_p', 'tol_m') + newton_raphson(net, solve_hydraulics, 'hydraulics', solver_vars, [tol_m, tol_p, tol_msl], + ['branch', 'node', 'node'], 'max_iter_hyd') if net.converged: set_user_pf_options(net, hyd_flag=True) - log_final_results(net, niter, residual_norm) if not get_net_option(net, "reuse_internal_data"): net.pop("_internal_data", None) + if not net.converged: + raise PipeflowNotConverged("The hydraulic calculation did not converge to a solution.") + extract_results_active_pit(net, mode="hydraulics") + def heat_transfer(net): - max_iter, nonlinear_method, tol_t, tol_res = get_net_options( - net, "max_iter_therm", "nonlinear_method", "tol_T", "tol_res") - # Start of nonlinear loop # --------------------------------------------------------------------------------------------- - + net.converged = False + identify_active_nodes_branches(net, False) + reduce_pit(net, mode="heat_transfer") if net.fluid.is_gas: logger.info("Caution! Temperature calculation does currently not affect hydraulic " "properties!") + solver_vars = ['Tout', 'T'] + tol_T = next(get_net_options(net, 'tol_T')) + newton_raphson(net, solve_temperature, 'heat', solver_vars, [tol_T, tol_T], ['branch', 'node'], + 'max_iter_therm') + if not net.converged: + raise PipeflowNotConverged("The heat transfer calculation did not converge to a " + "solution.") + extract_results_active_pit(net, mode="heat_transfer") - error_t, error_t_out, residual_norm = [], [], None - - net.converged = False - niter = 0 - - # This loop is left as soon as the solver converged - while not net.converged and niter < max_iter: - logger.debug("niter %d" % niter) - - # solve_hydraulics is where the calculation takes place - t_out, t_out_old, t_init, t_init_old, epsilon = solve_temperature(net) - - # Error estimation & convergence plot - delta_t_init = np.abs(t_init - t_init_old) - delta_t_out = np.abs(t_out - t_out_old) - - residual_norm = (linalg.norm(epsilon) / (len(epsilon))) - error_t.append(linalg.norm(delta_t_init) / (len(delta_t_init))) - error_t_out.append(linalg.norm(delta_t_out) / (len(delta_t_out))) - - finalize_iteration(net, niter, error_t, error_t_out, residual_norm, nonlinear_method, tol_t, - tol_t, tol_res, t_init_old, t_out_old, hydraulic_mode=False) - logger.debug("F: %s" % epsilon.round(4)) - logger.debug("T_init_: %s" % t_init.round(4)) - logger.debug("T_out_: %s" % t_out.round(4)) - niter += 1 - - write_internal_results(net, iterations_T=niter, error_T=error_t[niter - 1], - residual_norm_T=residual_norm) - log_final_results(net, niter, residual_norm, hyraulic_mode=False) +def solve_bidirectional(net): + reduce_pit(net, mode="hydraulics") + res_hyd, residual_hyd = solve_hydraulics(net) + extract_results_active_pit(net, mode="hydraulics") + identify_active_nodes_branches(net, False) + reduce_pit(net, mode="heat_transfer") + res_heat, residual_heat = solve_temperature(net) + extract_results_active_pit(net, mode="heat_transfer") + residual = np.concatenate([residual_hyd, residual_heat]) + res = res_hyd + res_heat + return res, residual def solve_hydraulics(net): @@ -217,22 +236,27 @@ def solve_hydraulics(net): branch_lookups = get_lookup(net, "branch", "from_to_active_hydraulics") for comp in net['component_list']: - comp.adaption_before_derivatives_hydraulic( - net, branch_pit, node_pit, branch_lookups, options) + comp.adaption_before_derivatives_hydraulic(net, branch_pit, node_pit, branch_lookups, + options) calculate_derivatives_hydraulic(net, branch_pit, node_pit, options) for comp in net['component_list']: - comp.adaption_after_derivatives_hydraulic( - net, branch_pit, node_pit, branch_lookups, options) + comp.adaption_after_derivatives_hydraulic(net, branch_pit, node_pit, branch_lookups, + options) jacobian, epsilon = build_system_matrix(net, branch_pit, node_pit, False) m_init_old = branch_pit[:, MDOTINIT].copy() p_init_old = node_pit[:, PINIT].copy() + slack_nodes = np.where(node_pit[:, NODE_TYPE] == P)[0] + msl_init_old = node_pit[slack_nodes, MDOTSLACKINIT].copy() x = spsolve(jacobian, epsilon) - branch_pit[:, MDOTINIT] -= x[len(node_pit):] + + branch_pit[:, MDOTINIT] -= x[len(node_pit):len(node_pit) + len(branch_pit)] * options["alpha"] node_pit[:, PINIT] -= x[:len(node_pit)] * options["alpha"] + node_pit[slack_nodes, MDOTSLACKINIT] -= x[len(node_pit) + len(branch_pit):] - return branch_pit[:, MDOTINIT], node_pit[:, PINIT], m_init_old, p_init_old, epsilon + return [branch_pit[:, MDOTINIT], m_init_old, node_pit[:, PINIT], p_init_old, msl_init_old, + node_pit[slack_nodes, MDOTSLACKINIT]], epsilon def solve_temperature(net): @@ -255,34 +279,29 @@ def solve_temperature(net): # Negative velocity values are turned to positive ones (including exchange of from_node and # to_node for temperature calculation - branch_pit[:, MDOTINIT_T] = branch_pit[:, MDOTINIT] - branch_pit[:, FROM_NODE_T] = branch_pit[:, FROM_NODE] - branch_pit[:, TO_NODE_T] = branch_pit[:, TO_NODE] - mask = branch_pit[:, MDOTINIT] < 0 - branch_pit[mask, MDOTINIT_T] = -branch_pit[mask, MDOTINIT] - branch_pit[mask, FROM_NODE_T] = branch_pit[mask, TO_NODE] - branch_pit[mask, TO_NODE_T] = branch_pit[mask, FROM_NODE] + branch_pit[:, FROM_NODE_T_SWITCHED] = branch_pit[:, MDOTINIT] < 0 for comp in net['component_list']: - comp.adaption_before_derivatives_thermal( - net, branch_pit, node_pit, branch_lookups, options) + comp.adaption_before_derivatives_thermal(net, branch_pit, node_pit, branch_lookups, options) calculate_derivatives_thermal(net, branch_pit, node_pit, options) for comp in net['component_list']: - comp.adaption_after_derivatives_thermal( - net, branch_pit, node_pit, branch_lookups, options) + comp.adaption_after_derivatives_thermal(net, branch_pit, node_pit, branch_lookups, options) + check_infeed_number(node_pit) + jacobian, epsilon = build_system_matrix(net, branch_pit, node_pit, True) t_init_old = node_pit[:, TINIT].copy() t_out_old = branch_pit[:, TOUTINIT].copy() x = spsolve(jacobian, epsilon) - node_pit[:, TINIT] += x[:len(node_pit)] * options["alpha"] - branch_pit[:, TOUTINIT] += x[len(node_pit):] - return branch_pit[:, TOUTINIT], t_out_old, node_pit[:, TINIT], t_init_old, epsilon + node_pit[:, TINIT] -= x[:len(node_pit)] * options["alpha"] + branch_pit[:, TOUTINIT] -= x[len(node_pit):] + return [branch_pit[:, TOUTINIT], t_out_old, node_pit[:, TINIT], t_init_old], epsilon -def set_damping_factor(net, niter, error): + +def set_damping_factor(net, niter, errors): """ Set the value of the damping factor (factor for the newton step width) from current results. @@ -290,73 +309,56 @@ def set_damping_factor(net, niter, error): :type net: pandapipesNet :param niter: :type niter: - :param error: an array containing the current residuals of all field variables solved for + :param errors: an array containing the current residuals of all field variables solved for :return: No Output. EXAMPLE: set_damping_factor(net, niter, [error_p, error_v]) """ - error_x0 = error[0] - error_x1 = error[1] - - error_x0_increased = error_x0[niter] > error_x0[niter - 1] - error_x1_increased = error_x1[niter] > error_x1[niter - 1] + error_increased = [] + for error in errors.values(): + error_increased.append(error[niter] > error[niter - 1]) current_alpha = get_net_option(net, "alpha") - - if error_x0_increased and error_x1_increased: + if np.all(error_increased): set_net_option(net, "alpha", current_alpha / 10 if current_alpha >= 0.1 else current_alpha) else: set_net_option(net, "alpha", current_alpha * 10 if current_alpha <= 0.1 else 1.0) - - return error_x0_increased, error_x1_increased + return error_increased -def finalize_iteration(net, niter, error_1, error_2, residual_norm, nonlinear_method, tol_1, tol_2, - tol_res, vals_1_old, vals_2_old, hydraulic_mode=True): - col1, col2 = (PINIT, MDOTINIT) if hydraulic_mode else (TINIT, TOUTINIT) - +def finalize_iteration(net, niter, residual_norm, nonlinear_method, errors, tols, tol_res, vals_old, + solver_vars, pit_names): # Control of damping factor if nonlinear_method == "automatic": - error_x0_increased, error_x1_increased = set_damping_factor(net, niter, - [error_1, error_2]) - if error_x0_increased: - net["_active_pit"]["node"][:, col1] = vals_1_old - if error_x1_increased: - net["_active_pit"]["branch"][:, col2] = vals_2_old + errors_increased = set_damping_factor(net, niter, errors) + logger.debug("alpha: %s" % get_net_option(net, "alpha")) + for error_increased, var, val, pit in zip(errors_increased, solver_vars, vals_old, + pit_names): + if error_increased: + # todo: not working in bidirectional mode as bidirectional is not distinguishing \ + # between hydraulics and heat transfer active pit + net["_active_pit"][pit][:, globals()[var.upper() + 'INIT']] = val + if get_net_option(net, "alpha") != 1: + net.converged = False + return elif nonlinear_method != "constant": logger.warning("No proper nonlinear method chosen. Using constant settings.") - - # Setting convergence flag - if error_2[niter] <= tol_2 and error_1[niter] <= tol_1 and residual_norm < tol_res: - if nonlinear_method != "automatic": - net.converged = True - elif get_net_option(net, "alpha") == 1: - net.converged = True - - if hydraulic_mode: - logger.debug("errorv: %s" % error_1[niter]) - logger.debug("errorp: %s" % error_2[niter]) - logger.debug("alpha: %s" % get_net_option(net, "alpha")) - else: - logger.debug("errorT: %s" % error_1[niter]) - logger.debug("alpha: %s" % get_net_option(net, "alpha")) + for error, var, tol in zip(errors.values(), solver_vars, tols): + converged = error[niter] <= tol + if not converged: break + logger.debug("error_%s: %s" % (var, error[niter])) + net.converged = converged and residual_norm <= tol_res -def log_final_results(net, niter, residual_norm, hyraulic_mode=True): - if hyraulic_mode: - solver = "hydraulics" - outputs = ["tol_p", "tol_m"] - else: - solver = "heat transfer" - outputs = ["tol_T"] +def log_final_results(net, solver, niter, residual_norm, solver_vars, tols): logger.debug("--------------------------------------------------------------------------------") if not net.converged: - logger.debug("Maximum number of iterations reached but %s solver did not converge." - % solver) + logger.debug( + "Maximum number of iterations reached but %s solver did not converge." % solver) logger.debug("Norm of residual: %s" % residual_norm) else: logger.debug("Calculation completed. Preparing results...") logger.debug("Converged after %d iterations." % niter) logger.debug("Norm of residual: %s" % residual_norm) - for out in outputs: - logger.debug("%s: %s" % (out, get_net_option(net, out))) + for var, tol in zip(solver_vars, tols): + logger.debug("tolerance for %s: %s" % (var, tol)) diff --git a/src/pandapipes/plotting/collections.py b/src/pandapipes/plotting/collections.py index 144b64d63..b05d8babf 100644 --- a/src/pandapipes/plotting/collections.py +++ b/src/pandapipes/plotting/collections.py @@ -4,12 +4,12 @@ import numpy as np import pandas as pd -from pandapower.plotting.collections import _create_node_collection, \ - _create_node_element_collection, _create_line2d_collection, _create_complex_branch_collection, \ - add_cmap_to_collection, coords_from_node_geodata -from pandapower.plotting.patch_makers import load_patches, ext_grid_patches from pandapipes.plotting.patch_makers import valve_patches, source_patches, heat_exchanger_patches, \ - pump_patches, pressure_control_patches, compressor_patches, flow_control_patches + pump_patches, pressure_control_patches, compressor_patches, flow_control_patches, heat_consumer_patches +from pandapipes.plotting.plotting_toolbox import coords_from_node_geodata +from pandapower.plotting.collections import _create_node_collection, add_cmap_to_collection, \ + _create_node_element_collection, _create_line2d_collection, _create_complex_branch_collection +from pandapower.plotting.patch_makers import load_patches, ext_grid_patches from pandapower.plotting.plotting_toolbox import get_index_array try: @@ -664,4 +664,55 @@ def create_compressor_collection(net, cmprs=None, table_name='compressor', size= patch_edgecolor=color, line_color=color, **kwargs) + return pc, lc + +def create_heat_consumer_collection(net, hec=None, table_name='heat_consumer', size=5., + junction_geodata=None, color='k', infofunc=None, picker=False, + **kwargs): + """ + Creates a matplotlib patch collection of pandapipes heat_consumers. Heat consumers are + plotted in the center between two junctions. + + :param net: The pandapipes network + :type net: pandapipesNet + :param hec: The heat consumers for which the collections are created. If None, all heat consumers + which have entries in the respective junction geodata will be plotted. + :type hec: list, default None + :param size: Patch size + :type size: float, default 5. + :param junction_geodata: Coordinates to use for plotting. If None, net["junction_geodata"] is \ + used. + :type junction_geodata: pandas.DataFrame, default None + :param colors: Color or list of colors for every compressor + :type colors: iterable, float, default None + :param infofunc: infofunction for the patch element + :type infofunc: function, default None + :param picker: Picker argument passed to the patch collection + :type picker: bool, default False + :param kwargs: Keyword arguments are passed to the patch function + :return: lc - line collection, pc - patch collection + + """ + hec = get_index_array(hec, net[table_name].index) + hec_table = net[table_name].loc[hec] + + coords, hec_with_geo = coords_from_node_geodata( + hec, hec_table.from_junction.values, hec_table.to_junction.values, + junction_geodata if junction_geodata is not None else net["junction_geodata"], table_name, + "Junction") + + if len(hec_with_geo) == 0: + return None + + linewidths = kwargs.pop("linewidths", 2.) + linewidths = kwargs.pop("linewidth", linewidths) + linewidths = kwargs.pop("lw", linewidths) + + infos = list(np.repeat([infofunc(i) for i in range(len(hec_with_geo))], 2)) \ + if infofunc is not None else [] + pc, lc = _create_complex_branch_collection(coords, heat_consumer_patches, size, infos, + picker=picker, linewidths=linewidths, + patch_edgecolor=color, line_color=color, + **kwargs) + return pc, lc \ No newline at end of file diff --git a/src/pandapipes/plotting/generic_geodata.py b/src/pandapipes/plotting/generic_geodata.py index 51bc2cd2d..9547d09d1 100644 --- a/src/pandapipes/plotting/generic_geodata.py +++ b/src/pandapipes/plotting/generic_geodata.py @@ -104,7 +104,7 @@ def create_generic_coordinates(net, mg=None, library="igraph", geodata_table="ju raise ValueError("Unknown library %s - chose 'igraph' or 'networkx'" % library) if len(coords): - net[geodata_table].x = coords[1] - net[geodata_table].y = coords[0] + net[geodata_table].loc[:, 'x'] = coords[1] + net[geodata_table].loc[:, 'y'] = coords[0] net[geodata_table].index = net.junction.index if junctions is None else junctions return net diff --git a/src/pandapipes/plotting/patch_makers.py b/src/pandapipes/plotting/patch_makers.py index 3c6950ca0..f2d339fa3 100644 --- a/src/pandapipes/plotting/patch_makers.py +++ b/src/pandapipes/plotting/patch_makers.py @@ -218,3 +218,115 @@ def pressure_control_patches(coords, size, **kwargs): lines.append([plr, pur]) return lines, polys, {} + +def heat_consumer_patches(coords, size, **kwargs): + """ + Creates patches for matplotlib plotting of heat consumer component + :param coords: + :type coords: + :param size: + :type size: + :param kwargs: + :type kwargs: + :return: + :rtype: + """ + polys, lines = [], [] + facecolor = kwargs.get("patch_facecolor", "w") + edgecolor = kwargs.get("patch_edgecolor", "k") + facecolors = get_color_list(facecolor, len(coords)) + edgecolors = get_color_list(edgecolor, len(coords)) + lw = kwargs.get("linewidths", 2.) + + for geodata, face_col, edge_col in zip(coords, facecolors, edgecolors): + p1, p2 = np.array(geodata[0]), np.array(geodata[-1]) + diff = p2 - p1 + m = 3 * size / 4 + direc = diff / np.sqrt(diff[0] ** 2 + diff[1] ** 2) + normal = np.array([-direc[1], direc[0]]) + circle_center = p1 + diff / 2 + triangle_center = circle_center + direc * size + radius = size + rectangle_size = 5 * size + triangle1, triangle2 = create_triangles(triangle_center + direc * radius, size/1.7, direc, normal, edgecolor) + polys.append(triangle1) + polys.append(triangle2) + + path1 = (p1 + diff / 2 + direc * m / 2) + normal * (size * 9 / 8) + path2 = p1 + diff / 2 + direc * m / 2 - normal*size/5 + path3 = p1 + diff / 2 + normal * size / 3 + path4 = p1 + diff / 2 - direc * m / 2 - normal*size/5 + path5 = (p1 + diff / 2 - direc * m / 2) + normal * (size * 9 / 8) + + path = [path1, path2, path3, path4, path5] + # np.sqrt(diff[0]**2+diff[1]**2)/15 + + pa = Path(path) + polys.append(PathPatch(pa, fill=False, lw=lw, edgecolor=edge_col)) + + angle = np.arctan2(*diff) + vec_size = _rotate_dim2(np.array([0, size]), angle) + vec_size_or = _rotate_dim2(np.array([0, size * 1.2/2]), angle + np.pi / 2) + pll = p1 + diff / 2 - vec_size + vec_size_or + + + polys.append(Rectangle(pll, rectangle_size, rectangle_size/4, angle=np.rad2deg(-angle + np.pi / 2), + edgecolor=edgecolor, facecolor='none', lw=lw)) + + lines.append([p2, p1]) + + return lines, polys, {} + + +def create_triangles(center, size, direc, normal, edgecolor): + """ + Creates a pathpatch for triangles + :param center: + :type center: + :param size: + :type size: + :param direc: + :type direc: + :param normal: + :type normal: + :param edgecolor: + :type edgecolor: + :return: + :rtype: + """ + + radius = size + + # Create the first triangle + verts1 = [ + center + direc * radius, # top + center + normal * radius, # bottom left + center - normal * radius, # bottom right + center + direc * radius # back to top + ] + codes1 = [ + Path.MOVETO, + Path.LINETO, + Path.LINETO, + Path.CLOSEPOLY + ] + + # Create the second triangle mirrored at the peak + mirrored_center = center + 2 * direc * radius + verts2 = [ + mirrored_center - direc * radius, # top + mirrored_center + normal * radius, # bottom left + mirrored_center - normal * radius, # bottom right + mirrored_center - direc * radius # back to top + ] + codes2 = [ + Path.MOVETO, + Path.LINETO, + Path.LINETO, + Path.CLOSEPOLY + ] + + path1 = Path(verts1, codes1) + path2 = Path(verts2, codes2) + + return PathPatch(path1, fill=False, lw=2, edgecolor=edgecolor), PathPatch(path2, fill=False, lw=2, edgecolor=edgecolor) \ No newline at end of file diff --git a/src/pandapipes/plotting/pipeflow_results.py b/src/pandapipes/plotting/pipeflow_results.py index c3810043b..a7a64f3b1 100644 --- a/src/pandapipes/plotting/pipeflow_results.py +++ b/src/pandapipes/plotting/pipeflow_results.py @@ -7,6 +7,7 @@ import pandas as pd import matplotlib.pyplot as plt import numpy as np +from warnings import warn def pressure_profile_to_junction_geodata(net): @@ -53,7 +54,7 @@ def plot_pressure_profile(net, ax=None, x0_junctions=None, plot_pressure_control axis to plot to, by default None x0_junctions : Any[list[int], pd.Index[int]], optional list of junction indices which should be at position x0. If None, all in service slack junctions are considered, - by default None + by default None. For circ pumps, if no x0_junctions are given the flow junctions are chosen automatically. plot_pressure_controller : bool, optional Whether vertical lines should be plotted to display the pressure drop of the pressure controller, by default True @@ -89,10 +90,21 @@ def plot_pressure_profile(net, ax=None, x0_junctions=None, plot_pressure_control if pipes is None: pipes = net.pipe.index if x0_junctions is None: - x0_junctions = net.ext_grid[net.ext_grid.in_service].junction.values.tolist() + x0_junctions = set(net.ext_grid[net.ext_grid.in_service].junction.values) + if hasattr(net, "circ_pump_pressure"): + x0_junctions |= set(net.circ_pump_pressure[net.circ_pump_pressure.in_service].flow_junction.values) + if hasattr(net, "circ_pump_mass"): + x0_junctions |= set(net.circ_pump_mass[net.circ_pump_mass.in_service].flow_junction.values) + x0_junctions = list(x0_junctions) + + unsupplied_junctions = list(top.unsupplied_junctions(net, slacks=set(x0_junctions))) + if len(unsupplied_junctions) > 0: + warn(UserWarning(f'There are unsupplied junctions in the net, they will not be plottet: {unsupplied_junctions}')) + pipe_table = net.pipe[net.pipe.in_service & net.pipe.index.isin(pipes) & + ~net.pipe.from_junction.isin(unsupplied_junctions) & + ~net.pipe.to_junction.isin(unsupplied_junctions)] d = top.calc_distance_to_junctions(net, x0_junctions) - pipe_table = net.pipe[net.pipe.in_service & net.pipe.index.isin(pipes)] x = np.array([d.loc[pipe_table.from_junction].values, d.loc[pipe_table.to_junction].values]) + x0 y = np.array([net.res_junction.p_bar.loc[pipe_table.from_junction].values, net.res_junction.p_bar.loc[pipe_table.to_junction].values]) diff --git a/src/pandapipes/plotting/plotting_toolbox.py b/src/pandapipes/plotting/plotting_toolbox.py index 23b5817ec..a5f2fc981 100644 --- a/src/pandapipes/plotting/plotting_toolbox.py +++ b/src/pandapipes/plotting/plotting_toolbox.py @@ -2,15 +2,24 @@ # and Energy System Technology (IEE), Kassel, and University of Kassel. All rights reserved. # Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. +import numpy as np +try: + import pandaplan.core.pplog as logging +except ImportError: + import logging + +logger = logging.getLogger(__name__) + + def get_collection_sizes(net, junction_size=1.0, ext_grid_size=1.0, sink_size=1.0, source_size=1.0, valve_size=2.0, pump_size=1.0, heat_exchanger_size=1.0, - pressure_control_size=1.0, compressor_size=1.0, flow_control_size=1.0): + pressure_control_size=1.0, compressor_size=1.0, flow_control_size=1.0, heat_consumer_size=1.0): """ Calculates the size for most collection types according to the distance between min and max geocoord so that the collections fit the plot nicely .. note: This is implemented because if you would choose a fixed values (e.g.\ - junction_size = 0.2), the size could be to small for large networks and vice versa + junction_size = 0.2), the size could be too small for large networks and vice versa :param net: pandapower network for which to create plot :type net: pandapowerNet @@ -26,10 +35,15 @@ def get_collection_sizes(net, junction_size=1.0, ext_grid_size=1.0, sink_size=1. :type valve_size: float, default 2. :param heat_exchanger_size: relative heat exchanger size :type heat_exchanger_size: float, default 1. + :param heat_consumer_size: relative heat consumer size + :type heat_consumer_size: float, default 1. :return: sizes (dict) - dictionary containing all scaled sizes """ - mean_distance_between_junctions = sum((net['junction_geodata'].max() - net[ - 'junction_geodata'].min()).dropna() / 200) + mean_distance_between_junctions = sum( + (np.max(net['junction_geodata'].loc[:, ["x", "y"]].to_numpy(), axis=0) + - np.min(net['junction_geodata'].loc[:, ["x", "y"]].to_numpy(), axis=0)) + / 200 + ) sizes = { "junction": junction_size * mean_distance_between_junctions, @@ -42,7 +56,49 @@ def get_collection_sizes(net, junction_size=1.0, ext_grid_size=1.0, sink_size=1. "pressure_control": pressure_control_size * mean_distance_between_junctions * 8, "compressor": compressor_size * mean_distance_between_junctions * 8, "flow_control": flow_control_size * mean_distance_between_junctions * 2, + "heat_consumer": heat_consumer_size * mean_distance_between_junctions*2 } return sizes + +def coords_from_node_geodata(element_indices, from_nodes, to_nodes, node_geodata, table_name, + node_name="Bus", ignore_zero_length=True): + """ + Auxiliary function to get the node coordinates for a number of branches with respective from + and to nodes. The branch elements for which there is no geodata available are not included in + the final list of coordinates. + + :param element_indices: Indices of the branch elements for which to find node geodata + :type element_indices: iterable + :param from_nodes: Indices of the starting nodes + :type from_nodes: iterable + :param to_nodes: Indices of the ending nodes + :type to_nodes: iterable + :param node_geodata: Dataframe containing x and y coordinates of the nodes + :type node_geodata: pd.DataFrame + :param table_name: Name of the table that the branches belong to (only for logging) + :type table_name: str + :param node_name: Name of the node type (only for logging) + :type node_name: str, default "Bus" + :param ignore_zero_length: States if branches should be left out, if their length is zero, i.e.\ + from_node_coords = to_node_coords + :type ignore_zero_length: bool, default True + :return: Return values are:\ + - coords (list) - list of branch coordinates of shape (N, (2, 2))\ + - elements_with_geo (set) - the indices of branch elements for which coordinates wer found\ + in the node geodata table + """ + have_geo = np.isin(from_nodes, node_geodata.index.values) \ + & np.isin(to_nodes, node_geodata.index.values) + elements_with_geo = np.array(element_indices)[have_geo] + fb_with_geo, tb_with_geo = from_nodes[have_geo], to_nodes[have_geo] + coords = [[(x_from, y_from), (x_to, y_to)] for x_from, y_from, x_to, y_to + in np.concatenate([node_geodata.loc[fb_with_geo, ["x", "y"]].values, + node_geodata.loc[tb_with_geo, ["x", "y"]].values], axis=1) + if not ignore_zero_length or not (x_from == x_to and y_from == y_to)] + elements_without_geo = set(element_indices) - set(elements_with_geo) + if len(elements_without_geo) > 0: + logger.warning("No coords found for %s %s. %s geodata is missing for those %s!" + % (table_name + "s", elements_without_geo, node_name, table_name + "s")) + return coords, elements_with_geo diff --git a/src/pandapipes/plotting/simple_plot.py b/src/pandapipes/plotting/simple_plot.py index 1d0902369..73ef01d93 100644 --- a/src/pandapipes/plotting/simple_plot.py +++ b/src/pandapipes/plotting/simple_plot.py @@ -13,7 +13,7 @@ from pandapipes.plotting.collections import create_junction_collection, create_pipe_collection, \ create_valve_collection, create_source_collection, create_pressure_control_collection, \ create_heat_exchanger_collection, create_sink_collection, create_pump_collection, \ - create_compressor_collection, create_flow_control_collection + create_compressor_collection, create_flow_control_collection, create_heat_consumer_collection from pandapipes.plotting.generic_geodata import create_generic_coordinates from pandapipes.plotting.plotting_toolbox import get_collection_sizes @@ -29,10 +29,10 @@ def simple_plot(net, respect_valves=False, respect_in_service=True, pipe_width=2 junction_size=1.0, ext_grid_size=1.0, plot_sinks=False, plot_sources=False, sink_size=1.0, source_size=1.0, valve_size=1.0, pump_size=1.0, heat_exchanger_size=1.0, pressure_control_size=1.0, compressor_size=1.0, flow_control_size=1.0, - scale_size=True, junction_color="r", pipe_color='silver', ext_grid_color='orange', - valve_color='silver', pump_color='silver', heat_exchanger_color='silver', + heat_consumer_size=1.0, scale_size=True, junction_color="r", pipe_color='silver', + ext_grid_color='orange', valve_color='silver', pump_color='silver', heat_exchanger_color='silver', pressure_control_color='silver', compressor_color='silver', flow_control_color='silver', - library="igraph", show_plot=True, ax=None, **kwargs): + heat_consumer_color='silver',library="igraph", show_plot=True, ax=None, **kwargs): """ Plots a pandapipes network as simple as possible. If no geodata is available, artificial geodata is generated. For advanced plotting see @@ -74,6 +74,8 @@ def simple_plot(net, respect_valves=False, respect_in_service=True, pipe_width=2 :type compressor_size: float, default 1.0 :param flow_control_size: Relative size of flow_control to plot. :type flow_control_size: float, default 1.0 + :param heat_consumer_size: Relative size of heat_consumer to plot. + :type heat_consumer_size: float, default 1.0 :param scale_size: Flag if junction_size, ext_grid_size, valve_size- and distance will be \ scaled with respect to grid mean distances :type scale_size: bool, default True @@ -96,6 +98,8 @@ def simple_plot(net, respect_valves=False, respect_in_service=True, pipe_width=2 :type compressor_color: str, tuple, default "silver" :param flow_control_color: Flow Control Color. :type flow_control_color: str, tuple, default "silver" + :param heat_consumer_color: heat_consumer Color. + :type heat_consumer_color: str, tuple, default "silver" :param library: Library name to create generic coordinates (case of missing geodata). Choose\ "igraph" to use igraph package or "networkx" to use networkx package. :type library: str, default "igraph" @@ -122,6 +126,7 @@ def simple_plot(net, respect_valves=False, respect_in_service=True, pipe_width=2 pressure_control_size=pressure_control_size, compressor_size=compressor_size, flow_control_size=flow_control_size, + heat_consumer_size=heat_consumer_size, scale_size=scale_size, junction_color=junction_color, pipe_color=pipe_color, @@ -132,6 +137,7 @@ def simple_plot(net, respect_valves=False, respect_in_service=True, pipe_width=2 pressure_control_color=pressure_control_color, compressor_color=compressor_color, flow_control_color=flow_control_color, + heat_consumer_color=heat_consumer_color, library=library, as_dict=False, **kwargs) ax = draw_collections(collections, ax=ax) @@ -145,11 +151,11 @@ def create_simple_collections(net, respect_valves=False, respect_in_service=True junction_size=1.0, ext_grid_size=1.0, plot_sinks=False, plot_sources=False, sink_size=1.0, source_size=1.0, valve_size=1.0, pump_size=1.0, heat_exchanger_size=1.0, pressure_control_size=1.0, - compressor_size=1.0, flow_control_size=1.0, + compressor_size=1.0, flow_control_size=1.0, heat_consumer_size=1.0, scale_size=True, junction_color="r", pipe_color='silver', ext_grid_color='orange', valve_color='silver', pump_color='silver', heat_exchanger_color='silver', pressure_control_color='silver', - compressor_color='silver', flow_control_color='silver', + compressor_color='silver', flow_control_color='silver', heat_consumer_color='silver', library="igraph", as_dict=True, **kwargs): """ Plots a pandapipes network as simple as possible. @@ -194,6 +200,8 @@ def create_simple_collections(net, respect_valves=False, respect_in_service=True :type compressor_size: float, default 1.0 :param flow_control_size: Relative size of flow_control to plot. :type flow_control_size: float, default 1.0 + :param heat_consumer_size: Relative size of heat_consumer to plot. + :type heat_consumer_size: float, default 1.0 :param scale_size: Flag if junction_size, ext_grid_size, valve_size- and distance will be \ scaled with respect to grid mean distances :type scale_size: bool, default True @@ -216,6 +224,8 @@ def create_simple_collections(net, respect_valves=False, respect_in_service=True :type compressor_color: str, tuple, default "silver" :param flow_control_color: Flow Control Color. :type flow_control_color: str, tuple, default "silver" + :param heat_consumer_color: heat_consumer Color. + :type heat_consumer_color: str, tuple, default "silver" :param library: library name to create generic coordinates (case of missing geodata). Choose\ "igraph" to use igraph package or "networkx" to use networkx package. **NOTE**: \ Currently the networkx implementation is not working! @@ -236,7 +246,7 @@ def create_simple_collections(net, respect_valves=False, respect_in_service=True # if scale_size -> calc size from distance between min and max geocoord sizes = get_collection_sizes( net, junction_size, ext_grid_size, sink_size, source_size, valve_size, pump_size, - heat_exchanger_size, pressure_control_size, compressor_size, flow_control_size) + heat_exchanger_size, pressure_control_size, compressor_size, flow_control_size, heat_consumer_size) junction_size = sizes["junction"] ext_grid_size = sizes["ext_grid"] source_size = sizes["source"] @@ -247,6 +257,7 @@ def create_simple_collections(net, respect_valves=False, respect_in_service=True pressure_control_size = sizes["pressure_control"] compressor_size = sizes["compressor"] flow_control_size = sizes["flow_control"] + heat_consumer_size = sizes["heat_consumer"] # create junction collections to plot junc_idx = net.junction[net.junction.in_service].index if respect_in_service \ @@ -340,6 +351,13 @@ def create_simple_collections(net, respect_valves=False, respect_in_service=True linewidths=pipe_width, color=compressor_color) collections["compressor"] = compr_colls + if 'heat_consumer' in net: + idx = net.heat_consumer[net.heat_consumer.in_service].index if respect_in_service \ + else net.heat_consumer.index + he_colls = create_heat_consumer_collection(net, idx, size=heat_consumer_size, + linewidths=pipe_width, color=heat_consumer_color) + collections["heat consumers"] = he_colls + if 'additional_collections' in kwargs: collections["additional"] = list() for collection in kwargs.pop('additional_collections'): diff --git a/src/pandapipes/properties/properties_toolbox.py b/src/pandapipes/properties/properties_toolbox.py index 2d2175a24..28eecf878 100644 --- a/src/pandapipes/properties/properties_toolbox.py +++ b/src/pandapipes/properties/properties_toolbox.py @@ -5,8 +5,9 @@ import numpy as np from pandapipes.constants import NORMAL_TEMPERATURE, NORMAL_PRESSURE -from pandapipes.idx_branch import TOUTINIT, FROM_NODE_T, TO_NODE +from pandapipes.idx_branch import TOUTINIT, TO_NODE from pandapipes.idx_node import TINIT, PINIT, PAMB +from pandapipes.pf.internals_toolbox import get_from_nodes_corrected def calculate_mixture_viscosity(components_viscosities, components_molar_proportions, @@ -149,7 +150,7 @@ def calculate_mass_fraction_from_molar_fraction(component_molar_proportions, com def get_branch_real_density(fluid, node_pit, branch_pit): - from_nodes = branch_pit[:, FROM_NODE_T].astype(np.int32) + from_nodes = get_from_nodes_corrected(branch_pit) t_from = node_pit[from_nodes, TINIT] t_to = branch_pit[:, TOUTINIT] if fluid.is_gas: @@ -168,15 +169,15 @@ def get_branch_real_density(fluid, node_pit, branch_pit): return rho def get_branch_real_eta(fluid, node_pit, branch_pit): - from_nodes = branch_pit[:, FROM_NODE_T].astype(np.int32) + from_nodes = get_from_nodes_corrected(branch_pit) t_from = node_pit[from_nodes, TINIT] t_to = branch_pit[:, TOUTINIT] tm = (t_from + t_to) / 2 eta = fluid.get_viscosity(tm) return eta -def get_branch_cp(net, fluid, node_pit, branch_pit): - from_nodes = branch_pit[:, FROM_NODE_T].astype(np.int32) +def get_branch_cp(fluid, node_pit, branch_pit): + from_nodes = get_from_nodes_corrected(branch_pit) t_from = node_pit[from_nodes, TINIT] t_to = branch_pit[:, TOUTINIT] tm = (t_from + t_to) / 2 diff --git a/src/pandapipes/std_types/library/Pipe.csv b/src/pandapipes/std_types/library/Pipe.csv index 800b02ed4..4a5eebda5 100644 --- a/src/pandapipes/std_types/library/Pipe.csv +++ b/src/pandapipes/std_types/library/Pipe.csv @@ -1,221 +1,239 @@ -std_type;nominal_width_mm;outer_diameter_mm;inner_diameter_mm;standard_dimension_ratio;material -80_GGG;80;98.0;86.0;16.33;GGG -100_GGG;100;118.0;105.8;19.34;GGG -125_GGG;125;144.0;131.6;23.23;GGG -150_GGG;150;170.0;157.0;26.15;GGG -200_GGG;200;222.0;208.0;31.71;GGG -250_GGG;250;274.0;259.0;36.53;GGG -300_GGG;300;326.0;310.0;40.75;GGG -350_GGG;350;378.0;361.0;44.47;GGG -400_GGG;400;429.0;411.0;47.67;GGG -500_GGG;500;532.0;512.0;53.2;GGG -600_GGG;600;635.0;613.0;57.73;GGG -20_PE_100_SDR_11;20;20.0;16.2;10.53;PE 100 -25_PE_100_SDR_11;25;25.0;20.4;10.87;PE 100 -32_PE_100_SDR_11;32;32.0;26.2;11.03;PE 100 -40_PE_100_SDR_11;40;40.0;32.6;10.81;PE 100 -50_PE_100_SDR_11;50;50.0;40.8;10.87;PE 100 -63_PE_100_SDR_11;63;63.0;51.4;10.86;PE 100 -75_PE_100_SDR_11;75;75.0;61.4;11.03;PE 100 -90_PE_100_SDR_11;90;90.0;73.6;10.98;PE 100 -90_PE_100_SDR_17;90;90.0;79.2;16.67;PE 100 -110_PE_100_SDR_11;110;110.0;90.0;11.0;PE 100 -110_PE_100_SDR_17;110;110.0;96.8;16.67;PE 100 -125_PE_100_SDR_11;125;125.0;102.2;10.96;PE 100 -125_PE_100_SDR_17;125;125.0;110.2;16.89;PE 100 -140_PE_100_SDR_17;140;140.0;123.4;16.87;PE 100 -160_PE_100_SDR_11;160;160.0;130.8;10.96;PE 100 -160_PE_100_SDR_17;160;160.0;141.0;16.84;PE 100 -180_PE_100_SDR_17;180;180.0;158.6;16.82;PE 100 -180_PE_100_SDR_11;180;180.0;147.2;10.98;PE 100 -200_PE_100_SDR_17;200;200.0;176.2;16.81;PE 100 -225_PE_100_SDR_11;225;225.0;184.0;10.98;PE 100 -225_PE_100_SDR_17;225;225.0;198.2;16.79;PE 100 -250_PE_100_SDR_11;250;250.0;204.6;11.01;PE 100 -250_PE_100_SDR_17;250;250.0;220.4;16.89;PE 100 -280_PE_100_SDR_11;280;280.0;229.2;11.02;PE 100 -280_PE_100_SDR_17;280;280.0;246.8;16.87;PE 100 -315_PE_100_SDR_17;315;315.0;277.6;16.84;PE 100 -315_PE_100_SDR_11;315;315.0;257.8;11.01;PE 100 -355_PE_100_SDR_11;355;355.0;290.6;11.02;PE 100 -355_PE_100_SDR_17;355;355.0;312.8;16.82;PE 100 -400_PE_100_SDR_11;400;400.0;327.4;11.02;PE 100 -400_PE_100_SDR_17;400;400.0;352.6;16.88;PE 100 -450_PE_100_SDR_17;450;450.0;396.6;16.85;PE 100 -450_PE_100_SDR_11;450;450.0;368.0;10.98;PE 100 -500_PE_100_SDR_17;500;500.0;440.6;16.84;PE 100 -560_PE_100_SDR_17;560;560.0;493.6;16.87;PE 100 -630_PE_100_SDR_17;630;630.0;555.2;16.84;PE 100 -710_PE_100_SDR_17;710;710.0;625.8;16.86;PE 100 -800_PE_100_SDR_17;800;800.0;705.2;16.88;PE 100 -900_PE_100_SDR_17;900;900.0;793.4;16.89;PE 100 -20_PE_80_SDR_11;20;20.0;16.2;10.53;PE 80 -25_PE_80_SDR_11;25;25.0;20.4;10.87;PE 80 -32_PE_80_SDR_17.6;32;32.0;28.4;17.78;PE 80 -32_PE_80_SDR_11;32;32.0;26.2;11.03;PE 80 -40_PE_80_SDR_11;40;40.0;32.6;10.81;PE 80 -50_PE_80_SDR_11;50;50.0;40.8;10.87;PE 80 -63_PE_80_SDR_11;63;63.0;51.4;10.86;PE 80 -75_PE_80_SDR_11;75;75.0;61.4;11.03;PE 80 -90_PE_80_SDR_17;90;90.0;79.2;16.67;PE 80 -90_PE_80_SDR_11;90;90.0;73.6;10.98;PE 80 -110_PE_80_SDR_17;110;110.0;96.8;16.67;PE 80 -110_PE_80_SDR_11;110;110.0;90.0;11.0;PE 80 -125_PE_80_SDR_17;125;125.0;110.2;16.89;PE 80 -125_PE_80_SDR_11;125;125.0;102.2;10.96;PE 80 -140_PE_80_SDR_17;140;140.0;123.4;16.87;PE 80 -160_PE_80_SDR_17;160;160.0;141.0;16.84;PE 80 -160_PE_80_SDR_11;160;160.0;130.8;10.96;PE 80 -180_PE_80_SDR_11;180;180.0;147.2;10.98;PE 80 -180_PE_80_SDR_17;180;180.0;158.6;16.82;PE 80 -200_PE_80_SDR_17;200;200.0;176.2;16.81;PE 80 -225_PE_80_SDR_17;225;225.0;198.2;16.79;PE 80 -225_PE_80_SDR_11;225;225.0;184.0;10.98;PE 80 -250_PE_80_SDR_17;250;250.0;220.4;16.89;PE 80 -250_PE_80_SDR_11;250;250.0;204.6;11.01;PE 80 -280_PE_80_SDR_17;280;280.0;246.8;16.87;PE 80 -280_PE_80_SDR_11;280;280.0;229.2;11.02;PE 80 -315_PE_80_SDR_17;315;315.0;277.6;16.84;PE 80 -315_PE_80_SDR_11;315;315.0;257.8;11.01;PE 80 -355_PE_80_SDR_11;355;355.0;290.6;11.02;PE 80 -355_PE_80_SDR_17;355;355.0;312.8;16.82;PE 80 -400_PE_80_SDR_11;400;400.0;327.4;11.02;PE 80 -400_PE_80_SDR_17;400;400.0;352.6;16.88;PE 80 -450_PE_80_SDR_17;450;450.0;396.6;16.85;PE 80 -500_PE_80_SDR_17;500;500.0;440.6;16.84;PE 80 -560_PE_80_SDR_17;560;560.0;493.6;16.87;PE 80 -630_PE_80_SDR_17;630;630.0;555.2;16.84;PE 80 -710_PE_80_SDR_17;710;710.0;625.8;16.86;PE 80 -800_PE_80_SDR_17;800;800.0;705.2;16.88;PE 80 -900_PE_80_SDR_17;900;900.0;793.4;16.89;PE 80 -75_PE-HD_10;75;75.0;61.2;10.87;PE-HD 10 -90_PE-HD_10;90;90.0;73.6;10.98;PE-HD 10 -110_PE-HD_10;110;110.0;90.0;11.0;PE-HD 10 -140_PE-HD_10;140;140.0;114.4;10.94;PE-HD 10 -160_PE-HD_10;160;160.0;130.8;10.96;PE-HD 10 -225_PE-HD_10;225;225.0;184.0;10.98;PE-HD 10 -280_PE-HD_10;280;280.0;229.0;10.98;PE-HD 10 -355_PE-HD_10;355;355.0;290.4;10.99;PE-HD 10 -400_PE-HD_10;400;400.0;327.2;10.99;PE-HD 10 -450_PE-HD_10;450;450.0;368.0;10.98;PE-HD 10 -20_PE-HD_16;20;20.0;14.4;7.14;PE-HD 16 -25_PE-HD_16;25;25.0;18.0;7.14;PE-HD 16 -32_PE-HD_16;32;32.0;23.0;7.11;PE-HD 16 -40_PE-HD_16;40;40.0;28.8;7.14;PE-HD 16 -50_PE-HD_16;50;50.0;36.2;7.25;PE-HD 16 -63_PE-HD_16;63;63.0;45.6;7.24;PE-HD 16 -75_PE-HD_16;75;75.0;54.2;7.21;PE-HD 16 -90_PE-HD_16;90;90.0;65.0;7.2;PE-HD 16 -110PE-HD_16;110;110.0;79.6;7.24;PE-HD 16 -125_PE-HD_16;125;125.0;90.4;7.23;PE-HD 16 -140_PE-HD_16;140;140.0;103.2;7.61;PE-HD 16 -160_PE-HD_16;160;160.0;115.8;7.24;PE-HD 16 -180-PE-HD_16;180;180.0;130.2;7.23;PE-HD 16 -200-PE-HD_16;200;200.0;144.8;7.25;PE-HD 16 -225_PE-HD_16;225;225.0;162.8;7.23;PE-HD 16 -250_PE-HD_16;250;250.0;181.0;7.25;PE-HD 16 -280_PE-HD_16;280;280.0;202.6;7.24;PE-HD 16 -315_PE-HD_16;315;315.0;228.0;7.24;PE-HD 16 -355_PE-HD_16;355;355.0;257.0;7.24;PE-HD 16 -400_PE-HD_16;400;400.0;289.6;7.25;PE-HD 16 -90_PE-HD_6;90;90.0;79.8;17.65;PE-HD 6 -110_PE-HD_6;110;110.0;97.4;17.46;PE-HD 6 -125_PE-HD_6;125;125.0;110.8;17.61;PE-HD 6 -140_PE-HD_6;140;140.0;124.0;17.5;PE-HD 6 -160_PE-HD_6;160;160.0;141.8;17.58;PE-HD 6 -180_PE-HD_6;180;180.0;159.6;17.65;PE-HD 6 -200_PE-HD_6;200;200.0;177.2;17.54;PE-HD 6 -225_PE-HD_6;225;225.0;199.4;17.58;PE-HD 6 -250_PE-HD_6;250;250.0;221.6;17.61;PE-HD 6 -280_PE-HD_6;280;280.0;248.2;17.61;PE-HD 6 -315_PE-HD_6;315;315.0;279.2;17.6;PE-HD 6 -355_PE-HD_6;355;355.0;314.8;17.66;PE-HD 6 -400_PE-HD_6;400;400.0;354.6;17.62;PE-HD 6 -450_PE-HD_6;450;450.0;399.0;17.65;PE-HD 6 -500_PE-HD_6;500;500.0;443.4;17.67;PE-HD 6 -560_PE-HD_6;560;560.0;496.6;17.67;PE-HD 6 -630_PE-HD_6;630;630.0;558.6;17.65;PE-HD 6 -25_PE-Xa_SDR_11;25;32.0;26.2;11.03;PE-Xa -32_PE-Xa_SDR_11;32;40.0;32.6;10.81;PE-Xa -40_PE-Xa_SDR_11;40;50.0;40.8;10.87;PE-Xa -50_PE-Xa_SDR_11;50;63.0;51.4;10.86;PE-Xa -65_PE-Xa_SDR_11;65;75.0;61.4;11.03;PE-Xa -80_PE-Xa_SDR_11;80;90.0;73.6;10.98;PE-Xa -40_PE_80_SDR_17.6;40;40.0;35.4;17.39;PE 80 -50_PE_80_SDR_17.6;50;50.0;44.2;17.24;PE 80 -63_PE_80_SDR_17.6;63;63.0;55.8;17.5;PE 80 -90_PE_80_SDR_17.6;90;90.0;79.8;17.65;PE 80 -110_PE_80_SDR_17.6;110;110.0;97.4;17.46;PE 80 -125_PE_80_SDR_17.6;125;125.0;110.8;17.61;PE 80 -160_PE_80_SDR_17.6;160;160.0;141.8;17.58;PE 80 -180_PE_80_SDR_17.6;180;180.0;159.6;17.65;PE 80 -225_PE_80_SDR_17.6;225;225.0;199.4;17.58;PE 80 -250_PE_80_SDR_17.6;250;250.0;221.6;17.61;PE 80 -280_PE_80_SDR_17.6;280;280.0;248.2;17.61;PE 80 -315_PE_80_SDR_17.6;315;315.0;279.2;17.6;PE 80 -355_PE_80_SDR_17.6;355;355.0;314.8;17.66;PE 80 -400_PE_80_SDR_17.6;400;400.0;354.6;17.62;PE 80 -50_PVC_10;50;63.0;57.0;21.0;PVC -80_PVC_10;80;90.0;81.4;20.93;PVC -100_PVC_10;100;110.0;99.4;20.75;PVC -125_PVC_10;125;140.0;126.6;20.9;PVC -150_PVC_10;150;160.0;144.6;20.78;PVC -200_PVC_10;200;225.0;203.4;20.83;PVC -250_PVC_10;250;280.0;253.2;20.9;PVC -300_PVC_10;300;355.0;321.2;21.01;PVC -350_PVC_10;350;400.0;361.8;20.94;PVC -400_PVC_10;400;450.0;407.0;20.93;PVC -500_PVC_10;500;560.0;506.6;20.97;PVC -600_PVC_10;600;630.0;570.0;21.0;PVC -20_ST;20;25.0;21.0;12.5;ST -20_ST<16;20;26.9;22.3;11.7;ST -25_ST;25;30.0;26.0;15.0;ST -25_ST<16;25;33.7;28.5;12.96;ST -25_ST>16;25;33.7;27.9;11.62;ST -32_ST;32;38.0;33.4;16.52;ST -32_ST<16;32;42.4;37.2;16.31;ST -32_ST>16;32;42.4;36.6;14.62;ST -40_ST;40;48.3;43.7;21.0;ST -40_ST<16;40;48.3;43.1;18.58;ST -50_ST;50;60.3;55.7;26.22;ST -50_ST<16;50;60.3;54.5;20.79;ST -65_ST;65;88.9;83.7;34.19;ST -65_ST<16;65;76.1;70.3;26.24;ST -65_ST>16;65;88.9;82.5;27.78;ST -80_ST;80;88.9;84.3;38.65;ST -80_ST<16;80;88.9;82.5;27.78;ST -80_ST>16;80;88.9;81.7;24.69;ST -100_ST;100;114.3;109.1;43.96;ST -100_ST<16;100;114.3;107.9;35.72;ST -100_ST>16;100;114.3;107.1;31.75;ST -125_ST<16;125;139.7;132.5;38.81;ST -125_ST>16;125;139.7;131.7;34.92;ST -150_ST;150;168.3;162.5;58.03;ST -150_ST<16;150;168.3;160.3;42.08;ST -150_ST>16;150;168.3;159.3;37.4;ST -200_ST;200;219.1;212.7;68.47;ST -200_ST<16;200;219.1;210.1;48.69;ST -200_ST>16;200;219.1;209.1;43.82;ST -250_ST;250;273.0;265.8;75.83;ST -250_ST<16;250;273.0;263.0;54.6;ST -250_ST>16;250;273.0;261.8;48.75;ST -300_ST;300;323.9;315.9;80.97;ST -300_ST<16;300;323.9;312.7;57.84;ST -300_ST>16;300;323.9;311.3;51.41;ST -350_ST;350;355.6;346.6;79.02;ST -350_ST<16;350;355.6;344.4;63.5;ST -400_ST;400;406.4;397.4;90.31;ST -400_ST<16;400;406.4;393.8;64.51;ST -500_ST;500;508.0;496.8;90.71;ST -500_ST<16;500;508.0;495.4;80.63;ST -600_ST;600;610.0;598.8;108.93;ST -600_ST<16;600;610.0;597.4;96.83;ST -700_ST<16;700;711.0;696.8;100.14;ST -800_ST<16;800;813.0;797.0;101.62;ST -900_ST<16;900;914.0;894.0;91.4;ST -1000_ST<16;1000;1016.0;996.0;101.6;ST -1200_ST<16;1200;1220.0;1198.0;110.91;ST -1400_ST<16;1400;1420.0;1398.0;129.09;ST -1600_ST<16;1600;1620.0;1588.0;101.25;ST -1800_ST<16;1800;1820.0;1785.0;104.0;ST -2000_ST<16;2000;2020.0;1980.0;101.0;ST +std_type;nominal_width_mm;outer_diameter_mm;inner_diameter_mm;standard_dimension_ratio;material;u_w_per_m2k +80_GGG;80;98;86;16.33;GGG;0 +100_GGG;100;118;105.8;19.34;GGG;0 +125_GGG;125;144;131.6;23.23;GGG;0 +150_GGG;150;170;157;26.15;GGG;0 +200_GGG;200;222;208;31.71;GGG;0 +250_GGG;250;274;259;36.53;GGG;0 +300_GGG;300;326;310;40.75;GGG;0 +350_GGG;350;378;361;44.47;GGG;0 +400_GGG;400;429;411;47.67;GGG;0 +500_GGG;500;532;512;53.2;GGG;0 +600_GGG;600;635;613;57.73;GGG;0 +20_PE_100_SDR_11;20;20;16.2;10.53;PE 100;0 +25_PE_100_SDR_11;25;25;20.4;10.87;PE 100;0 +32_PE_100_SDR_11;32;32;26.2;11.03;PE 100;0 +40_PE_100_SDR_11;40;40;32.6;10.81;PE 100;0 +50_PE_100_SDR_11;50;50;40.8;10.87;PE 100;0 +63_PE_100_SDR_11;63;63;51.4;10.86;PE 100;0 +75_PE_100_SDR_11;75;75;61.4;11.03;PE 100;0 +90_PE_100_SDR_11;90;90;73.6;10.98;PE 100;0 +90_PE_100_SDR_17;90;90;79.2;16.67;PE 100;0 +110_PE_100_SDR_11;110;110;90;11;PE 100;0 +110_PE_100_SDR_17;110;110;96.8;16.67;PE 100;0 +125_PE_100_SDR_11;125;125;102.2;10.96;PE 100;0 +125_PE_100_SDR_17;125;125;110.2;16.89;PE 100;0 +140_PE_100_SDR_17;140;140;123.4;16.87;PE 100;0 +160_PE_100_SDR_11;160;160;130.8;10.96;PE 100;0 +160_PE_100_SDR_17;160;160;141;16.84;PE 100;0 +180_PE_100_SDR_17;180;180;158.6;16.82;PE 100;0 +180_PE_100_SDR_11;180;180;147.2;10.98;PE 100;0 +200_PE_100_SDR_17;200;200;176.2;16.81;PE 100;0 +225_PE_100_SDR_11;225;225;184;10.98;PE 100;0 +225_PE_100_SDR_17;225;225;198.2;16.79;PE 100;0 +250_PE_100_SDR_11;250;250;204.6;11.01;PE 100;0 +250_PE_100_SDR_17;250;250;220.4;16.89;PE 100;0 +280_PE_100_SDR_11;280;280;229.2;11.02;PE 100;0 +280_PE_100_SDR_17;280;280;246.8;16.87;PE 100;0 +315_PE_100_SDR_17;315;315;277.6;16.84;PE 100;0 +315_PE_100_SDR_11;315;315;257.8;11.01;PE 100;0 +355_PE_100_SDR_11;355;355;290.6;11.02;PE 100;0 +355_PE_100_SDR_17;355;355;312.8;16.82;PE 100;0 +400_PE_100_SDR_11;400;400;327.4;11.02;PE 100;0 +400_PE_100_SDR_17;400;400;352.6;16.88;PE 100;0 +450_PE_100_SDR_17;450;450;396.6;16.85;PE 100;0 +450_PE_100_SDR_11;450;450;368;10.98;PE 100;0 +500_PE_100_SDR_17;500;500;440.6;16.84;PE 100;0 +560_PE_100_SDR_17;560;560;493.6;16.87;PE 100;0 +630_PE_100_SDR_17;630;630;555.2;16.84;PE 100;0 +710_PE_100_SDR_17;710;710;625.8;16.86;PE 100;0 +800_PE_100_SDR_17;800;800;705.2;16.88;PE 100;0 +900_PE_100_SDR_17;900;900;793.4;16.89;PE 100;0 +20_PE_80_SDR_11;20;20;16.2;10.53;PE 80;0 +25_PE_80_SDR_11;25;25;20.4;10.87;PE 80;0 +32_PE_80_SDR_17.6;32;32;28.4;17.78;PE 80;0 +32_PE_80_SDR_11;32;32;26.2;11.03;PE 80;0 +40_PE_80_SDR_11;40;40;32.6;10.81;PE 80;0 +50_PE_80_SDR_11;50;50;40.8;10.87;PE 80;0 +63_PE_80_SDR_11;63;63;51.4;10.86;PE 80;0 +75_PE_80_SDR_11;75;75;61.4;11.03;PE 80;0 +90_PE_80_SDR_17;90;90;79.2;16.67;PE 80;0 +90_PE_80_SDR_11;90;90;73.6;10.98;PE 80;0 +110_PE_80_SDR_17;110;110;96.8;16.67;PE 80;0 +110_PE_80_SDR_11;110;110;90;11;PE 80;0 +125_PE_80_SDR_17;125;125;110.2;16.89;PE 80;0 +125_PE_80_SDR_11;125;125;102.2;10.96;PE 80;0 +140_PE_80_SDR_17;140;140;123.4;16.87;PE 80;0 +160_PE_80_SDR_17;160;160;141;16.84;PE 80;0 +160_PE_80_SDR_11;160;160;130.8;10.96;PE 80;0 +180_PE_80_SDR_11;180;180;147.2;10.98;PE 80;0 +180_PE_80_SDR_17;180;180;158.6;16.82;PE 80;0 +200_PE_80_SDR_17;200;200;176.2;16.81;PE 80;0 +225_PE_80_SDR_17;225;225;198.2;16.79;PE 80;0 +225_PE_80_SDR_11;225;225;184;10.98;PE 80;0 +250_PE_80_SDR_17;250;250;220.4;16.89;PE 80;0 +250_PE_80_SDR_11;250;250;204.6;11.01;PE 80;0 +280_PE_80_SDR_17;280;280;246.8;16.87;PE 80;0 +280_PE_80_SDR_11;280;280;229.2;11.02;PE 80;0 +315_PE_80_SDR_17;315;315;277.6;16.84;PE 80;0 +315_PE_80_SDR_11;315;315;257.8;11.01;PE 80;0 +355_PE_80_SDR_11;355;355;290.6;11.02;PE 80;0 +355_PE_80_SDR_17;355;355;312.8;16.82;PE 80;0 +400_PE_80_SDR_11;400;400;327.4;11.02;PE 80;0 +400_PE_80_SDR_17;400;400;352.6;16.88;PE 80;0 +450_PE_80_SDR_17;450;450;396.6;16.85;PE 80;0 +500_PE_80_SDR_17;500;500;440.6;16.84;PE 80;0 +560_PE_80_SDR_17;560;560;493.6;16.87;PE 80;0 +630_PE_80_SDR_17;630;630;555.2;16.84;PE 80;0 +710_PE_80_SDR_17;710;710;625.8;16.86;PE 80;0 +800_PE_80_SDR_17;800;800;705.2;16.88;PE 80;0 +900_PE_80_SDR_17;900;900;793.4;16.89;PE 80;0 +75_PE-HD_10;75;75;61.2;10.87;PE-HD 10;0 +90_PE-HD_10;90;90;73.6;10.98;PE-HD 10;0 +110_PE-HD_10;110;110;90;11;PE-HD 10;0 +140_PE-HD_10;140;140;114.4;10.94;PE-HD 10;0 +160_PE-HD_10;160;160;130.8;10.96;PE-HD 10;0 +225_PE-HD_10;225;225;184;10.98;PE-HD 10;0 +280_PE-HD_10;280;280;229;10.98;PE-HD 10;0 +355_PE-HD_10;355;355;290.4;10.99;PE-HD 10;0 +400_PE-HD_10;400;400;327.2;10.99;PE-HD 10;0 +450_PE-HD_10;450;450;368;10.98;PE-HD 10;0 +20_PE-HD_16;20;20;14.4;7.14;PE-HD 16;0 +25_PE-HD_16;25;25;18;7.14;PE-HD 16;0 +32_PE-HD_16;32;32;23;7.11;PE-HD 16;0 +40_PE-HD_16;40;40;28.8;7.14;PE-HD 16;0 +50_PE-HD_16;50;50;36.2;7.25;PE-HD 16;0 +63_PE-HD_16;63;63;45.6;7.24;PE-HD 16;0 +75_PE-HD_16;75;75;54.2;7.21;PE-HD 16;0 +90_PE-HD_16;90;90;65;7.2;PE-HD 16;0 +110PE-HD_16;110;110;79.6;7.24;PE-HD 16;0 +125_PE-HD_16;125;125;90.4;7.23;PE-HD 16;0 +140_PE-HD_16;140;140;103.2;7.61;PE-HD 16;0 +160_PE-HD_16;160;160;115.8;7.24;PE-HD 16;0 +180-PE-HD_16;180;180;130.2;7.23;PE-HD 16;0 +200-PE-HD_16;200;200;144.8;7.25;PE-HD 16;0 +225_PE-HD_16;225;225;162.8;7.23;PE-HD 16;0 +250_PE-HD_16;250;250;181;7.25;PE-HD 16;0 +280_PE-HD_16;280;280;202.6;7.24;PE-HD 16;0 +315_PE-HD_16;315;315;228;7.24;PE-HD 16;0 +355_PE-HD_16;355;355;257;7.24;PE-HD 16;0 +400_PE-HD_16;400;400;289.6;7.25;PE-HD 16;0 +90_PE-HD_6;90;90;79.8;17.65;PE-HD 6;0 +110_PE-HD_6;110;110;97.4;17.46;PE-HD 6;0 +125_PE-HD_6;125;125;110.8;17.61;PE-HD 6;0 +140_PE-HD_6;140;140;124;17.5;PE-HD 6;0 +160_PE-HD_6;160;160;141.8;17.58;PE-HD 6;0 +180_PE-HD_6;180;180;159.6;17.65;PE-HD 6;0 +200_PE-HD_6;200;200;177.2;17.54;PE-HD 6;0 +225_PE-HD_6;225;225;199.4;17.58;PE-HD 6;0 +250_PE-HD_6;250;250;221.6;17.61;PE-HD 6;0 +280_PE-HD_6;280;280;248.2;17.61;PE-HD 6;0 +315_PE-HD_6;315;315;279.2;17.6;PE-HD 6;0 +355_PE-HD_6;355;355;314.8;17.66;PE-HD 6;0 +400_PE-HD_6;400;400;354.6;17.62;PE-HD 6;0 +450_PE-HD_6;450;450;399;17.65;PE-HD 6;0 +500_PE-HD_6;500;500;443.4;17.67;PE-HD 6;0 +560_PE-HD_6;560;560;496.6;17.67;PE-HD 6;0 +630_PE-HD_6;630;630;558.6;17.65;PE-HD 6;0 +25_PE-Xa_SDR_11;25;32;26.2;11.03;PE-Xa;0 +32_PE-Xa_SDR_11;32;40;32.6;10.81;PE-Xa;0 +40_PE-Xa_SDR_11;40;50;40.8;10.87;PE-Xa;0 +50_PE-Xa_SDR_11;50;63;51.4;10.86;PE-Xa;0 +65_PE-Xa_SDR_11;65;75;61.4;11.03;PE-Xa;0 +80_PE-Xa_SDR_11;80;90;73.6;10.98;PE-Xa;0 +40_PE_80_SDR_17.6;40;40;35.4;17.39;PE 80;0 +50_PE_80_SDR_17.6;50;50;44.2;17.24;PE 80;0 +63_PE_80_SDR_17.6;63;63;55.8;17.5;PE 80;0 +90_PE_80_SDR_17.6;90;90;79.8;17.65;PE 80;0 +110_PE_80_SDR_17.6;110;110;97.4;17.46;PE 80;0 +125_PE_80_SDR_17.6;125;125;110.8;17.61;PE 80;0 +160_PE_80_SDR_17.6;160;160;141.8;17.58;PE 80;0 +180_PE_80_SDR_17.6;180;180;159.6;17.65;PE 80;0 +225_PE_80_SDR_17.6;225;225;199.4;17.58;PE 80;0 +250_PE_80_SDR_17.6;250;250;221.6;17.61;PE 80;0 +280_PE_80_SDR_17.6;280;280;248.2;17.61;PE 80;0 +315_PE_80_SDR_17.6;315;315;279.2;17.6;PE 80;0 +355_PE_80_SDR_17.6;355;355;314.8;17.66;PE 80;0 +400_PE_80_SDR_17.6;400;400;354.6;17.62;PE 80;0 +50_PVC_10;50;63;57;21;PVC;0 +80_PVC_10;80;90;81.4;20.93;PVC;0 +100_PVC_10;100;110;99.4;20.75;PVC;0 +125_PVC_10;125;140;126.6;20.9;PVC;0 +150_PVC_10;150;160;144.6;20.78;PVC;0 +200_PVC_10;200;225;203.4;20.83;PVC;0 +250_PVC_10;250;280;253.2;20.9;PVC;0 +300_PVC_10;300;355;321.2;21.01;PVC;0 +350_PVC_10;350;400;361.8;20.94;PVC;0 +400_PVC_10;400;450;407;20.93;PVC;0 +500_PVC_10;500;560;506.6;20.97;PVC;0 +600_PVC_10;600;630;570;21;PVC;0 +20_ST;20;25;21;12.5;ST;0 +20_ST<16;20;26.9;22.3;11.7;ST;0 +25_ST;25;30;26;15;ST;0 +25_ST<16;25;33.7;28.5;12.96;ST;0 +25_ST>16;25;33.7;27.9;11.62;ST;0 +32_ST;32;38;33.4;16.52;ST;0 +32_ST<16;32;42.4;37.2;16.31;ST;0 +32_ST>16;32;42.4;36.6;14.62;ST;0 +40_ST;40;48.3;43.7;21;ST;0 +40_ST<16;40;48.3;43.1;18.58;ST;0 +50_ST;50;60.3;55.7;26.22;ST;0 +50_ST<16;50;60.3;54.5;20.79;ST;0 +65_ST;65;88.9;83.7;34.19;ST;0 +65_ST<16;65;76.1;70.3;26.24;ST;0 +65_ST>16;65;88.9;82.5;27.78;ST;0 +80_ST;80;88.9;84.3;38.65;ST;0 +80_ST<16;80;88.9;82.5;27.78;ST;0 +80_ST>16;80;88.9;81.7;24.69;ST;0 +100_ST;100;114.3;109.1;43.96;ST;0 +100_ST<16;100;114.3;107.9;35.72;ST;0 +100_ST>16;100;114.3;107.1;31.75;ST;0 +125_ST<16;125;139.7;132.5;38.81;ST;0 +125_ST>16;125;139.7;131.7;34.92;ST;0 +150_ST;150;168.3;162.5;58.03;ST;0 +150_ST<16;150;168.3;160.3;42.08;ST;0 +150_ST>16;150;168.3;159.3;37.4;ST;0 +200_ST;200;219.1;212.7;68.47;ST;0 +200_ST<16;200;219.1;210.1;48.69;ST;0 +200_ST>16;200;219.1;209.1;43.82;ST;0 +250_ST;250;273;265.8;75.83;ST;0 +250_ST<16;250;273;263;54.6;ST;0 +250_ST>16;250;273;261.8;48.75;ST;0 +300_ST;300;323.9;315.9;80.97;ST;0 +300_ST<16;300;323.9;312.7;57.84;ST;0 +300_ST>16;300;323.9;311.3;51.41;ST;0 +350_ST;350;355.6;346.6;79.02;ST;0 +350_ST<16;350;355.6;344.4;63.5;ST;0 +400_ST;400;406.4;397.4;90.31;ST;0 +400_ST<16;400;406.4;393.8;64.51;ST;0 +500_ST;500;508;496.8;90.71;ST;0 +500_ST<16;500;508;495.4;80.63;ST;0 +600_ST;600;610;598.8;108.93;ST;0 +600_ST<16;600;610;597.4;96.83;ST;0 +700_ST<16;700;711;696.8;100.14;ST;0 +800_ST<16;800;813;797;101.62;ST;0 +900_ST<16;900;914;894;91.4;ST;0 +1000_ST<16;1000;1016;996;101.6;ST;0 +1200_ST<16;1200;1220;1198;110.91;ST;0 +1400_ST<16;1400;1420;1398;129.09;ST;0 +1600_ST<16;1600;1620;1588;101.25;ST;0 +1800_ST<16;1800;1820;1785;104;ST;0 +2000_ST<16;2000;2020;1980;101;ST;0 +25/91 PLUS;20;94;25;11.36;PEXa;0.099 +32/91 PLUS;25;94;32;12.8;PEXa;0.121 +40/111 PLUS;32;114;40;14.29;PEXa;0.124 +50/111;40;114;47.6;13.22;PEXa;0.147 +50/126 PLUS;40;129;47.6;13.22;PEXa;0.13 +63/126;50;129;58.5;14.63;PEXa;0.162 +63/142 PLUS;50;145;58.5;14.63;PEXa;0.142 +75/142;65;145;69.5;15.11;PEXa;0.173 +75/162 PLUS;65;165;69.5;15.11;PEXa;0.148 +90/162;80;165;84;14;PEXa;0.187 +90/182 PLUS;80;185;84;14;PEXa;0.161 +110/182 PLUS;100;185;101;15.54;PEXa;0.206 +110/202 PLUS;100;205;101;15.54;PEXa;0.178 +125/202 PLUS;125;205;116;17.06;PEXa;0.217 +125/225 PLUS;125;228;116;17.06;PEXa;0.185 +140/202;125;205;127;17.89;PEXa;0.255 +140/225 PLUS;125;228;127;17.89;PEXa;0.212 +160/225;150;228;144;19.2;PEXa;0.264 diff --git a/src/pandapipes/test/api/old_versions/example_0.11.0_gas.json b/src/pandapipes/test/api/old_versions/example_0.11.0_gas.json new file mode 100644 index 000000000..e8095833e --- /dev/null +++ b/src/pandapipes/test/api/old_versions/example_0.11.0_gas.json @@ -0,0 +1,460 @@ +{ + "_module": "pandapipes.pandapipes_net", + "_class": "pandapipesNet", + "_object": { + "fluid": { + "_module": "pandapipes.properties.fluids", + "_class": "Fluid", + "_object": "{\"name\": \"hgas\", \"fluid_type\": \"gas\", \"is_gas\": true, \"all_properties\": {\"density\": {\"_module\": \"pandapipes.properties.fluids\", \"_class\": \"FluidPropertyInterExtra\", \"_object\": \"{\\\"x\\\": {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"array\\\", \\\"_object\\\": [{\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 263.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 273.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 283.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 293.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 303.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 313.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 323.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 333.0}], \\\"dtype\\\": \\\"float64\\\"}, \\\"y\\\": {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"array\\\", \\\"_object\\\": [{\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 0.7614762591064257}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 0.733332277439119}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 0.7072104923835694}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 0.6828947600611692}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 0.660205611537355}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 0.6389854855679075}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 0.6190946329317856}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 0.6004074588524487}], \\\"dtype\\\": \\\"float64\\\"}, \\\"_fill_value_orig\\\": \\\"extrapolate\\\"}\"}, \"viscosity\": {\"_module\": \"pandapipes.properties.fluids\", \"_class\": \"FluidPropertyInterExtra\", \"_object\": \"{\\\"x\\\": {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"array\\\", \\\"_object\\\": [{\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 263.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 273.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 283.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 293.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 303.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 313.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 323.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 333.0}], \\\"dtype\\\": \\\"float64\\\"}, \\\"y\\\": {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"array\\\", \\\"_object\\\": [{\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 1.0047118361853041e-05}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 1.04021750220461e-05}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 1.0704866480048474e-05}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 1.1007402297863992e-05}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 1.1337005139349375e-05}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 1.170765177634217e-05}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 1.2010332619395079e-05}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 1.231274052527204e-05}], \\\"dtype\\\": \\\"float64\\\"}, \\\"_fill_value_orig\\\": \\\"extrapolate\\\"}\"}, \"heat_capacity\": {\"_module\": \"pandapipes.properties.fluids\", \"_class\": \"FluidPropertyInterExtra\", \"_object\": \"{\\\"x\\\": {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"array\\\", \\\"_object\\\": [{\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 263.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 273.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 283.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 293.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 303.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 313.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 323.0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 333.0}], \\\"dtype\\\": \\\"float64\\\"}, \\\"y\\\": {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"array\\\", \\\"_object\\\": [{\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 2111.7430409177705}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 2129.19525821288}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 2148.5756908384515}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 2169.8204812997346}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 2192.8111461983763}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 2217.455354914997}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 2243.67904088272}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 2271.295613279192}], \\\"dtype\\\": \\\"float64\\\"}, \\\"_fill_value_orig\\\": \\\"extrapolate\\\"}\"}, \"molar_mass\": {\"_module\": \"pandapipes.properties.fluids\", \"_class\": \"FluidPropertyConstant\", \"_object\": \"{\\\"value\\\": 16.604497, \\\"warn_dependent_variables\\\": false}\"}, \"der_compressibility\": {\"_module\": \"pandapipes.properties.fluids\", \"_class\": \"FluidPropertyConstant\", \"_object\": \"{\\\"value\\\": -0.0022, \\\"warn_dependent_variables\\\": false}\"}, \"compressibility\": {\"_module\": \"pandapipes.properties.fluids\", \"_class\": \"FluidPropertyLinear\", \"_object\": \"{\\\"slope\\\": {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": -0.0022}, \\\"offset\\\": {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"float64\\\", \\\"_object\\\": 1.0}}\"}, \"lhv\": {\"_module\": \"pandapipes.properties.fluids\", \"_class\": \"FluidPropertyConstant\", \"_object\": \"{\\\"value\\\": 13.20179, \\\"warn_dependent_variables\\\": false}\"}, \"hhv\": {\"_module\": \"pandapipes.properties.fluids\", \"_class\": \"FluidPropertyConstant\", \"_object\": \"{\\\"value\\\": 14.62197, \\\"warn_dependent_variables\\\": false}\"}}}" + }, + "converged": { + "_module": "numpy", + "_class": "bool_", + "_object": "true" + }, + "name": "net", + "version": "0.11.0", + "format_version": "0.11.0", + "component_list": [ + { + "_module": "pandapipes.component_models.junction_component", + "_class": "Junction", + "_object": "{}" + }, + { + "_module": "pandapipes.component_models.pipe_component", + "_class": "Pipe", + "_object": "{}" + }, + { + "_module": "pandapipes.component_models.ext_grid_component", + "_class": "ExtGrid", + "_object": "{}" + }, + { + "_module": "pandapipes.component_models.sink_component", + "_class": "Sink", + "_object": "{}" + }, + { + "_module": "pandapipes.component_models.source_component", + "_class": "Source", + "_object": "{}" + }, + { + "_module": "pandapipes.component_models.mass_storage_component", + "_class": "MassStorage", + "_object": "{}" + }, + { + "_module": "pandapipes.component_models.valve_component", + "_class": "Valve", + "_object": "{}" + }, + { + "_module": "pandapipes.component_models.flow_control_component", + "_class": "FlowControlComponent", + "_object": "{}" + }, + { + "_module": "pandapipes.component_models.pressure_control_component", + "_class": "PressureControlComponent", + "_object": "{}" + }, + { + "_module": "pandapipes.component_models.compressor_component", + "_class": "Compressor", + "_object": "{}" + } + ], + "junction": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"pn_bar\",\"tfluid_k\",\"height_m\",\"in_service\",\"type\"],\"index\":[0,1,2,3,4,5,6,7,8,9,10,11,12],\"data\":[[\"Junction 0\",16.0,283.0,0.0,true,\"junction\"],[\"Junction 1\",16.0,283.0,0.0,true,\"junction\"],[\"Junction 2\",16.0,283.0,0.0,true,\"junction\"],[\"Junction 3\",16.0,283.0,0.0,true,\"junction\"],[\"Junction 4\",16.0,283.0,0.0,true,\"junction\"],[\"Junction 5\",16.0,283.0,0.0,true,\"junction\"],[\"Junction 6\",16.0,283.0,0.0,true,\"junction\"],[\"Junction 7\",16.0,283.0,0.0,true,\"junction\"],[\"Junction 8\",16.0,283.0,0.0,true,\"junction\"],[\"Junction 9\",16.0,283.0,0.0,true,\"junction\"],[\"Junction 10\",16.0,283.0,0.0,true,\"junction\"],[\"Junction 11\",0.7,283.0,0.0,true,\"junction\"],[\"Junction 12\",0.7,283.0,0.0,true,\"junction\"]]}", + "orient": "split", + "dtype": { + "name": "object", + "pn_bar": "float64", + "tfluid_k": "float64", + "height_m": "float64", + "in_service": "bool", + "type": "object" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "junction_geodata": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"x\",\"y\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "x": "float64", + "y": "float64" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "pipe": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"from_junction\",\"to_junction\",\"std_type\",\"length_km\",\"diameter_m\",\"k_mm\",\"loss_coefficient\",\"u_w_per_m2k\",\"text_k\",\"qext_w\",\"sections\",\"in_service\",\"type\"],\"index\":[0,1,2,3,4,5,6,7],\"data\":[[\"Pipe 0\",0,1,null,3.0,0.1,1.0,0.0,10.0,293.0,0.0,10,true,\"pipe\"],[\"Pipe 1\",2,3,null,6.0,0.075,0.1,0.0,3.0,null,0.0,10,true,\"pipe\"],[\"Pipe 2\",3,4,null,5.0,0.06,0.1,0.0,20.0,null,0.0,10,true,\"pipe\"],[\"Pipe 3\",4,5,null,0.1,0.07,0.1,0.0,2.0,null,0.0,10,true,\"pipe\"],[\"Pipe 4\",5,6,null,4.5,0.085,0.1,0.0,2.5,null,0.0,10,true,\"pipe\"],[\"Pipe 5\",8,7,null,4.0,0.03,0.1,0.0,1.0,null,0.0,10,true,\"pipe\"],[\"Pipe 6\",9,10,null,1.0,0.03,0.1,0.0,1.0,null,0.0,10,true,\"pipe\"],[\"Pipe 7\",11,12,null,1.5,0.09,0.1,0.0,3.0,null,0.0,10,true,\"pipe\"]]}", + "orient": "split", + "dtype": { + "name": "object", + "from_junction": "uint32", + "to_junction": "uint32", + "std_type": "object", + "length_km": "float64", + "diameter_m": "float64", + "k_mm": "float64", + "loss_coefficient": "float64", + "u_w_per_m2k": "float64", + "text_k": "float64", + "qext_w": "float64", + "sections": "uint32", + "in_service": "bool", + "type": "object" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "pipe_geodata": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"coords\"],\"index\":[],\"data\":[]}", + "orient": "split", + "dtype": { + "coords": "object" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "ext_grid": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"name\",\"junction\",\"p_bar\",\"t_k\",\"in_service\",\"type\"],\"index\":[0,1],\"data\":[[\"External Grid 0\",0,16.0,280.0,true,\"pt\"],[\"External Grid 1\",8,15.0,285.0,true,\"pt\"]]}", + "orient": "split", + "dtype": { + "name": "object", + "junction": "uint32", + "p_bar": "float64", + "t_k": "float64", + "in_service": "bool", + "type": "object" + }, + "is_multiindex": false, + "is_multicolumn": false + }, + "controller": { + "_module": "pandas.core.frame", + "_class": "DataFrame", + "_object": "{\"columns\":[\"object\",\"in_service\",\"order\",\"level\",\"initial_run\",\"recycle\"],\"index\":[0,1],\"data\":[[{\"_module\":\"pandapower.control.controller.const_control\",\"_class\":\"ConstControl\",\"_object\":\"{\\\"index\\\": {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"int64\\\", \\\"_object\\\": 0}, \\\"matching_params\\\": {\\\"element\\\": \\\"sink\\\", \\\"variable\\\": \\\"mdot_kg_per_s\\\", \\\"element_index\\\": {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"array\\\", \\\"_object\\\": [{\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"int64\\\", \\\"_object\\\": 0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"int64\\\", \\\"_object\\\": 1}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"int64\\\", \\\"_object\\\": 2}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"int64\\\", \\\"_object\\\": 3}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"int64\\\", \\\"_object\\\": 4}], \\\"dtype\\\": \\\"int64\\\"}}, \\\"data_source\\\": {\\\"_module\\\": \\\"pandapower.timeseries.data_sources.frame_data\\\", \\\"_class\\\": \\\"DFData\\\", \\\"_object\\\": \\\"{\\\\\\\"df\\\\\\\": {\\\\\\\"_module\\\\\\\": \\\\\\\"pandas.core.frame\\\\\\\", \\\\\\\"_class\\\\\\\": \\\\\\\"DataFrame\\\\\\\", \\\\\\\"_object\\\\\\\": \\\\\\\"{\\\\\\\\\\\\\\\"columns\\\\\\\\\\\\\\\":[\\\\\\\\\\\\\\\"0\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"1\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"2\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"3\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"4\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"5\\\\\\\\\\\\\\\"],\\\\\\\\\\\\\\\"index\\\\\\\\\\\\\\\":[0,1,2,3],\\\\\\\\\\\\\\\"data\\\\\\\\\\\\\\\":[[0.2,0.1,0.5,0.07,0.09,0.1],[0.3,0.2,0.6,0.08,0.1,0.2],[0.4,0.3,0.7,0.09,0.11,0.3],[0.5,0.4,0.8,0.1,0.12,0.4]]}\\\\\\\", \\\\\\\"orient\\\\\\\": \\\\\\\"split\\\\\\\", \\\\\\\"dtype\\\\\\\": {\\\\\\\"0\\\\\\\": \\\\\\\"float64\\\\\\\", \\\\\\\"1\\\\\\\": \\\\\\\"float64\\\\\\\", \\\\\\\"2\\\\\\\": \\\\\\\"float64\\\\\\\", \\\\\\\"3\\\\\\\": \\\\\\\"float64\\\\\\\", \\\\\\\"4\\\\\\\": \\\\\\\"float64\\\\\\\", \\\\\\\"5\\\\\\\": \\\\\\\"float64\\\\\\\"}, \\\\\\\"is_multiindex\\\\\\\": false, \\\\\\\"is_multicolumn\\\\\\\": false}}\\\"}, \\\"element_index\\\": {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"array\\\", \\\"_object\\\": [{\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"int64\\\", \\\"_object\\\": 0}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"int64\\\", \\\"_object\\\": 1}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"int64\\\", \\\"_object\\\": 2}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"int64\\\", \\\"_object\\\": 3}, {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"int64\\\", \\\"_object\\\": 4}], \\\"dtype\\\": \\\"int64\\\"}, \\\"element\\\": \\\"sink\\\", \\\"values\\\": null, \\\"profile_name\\\": {\\\"_module\\\": \\\"numpy\\\", \\\"_class\\\": \\\"array\\\", \\\"_object\\\": [\\\"0\\\", \\\"1\\\", \\\"2\\\", \\\"3\\\", \\\"4\\\"], \\\"dtype\\\": \\\"= version.parse(minimal_version_two_nets): names = ["_gas", "_water"] net_gas = release_control_test_network_gas(max_iter_hyd=5) - net_water = release_control_test_network_water(max_iter_hyd=10) + net_water = release_control_test_network_water(max_iter_hyd=11) else: names = [""] - net_old = release_control_test_network(max_iter_hyd=10) + net_old = release_control_test_network(max_iter_hyd=11) for name in names: if "_gas" in name: net_ref = net_gas max_iter_hyd = 5 if use_numba else 5 elif "_water" in name: net_ref = net_water - max_iter_hyd = 10 if use_numba else 10 + max_iter_hyd = 11 if use_numba else 11 else: net_ref = net_old - max_iter_hyd = 10 if use_numba else 10 + max_iter_hyd = 11 if use_numba else 11 filename = os.path.join(folder, "example_%s%s.json" % (pp_version, name)) if not os.path.isfile(filename): raise ValueError("File for %s grid of version %s does not exist" % (name, pp_version)) try: net = pp.from_json(filename, convert=False) + if not "_gas" in name: + pp.create_ext_grid(net, junction=4, p_bar=6, t_k=290, name="External Grid 2", index=None) + pp.create_ext_grid(net, junction=5, p_bar=5, t_k=290, name="External Grid 3") + except: raise UserWarning("Can not load %s network saved in pandapipes version %s" % (name, pp_version)) diff --git a/src/pandapipes/test/api/test_create.py b/src/pandapipes/test/api/test_create.py index 50fe21f6b..c2dc946a3 100644 --- a/src/pandapipes/test/api/test_create.py +++ b/src/pandapipes/test/api/test_create.py @@ -94,21 +94,20 @@ def test_create_heat_exchanger(create_empty_net): net = copy.deepcopy(create_empty_net) pandapipes.create_junction(net, 1, 293, index=8, geodata=(0, 1)) pandapipes.create_junction(net, 1, 293, index=9, geodata=(2, 2)) - pandapipes.create_heat_exchanger(net, 8, 9, 0.3, qext_w=200, index=2) + pandapipes.create_heat_exchanger(net, 8, 9, qext_w=200, index=2) assert len(net.junction) == 2 assert len(net.heat_exchanger) == 1 assert np.all(net.heat_exchanger.index == [2]) assert net.heat_exchanger.at[2, "from_junction"] == 8 assert net.heat_exchanger.at[2, "to_junction"] == 9 - assert net.heat_exchanger.at[2, "diameter_m"] == 0.3 assert net.heat_exchanger.at[2, "qext_w"] == 200 assert net.heat_exchanger.at[2, "loss_coefficient"] == 0 with pytest.raises(UserWarning): - pandapipes.create_heat_exchanger(net, 8, 10, 0.3, qext_w=200) + pandapipes.create_heat_exchanger(net, 8, 10, qext_w=200) with pytest.raises(UserWarning): - pandapipes.create_heat_exchanger(net, 8, 9, 0.3, qext_w=200, index=2) + pandapipes.create_heat_exchanger(net, 8, 9, qext_w=200, index=2) def test_create_pipe(create_empty_net): @@ -315,7 +314,7 @@ def test_create_pipes_from_parameters(create_empty_net): p = pandapipes.create_pipes_from_parameters( net, [j1, j1], [j2, j2], length_km=5, diameter_m=0.8, in_service=False, geodata=[(10, 10), (20, 20)], name="test", k_mm=0.01, loss_coefficient=0.3, sections=2, - alpha_w_per_m2k=0.1, text_k=273, qext_w=0.01) + u_w_per_m2k=0.1, text_k=273, qext_w=0.01) assert len(net.pipe) == 2 assert len(net.pipe_geodata) == 2 @@ -335,8 +334,8 @@ def test_create_pipes_from_parameters(create_empty_net): assert net.pipe.at[p[1], "diameter_m"] == 0.8 assert net.pipe.at[p[0], "sections"] == 2 assert net.pipe.at[p[1], "sections"] == 2 - assert net.pipe.at[p[0], "alpha_w_per_m2k"] == 0.1 - assert net.pipe.at[p[1], "alpha_w_per_m2k"] == 0.1 + assert net.pipe.at[p[0], "u_w_per_m2k"] == 0.1 + assert net.pipe.at[p[1], "u_w_per_m2k"] == 0.1 assert net.pipe.at[p[0], "text_k"] == 273 assert net.pipe.at[p[1], "text_k"] == 273 assert net.pipe.at[p[0], "qext_w"] == 0.01 @@ -351,7 +350,7 @@ def test_create_pipes_from_parameters(create_empty_net): in_service=[True, False], geodata=[[(10, 10), (20, 20)], [(100, 10), (200, 20)]], name=["p1", "p2"], k_mm=[0.01, 0.02], loss_coefficient=[0.3, 0.5], sections=[1, 2], - alpha_w_per_m2k=[0.1, 0.2], text_k=[273, 274], qext_w=[0.01, 0.02]) + u_w_per_m2k=[0.1, 0.2], text_k=[273, 274], qext_w=[0.01, 0.02]) assert len(net.pipe) == 2 assert len(net.pipe_geodata) == 2 @@ -369,8 +368,8 @@ def test_create_pipes_from_parameters(create_empty_net): assert net.pipe.at[p[1], "k_mm"] == 0.02 assert net.pipe.at[p[0], "loss_coefficient"] == 0.3 assert net.pipe.at[p[1], "loss_coefficient"] == 0.5 - assert net.pipe.at[p[0], "alpha_w_per_m2k"] == 0.1 - assert net.pipe.at[p[1], "alpha_w_per_m2k"] == 0.2 + assert net.pipe.at[p[0], "u_w_per_m2k"] == 0.1 + assert net.pipe.at[p[1], "u_w_per_m2k"] == 0.2 assert net.pipe.at[p[0], "sections"] == 1 assert net.pipe.at[p[1], "sections"] == 2 assert net.pipe.at[p[0], "text_k"] == 273 @@ -389,17 +388,17 @@ def test_create_pipes_from_parameters_raise_except(create_empty_net): pandapipes.create_pipes_from_parameters( net, [1, 3], [4, 5], length_km=5, diameter_m=0.8, in_service=False, geodata=[(10, 10), (20, 20)], name="test", k_mm=0.01, loss_coefficient=0.3, sections=2, - alpha_w_per_m2k=0.1, text_k=273, qext_w=0.01) + u_w_per_m2k=0.1, text_k=273, qext_w=0.01) pandapipes.create_pipes_from_parameters( net, [j1, j1], [j2, j3], length_km=5, diameter_m=0.8, in_service=False, geodata=[(10, 10), (20, 20)], name="test", k_mm=0.01, loss_coefficient=0.3, sections=2, - alpha_w_per_m2k=0.1, text_k=273, qext_w=0.01, index=[0, 1]) + u_w_per_m2k=0.1, text_k=273, qext_w=0.01, index=[0, 1]) with pytest.raises(UserWarning, match=r"with indexes \[0 1\] already exist"): pandapipes.create_pipes_from_parameters( net, [j1, j1], [j2, j3], length_km=5, diameter_m=0.8, in_service=False, geodata=[(10, 10), (20, 20)], name="test", k_mm=0.01, loss_coefficient=0.3, sections=2, - alpha_w_per_m2k=0.1, text_k=273, qext_w=0.01, index=[0, 1]) + u_w_per_m2k=0.1, text_k=273, qext_w=0.01, index=[0, 1]) def test_create_pipes(create_empty_net): @@ -433,7 +432,7 @@ def test_create_pipes(create_empty_net): p = pandapipes.create_pipes( net, [j1, j1], [j2, j2], std_type="80_GGG", length_km=5, in_service=False, geodata=[(10, 10), (20, 20)], name="test", k_mm=0.01, loss_coefficient=0.3, sections=2, - alpha_w_per_m2k=0.1, text_k=273, qext_w=0.01) + u_w_per_m2k=0.1, text_k=273, qext_w=0.01) assert len(net.pipe) == 2 assert len(net.pipe_geodata) == 2 @@ -455,8 +454,8 @@ def test_create_pipes(create_empty_net): assert net.pipe.at[p[1], "diameter_m"] == 0.086 assert net.pipe.at[p[0], "sections"] == 2 assert net.pipe.at[p[1], "sections"] == 2 - assert net.pipe.at[p[0], "alpha_w_per_m2k"] == 0.1 - assert net.pipe.at[p[1], "alpha_w_per_m2k"] == 0.1 + assert net.pipe.at[p[0], "u_w_per_m2k"] == 0.1 + assert net.pipe.at[p[1], "u_w_per_m2k"] == 0.1 assert net.pipe.at[p[0], "text_k"] == 273 assert net.pipe.at[p[1], "text_k"] == 273 assert net.pipe.at[p[0], "qext_w"] == 0.01 @@ -470,7 +469,7 @@ def test_create_pipes(create_empty_net): net, [j1, j1], [j2, j2], std_type="80_GGG", length_km=[1, 5], in_service=[True, False], geodata=[[(10, 10), (20, 20)], [(100, 10), (200, 20)]], name=["p1", "p2"], k_mm=[0.01, 0.02], loss_coefficient=[0.3, 0.5], sections=[1, 2], - alpha_w_per_m2k=[0.1, 0.2], text_k=[273, 274], qext_w=[0.01, 0.02]) + u_w_per_m2k=[0.1, 0.2], text_k=[273, 274], qext_w=[0.01, 0.02]) assert len(net.pipe) == 2 assert len(net.pipe_geodata) == 2 @@ -490,8 +489,8 @@ def test_create_pipes(create_empty_net): assert net.pipe.at[p[1], "k_mm"] == 0.02 assert net.pipe.at[p[0], "loss_coefficient"] == 0.3 assert net.pipe.at[p[1], "loss_coefficient"] == 0.5 - assert net.pipe.at[p[0], "alpha_w_per_m2k"] == 0.1 - assert net.pipe.at[p[1], "alpha_w_per_m2k"] == 0.2 + assert net.pipe.at[p[0], "u_w_per_m2k"] == 0.1 + assert net.pipe.at[p[1], "u_w_per_m2k"] == 0.2 assert net.pipe.at[p[0], "sections"] == 1 assert net.pipe.at[p[1], "sections"] == 2 assert net.pipe.at[p[0], "text_k"] == 273 @@ -510,17 +509,17 @@ def test_create_pipes_raise_except(create_empty_net): pandapipes.create_pipes( net, [1, 3], [4, 5], std_type="80_GGG", length_km=5, in_service=False, geodata=[(10, 10), (20, 20)], name="test", k_mm=0.01, loss_coefficient=0.3, sections=2, - alpha_w_per_m2k=0.1, text_k=273, qext_w=0.01) + u_w_per_m2k=0.1, text_k=273, qext_w=0.01) pandapipes.create_pipes( net, [j1, j1], [j2, j3], std_type="80_GGG", length_km=5, in_service=False, geodata=[(10, 10), (20, 20)], name="test", k_mm=0.01, loss_coefficient=0.3, sections=2, - alpha_w_per_m2k=0.1, text_k=273, qext_w=0.01, index=[0, 1]) + u_w_per_m2k=0.1, text_k=273, qext_w=0.01, index=[0, 1]) with pytest.raises(UserWarning, match=r"with indexes \[0 1\] already exist"): pandapipes.create_pipes( net, [j1, j1], [j2, j3], std_type="80_GGG", length_km=5, in_service=False, geodata=[(10, 10), (20, 20)], name="test", k_mm=0.01, loss_coefficient=0.3, sections=2, - alpha_w_per_m2k=0.1, text_k=273, qext_w=0.01, index=[0, 1]) + u_w_per_m2k=0.1, text_k=273, qext_w=0.01, index=[0, 1]) def test_create_valves(create_empty_net): diff --git a/src/pandapipes/test/api/test_network_tables.py b/src/pandapipes/test/api/test_network_tables.py index 8ee1510bf..ce5bf389e 100644 --- a/src/pandapipes/test/api/test_network_tables.py +++ b/src/pandapipes/test/api/test_network_tables.py @@ -24,7 +24,7 @@ def test_default_input_tables(): pipe_input = list(copy.deepcopy(net.pipe.columns)) pandapipes.create_pipe_from_parameters(net, 0, 1, 6, diameter_m=0.2, k_mm=.1, sections=6, - alpha_w_per_m2k=5) + u_w_per_m2k=5) pipe_input_create = list(net.pipe.columns) assert pipe_input == pipe_input_create, "Input does not equal Table in create-function" @@ -77,7 +77,7 @@ def test_additional_tables(): pandapipes.add_new_component(net, HeatExchanger) hex_input = list(copy.deepcopy(net.heat_exchanger.columns)) - pandapipes.create_heat_exchanger(net, 0, 1, 0.2, qext_w=20000) + pandapipes.create_heat_exchanger(net, 0, 1, qext_w=20000) hex_input_create = list(net.heat_exchanger.columns) assert hex_input == hex_input_create, "Input does not equal create-table" diff --git a/src/pandapipes/test/api/test_special_networks.py b/src/pandapipes/test/api/test_special_networks.py index 90e63497b..b04769f87 100644 --- a/src/pandapipes/test/api/test_special_networks.py +++ b/src/pandapipes/test/api/test_special_networks.py @@ -28,7 +28,7 @@ def test_one_node_net(use_numba): create_sink(net, j, 0.01) create_source(net, j, 0.02) - max_iter_hyd = 1 if use_numba else 1 + max_iter_hyd = 2 if use_numba else 2 pandapipes.pipeflow(net, use_numba=use_numba, max_iter_hyd=max_iter_hyd) assert np.isclose(net.res_ext_grid.values + net.res_sink.values - net.res_source.values, 0) @@ -60,7 +60,7 @@ def test_two_node_net(use_numba): create_ext_grid(net, j, 1, 298.15) create_sink(net, j, 0.01) create_source(net, j, 0.02) - max_iter_hyd = 1 if use_numba else 1 + max_iter_hyd = 2 if use_numba else 2 pandapipes.pipeflow(net, use_numba=use_numba, max_iter_hyd=max_iter_hyd) assert np.all(np.isclose(net.res_ext_grid.values + net.res_sink.values - net.res_source.values, diff --git a/src/pandapipes/test/api/test_std_types.py b/src/pandapipes/test/api/test_std_types.py index b65da82d9..a912bcb98 100644 --- a/src/pandapipes/test/api/test_std_types.py +++ b/src/pandapipes/test/api/test_std_types.py @@ -305,10 +305,11 @@ def test_available_std_types(): do = 99.5 di = 87.5 rat = 16.33 + u = 10 mat = "GGG" typdata = {"standard_dimension_ratio": rat, "material": mat, "inner_diameter_mm": di, - "outer_diameter_mm": do, "nominal_width_mm": w} + "outer_diameter_mm": do, "nominal_width_mm": w, "u_w_per_m2k":u} typdatas = {"typ1": typdata, "typ2": typdata} pandapipes.create_std_types(net, component="pipe", type_dict=typdatas) diff --git a/src/pandapipes/test/api/test_time_series.py b/src/pandapipes/test/api/test_time_series.py index b565cbaae..2045ec107 100644 --- a/src/pandapipes/test/api/test_time_series.py +++ b/src/pandapipes/test/api/test_time_series.py @@ -13,9 +13,9 @@ def person_run_fct(net, sol_vec=None, **kwargs): net = ntw.water_strand_net_2pumps() max_iter_hyd = 3 max_iter_therm = 1 - pps.pipeflow(net, mode='all', max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm) + pps.pipeflow(net, mode='sequential', max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm) assert all(np.isclose(net.res_junction.p_bar.values, [7., 25.02309542, 24.73038636, 22.11851835, 16.70728061, 16.23637491])) run_timeseries(net, time_steps=range(10), max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, - mode='all', run=person_run_fct) + mode='sequential', run=person_run_fct) assert all(net.output_writer.iat[0, 0].np_results['res_junction.p_bar'].flatten() == 15.) diff --git a/src/pandapipes/test/openmodelica_comparison/pipeflow_openmodelica_comparison.py b/src/pandapipes/test/openmodelica_comparison/pipeflow_openmodelica_comparison.py index c70eaa1c0..9169f7864 100644 --- a/src/pandapipes/test/openmodelica_comparison/pipeflow_openmodelica_comparison.py +++ b/src/pandapipes/test/openmodelica_comparison/pipeflow_openmodelica_comparison.py @@ -171,14 +171,8 @@ def retrieve_velocity_liquid(net, element="pipe"): v_valid = pd.notnull(v_om) v_om = v_om.loc[v_valid] v_om[v_om == 0] += 0.0001 - - if element == "pipe": - v_mean_pandapipes = net.res_pipe.v_mean_m_per_s.loc[v_valid].values.astype( - np.float64).round(4) - - if element == "valve": - v_mean_pandapipes = net.res_valve.v_mean_m_per_s.loc[v_valid].values.astype( - np.float64).round(4) + v_mean_pandapipes = net['res_%s' %element].v_mean_m_per_s.loc[v_valid].values.astype( + np.float64).round(4) v_mean_pandapipes[v_mean_pandapipes == 0] += 0.0001 diff --git a/src/pandapipes/test/openmodelica_comparison/test_heat_transfer_openmodelica.py b/src/pandapipes/test/openmodelica_comparison/test_heat_transfer_openmodelica.py index 03c7ab523..74c9f5bf7 100644 --- a/src/pandapipes/test/openmodelica_comparison/test_heat_transfer_openmodelica.py +++ b/src/pandapipes/test/openmodelica_comparison/test_heat_transfer_openmodelica.py @@ -28,7 +28,7 @@ def test_case_delta(use_numba, log_results=False): p_diff, v_diff_abs, temp_diff_mean = pipeflow_openmodelica_comparison( net, log_results, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, - mode="all", use_numba=use_numba) + mode='sequential', use_numba=use_numba) assert np.all(temp_diff_mean < 0.007) assert np.all(p_diff < 0.05) assert np.all(v_diff_abs < 0.05) @@ -42,7 +42,7 @@ def test_case_delta_2sinks(use_numba, log_results=False): p_diff, v_diff_abs, temp_diff_mean = pipeflow_openmodelica_comparison( net, log_results, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, - mode="all", use_numba=use_numba) + mode='sequential', use_numba=use_numba) assert np.all(temp_diff_mean < 0.007) assert np.all(p_diff < 0.02) assert np.all(v_diff_abs < 0.05) @@ -56,7 +56,7 @@ def test_case_heights(use_numba, log_results=False): p_diff, v_diff_abs, temp_diff_mean = pipeflow_openmodelica_comparison( net, log_results, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, - mode="all", use_numba=use_numba) + mode='sequential', use_numba=use_numba) assert np.all(temp_diff_mean < 0.0065) assert np.all(p_diff < 0.02) assert np.all(v_diff_abs < 0.05) @@ -70,7 +70,7 @@ def test_case_one_pipe(use_numba, log_results=False): p_diff, v_diff_abs, temp_diff_mean = pipeflow_openmodelica_comparison( net, log_results, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, - mode="all", use_numba=use_numba) + mode='sequential', use_numba=use_numba) assert np.all(temp_diff_mean < 0.004) assert np.all(p_diff < 0.01) assert np.all(v_diff_abs < 0.05) @@ -84,7 +84,7 @@ def test_case_one_source(use_numba, log_results=False): p_diff, v_diff_abs, temp_diff_mean = pipeflow_openmodelica_comparison( net, log_results, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, - mode="all", use_numba=use_numba) + mode='sequential', use_numba=use_numba) assert np.all(temp_diff_mean < 0.04) assert np.all(p_diff < 0.01) assert np.all(v_diff_abs < 0.05) @@ -98,7 +98,7 @@ def test_case_section_variation(use_numba, log_results=False): p_diff, v_diff_abs, temp_diff_mean = pipeflow_openmodelica_comparison( net, log_results, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, - mode="all", use_numba=use_numba) + mode='sequential', use_numba=use_numba) # all values of temp_diff_mean are zero except one with about 0.025 assert np.all(temp_diff_mean < 0.03) assert np.all(p_diff < 0.022) @@ -113,7 +113,7 @@ def test_case_t_cross(use_numba, log_results=False): p_diff, v_diff_abs, temp_diff_mean = pipeflow_openmodelica_comparison( net, log_results, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, - mode="all", use_numba=use_numba) + mode='sequential', use_numba=use_numba) assert np.all(temp_diff_mean < 0.007) assert np.all(p_diff < 0.01) assert np.all(v_diff_abs < 0.05) @@ -127,7 +127,7 @@ def test_case_two_pipes(use_numba, log_results=False): p_diff, v_diff_abs, temp_diff_mean = pipeflow_openmodelica_comparison( net, log_results, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, - mode="all", use_numba=use_numba) + mode='sequential', use_numba=use_numba) assert np.all(temp_diff_mean < 0.004) assert np.all(p_diff < 0.01) assert np.all(v_diff_abs < 0.05) diff --git a/src/pandapipes/test/openmodelica_comparison/test_water_openmodelica.py b/src/pandapipes/test/openmodelica_comparison/test_water_openmodelica.py index da8de0c4d..982fac1b7 100644 --- a/src/pandapipes/test/openmodelica_comparison/test_water_openmodelica.py +++ b/src/pandapipes/test/openmodelica_comparison/test_water_openmodelica.py @@ -46,7 +46,7 @@ def test_case_combined_mixed_sj(use_numba, log_results=False): @pytest.mark.parametrize("use_numba", [True, False]) def test_case_combined_versatility_pc(use_numba, log_results=False): net = nw.water_combined_versatility() - max_iter_hyd = 14 if use_numba else 14 + max_iter_hyd = 15 if use_numba else 15 p_diff, v_diff_abs = pipeflow_openmodelica_comparison( net, log_results, max_iter_hyd=max_iter_hyd, @@ -58,7 +58,7 @@ def test_case_combined_versatility_pc(use_numba, log_results=False): @pytest.mark.parametrize("use_numba", [True, False]) def test_case_combined_versatility_sj(use_numba, log_results=False): net = nw.water_combined_versatility(method="swamee-jain") - max_iter_hyd = 14 if use_numba else 14 + max_iter_hyd = 15 if use_numba else 15 p_diff, v_diff_abs = pipeflow_openmodelica_comparison( net, log_results, max_iter_hyd=max_iter_hyd, diff --git a/src/pandapipes/test/pipeflow_internals/test_inservice.py b/src/pandapipes/test/pipeflow_internals/test_inservice.py index 29ba322fe..6827e9233 100644 --- a/src/pandapipes/test/pipeflow_internals/test_inservice.py +++ b/src/pandapipes/test/pipeflow_internals/test_inservice.py @@ -40,13 +40,13 @@ def create_test_net(): pandapipes.create_ext_grid(net, j1, 1, 285.15, type="pt") - pandapipes.create_pipe_from_parameters(net, j1, j2, 0.1, 0.1, sections=1, alpha_w_per_m2k=5) - pandapipes.create_pipe_from_parameters(net, j2, j3, 0.1, 0.1, sections=2, alpha_w_per_m2k=5, + pandapipes.create_pipe_from_parameters(net, j1, j2, 0.1, 0.1, sections=1, u_w_per_m2k=5) + pandapipes.create_pipe_from_parameters(net, j2, j3, 0.1, 0.1, sections=2, u_w_per_m2k=5, in_service=False) - pandapipes.create_pipe_from_parameters(net, j4, j6, 0.1, 0.1, sections=2, alpha_w_per_m2k=5) - pandapipes.create_pipe_from_parameters(net, j6, j7, 0.1, 0.1, sections=1, alpha_w_per_m2k=5, + pandapipes.create_pipe_from_parameters(net, j4, j6, 0.1, 0.1, sections=2, u_w_per_m2k=5) + pandapipes.create_pipe_from_parameters(net, j6, j7, 0.1, 0.1, sections=1, u_w_per_m2k=5, in_service=False) - pandapipes.create_pipe_from_parameters(net, j1, j5, 0.1, 0.1, sections=2, alpha_w_per_m2k=5) + pandapipes.create_pipe_from_parameters(net, j1, j5, 0.1, 0.1, sections=2, u_w_per_m2k=5) pandapipes.create_valve(net, j1, j4, 0.1) pandapipes.create_valve(net, j4, j5, 0.1, opened=False) @@ -80,17 +80,17 @@ def complex_heat_connectivity_grid(): pandapipes.create_ext_grid(net, j7, 1, 320.15, type="t", index=2) pandapipes.create_ext_grid(net, j10, 1, 320.15, type="pt", index=1) - pandapipes.create_pipe_from_parameters(net, j1, j2, 0.1, 0.1, alpha_w_per_m2k=5, index=3) - pandapipes.create_pipe_from_parameters(net, j1, j3, 0.1, 0.1, alpha_w_per_m2k=5, index=4) - pandapipes.create_pipe_from_parameters(net, j2, j4, 0.1, 0.1, alpha_w_per_m2k=5, + pandapipes.create_pipe_from_parameters(net, j1, j2, 0.1, 0.1, u_w_per_m2k=5, index=3) + pandapipes.create_pipe_from_parameters(net, j1, j3, 0.1, 0.1, u_w_per_m2k=5, index=4) + pandapipes.create_pipe_from_parameters(net, j2, j4, 0.1, 0.1, u_w_per_m2k=5, in_service=False, index=5) - pandapipes.create_pipe_from_parameters(net, j3, j5, 0.1, 0.1, alpha_w_per_m2k=5, + pandapipes.create_pipe_from_parameters(net, j3, j5, 0.1, 0.1, u_w_per_m2k=5, in_service=False, index=7) - pandapipes.create_pipe_from_parameters(net, j6, j7, 0.1, 0.1, alpha_w_per_m2k=5, index=9) - pandapipes.create_pipe_from_parameters(net, j5, j8, 0.1, 0.1, alpha_w_per_m2k=5, + pandapipes.create_pipe_from_parameters(net, j6, j7, 0.1, 0.1, u_w_per_m2k=5, index=9) + pandapipes.create_pipe_from_parameters(net, j5, j8, 0.1, 0.1, u_w_per_m2k=5, in_service=False, index=8) - pandapipes.create_pipe_from_parameters(net, j8, j10, 0.1, 0.1, alpha_w_per_m2k=5, index=1) - pandapipes.create_pipe_from_parameters(net, j9, j10, 0.1, 0.1, alpha_w_per_m2k=5, index=2) + pandapipes.create_pipe_from_parameters(net, j8, j10, 0.1, 0.1, u_w_per_m2k=5, index=1) + pandapipes.create_pipe_from_parameters(net, j9, j10, 0.1, 0.1, u_w_per_m2k=5, index=2) pandapipes.create_valve(net, j5, j6, 0.1, index=10) pandapipes.create_valve(net, j4, j5, 0.1, opened=False, index=12) @@ -139,7 +139,7 @@ def create_net_wo_ext_grid(): name="Junction 10", in_service=True, type="junction", geodata=(2, 0)) pandapipes.create_pipe_from_parameters(net, 9, 10, length_km=1, diameter_m=0.03, k_mm=.1, sections=10, - alpha_w_per_m2k=1, name="Pipe 6") + u_w_per_m2k=1, name="Pipe 6") pandapipes.create_sink(net, 9, mdot_kg_per_s=0.01, name="Sink 3") pandapipes.create_source(net, junction=10, mdot_kg_per_s=0.04, name="Source 3") pandapipes.create_compressor(net, from_junction=9, to_junction=3, pressure_ratio=1.1, @@ -306,7 +306,7 @@ def test_connectivity_heat1(complex_heat_connectivity_grid, use_numba): max_iter_hyd = 3 if use_numba else 3 max_iter_therm = 3 if use_numba else 3 pandapipes.pipeflow(net, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, - mode="all", check_connectivity=True, use_numba=use_numba) + mode='sequential', check_connectivity=True, use_numba=use_numba) oos_juncs_hyd = {4, 5, 6, 7} oos_pipe_hyd = {5, 7, 8, 9} @@ -346,7 +346,7 @@ def test_connectivity_heat2(complex_heat_connectivity_grid, use_numba): max_iter_hyd = 3 if use_numba else 3 max_iter_therm = 5 if use_numba else 5 pandapipes.pipeflow(net, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, - mode="all", check_connectivity=True, use_numba=use_numba) + mode='sequential', check_connectivity=True, use_numba=use_numba) assert set(net.res_junction.loc[net.res_junction.p_bar.isnull()].index) == {4} assert set(net.res_junction.loc[net.res_junction.p_bar.notnull()].index) \ @@ -379,7 +379,7 @@ def test_connectivity_heat3(complex_heat_connectivity_grid, use_numba): max_iter_hyd = 3 if use_numba else 3 max_iter_therm = 4 if use_numba else 4 pandapipes.pipeflow(net, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, - mode="all", check_connectivity=True, use_numba=use_numba) + mode='sequential', check_connectivity=True, use_numba=use_numba) assert set(net.res_junction.loc[net.res_junction.p_bar.isnull()].index) == set() assert set(net.res_junction.loc[net.res_junction.p_bar.notnull()].index) \ @@ -408,16 +408,16 @@ def test_connectivity_heat4(complex_heat_connectivity_grid, use_numba): net.pipe.loc[[7, 8], 'in_service'] = True j_new = pandapipes.create_junction(net, 1, 320.15) - pandapipes.create_pipe_from_parameters(net, 8, j_new, 0.1, 0.1, alpha_w_per_m2k=5) + pandapipes.create_pipe_from_parameters(net, 8, j_new, 0.1, 0.1, u_w_per_m2k=5) net2 = copy.deepcopy(net) - max_iter_hyd = 9 if use_numba else 9 + max_iter_hyd = 10 if use_numba else 10 max_iter_therm = 6 if use_numba else 6 pandapipes.pipeflow(net, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, - mode="all", check_connectivity=True, use_numba=use_numba) + mode='sequential', check_connectivity=True, use_numba=use_numba) pandapipes.pipeflow(net2, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, - mode="all", check_connectivity=False, use_numba=use_numba) + mode='sequential', check_connectivity=False, use_numba=use_numba) assert pandapipes.nets_equal(net, net2, check_only_results=True) @@ -429,21 +429,21 @@ def test_connectivity_heat5(complex_heat_connectivity_grid, use_numba): j_from, j_to = pandapipes.create_junctions(net, 2, 1, 320.15) - pandapipes.create_pipe_from_parameters(net, j_from, j_to, 0.1, 0.1, alpha_w_per_m2k=5) + pandapipes.create_pipe_from_parameters(net, j_from, j_to, 0.1, 0.1, u_w_per_m2k=5) pandapipes.create_sink(net, j_to, 0.1) pandapipes.create_ext_grid(net, j_from, 1, 320.15) net.ext_grid.loc[2, 'in_service'] = False net.ext_grid.loc[1, 'type'] = 'p' - max_iter_hyd = 9 if use_numba else 9 + max_iter_hyd = 10 if use_numba else 10 max_iter_therm = 3 if use_numba else 3 pandapipes.pipeflow(net, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, - check_connectivity=True, mode='all', use_numba=use_numba) + check_connectivity=True, mode='sequential', use_numba=use_numba) with pytest.raises(PipeflowNotConverged): pandapipes.pipeflow(net, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, - check_connectivity=False, mode='all', use_numba=use_numba) + check_connectivity=False, mode='sequential', use_numba=use_numba) @pytest.mark.parametrize("use_numba", [True, False]) @@ -669,7 +669,7 @@ def test_pipeflow_all_oos(create_net_wo_ext_grid, use_numba): assert net.converged with pytest.raises(PipeflowNotConverged): - pandapipes.pipeflow(net, mode='all', max_iter_hyd=max_iter_hyd, + pandapipes.pipeflow(net, mode='sequential', max_iter_hyd=max_iter_hyd, tol_p=1e-7, tol_m=1e-7, friction_model="nikuradse", use_numba=use_numba, check_connectivity=True) assert ~net.converged diff --git a/src/pandapipes/test/pipeflow_internals/test_options.py b/src/pandapipes/test/pipeflow_internals/test_options.py index 416ac7de2..59b42f7c7 100644 --- a/src/pandapipes/test/pipeflow_internals/test_options.py +++ b/src/pandapipes/test/pipeflow_internals/test_options.py @@ -84,29 +84,29 @@ def test_iter(create_test_net, use_numba): pandapipes.set_user_pf_options(net, iter=2) with pytest.raises(PipeflowNotConverged): - pandapipes.pipeflow(net, mode='all') + pandapipes.pipeflow(net, mode='sequential') pandapipes.pipeflow(net, mode='hydraulics', max_iter_hyd=max_iter_hyd) with pytest.raises(PipeflowNotConverged): - pandapipes.pipeflow(net, mode='all', max_iter_hyd=max_iter_hyd) + pandapipes.pipeflow(net, mode='sequential', max_iter_hyd=max_iter_hyd) - pandapipes.pipeflow(net, mode='all', max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm) + pandapipes.pipeflow(net, mode='sequential', max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm) pandapipes.set_user_pf_options(net, max_iter_hyd=max_iter_hyd) pandapipes.pipeflow(net, mode='hydraulics') with pytest.raises(PipeflowNotConverged): - pandapipes.pipeflow(net, mode='all') + pandapipes.pipeflow(net, mode='sequential') pandapipes.set_user_pf_options(net, max_iter_therm=max_iter_therm) - pandapipes.pipeflow(net, mode='all') + pandapipes.pipeflow(net, mode='sequential') pandapipes.set_user_pf_options(net, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm) with pytest.raises(PipeflowNotConverged): - pandapipes.pipeflow(net, mode='all', iter=2) + pandapipes.pipeflow(net, mode='sequential', iter=2) if __name__ == '__main__': diff --git a/src/pandapipes/test/pipeflow_internals/test_pipeflow_analytic_comparison.py b/src/pandapipes/test/pipeflow_internals/test_pipeflow_analytic_comparison.py index 44d85e71f..1212961ad 100644 --- a/src/pandapipes/test/pipeflow_internals/test_pipeflow_analytic_comparison.py +++ b/src/pandapipes/test/pipeflow_internals/test_pipeflow_analytic_comparison.py @@ -17,6 +17,41 @@ from pandapipes.test import data_path +def create_source_2pipes_sink( + net, + t_source_k, + t_junctions_k, + mdot_kg_per_s, + length_km, + diameter_m, + pipe_name_suffix="", + k_mm=0.1, +): + j1, j2, j3 = pandapipes.create_junctions( + net, nr_junctions=3, pn_bar=1, tfluid_k=t_junctions_k + ) + pandapipes.create_pipe_from_parameters( + net, + from_junction=j1, + to_junction=j2, + name="pipe1" + pipe_name_suffix, + length_km=length_km, + diameter_m=diameter_m, + k_mm=k_mm, + ) + pandapipes.create_pipe_from_parameters( + net, + from_junction=j2, + to_junction=j3, + name="pipe2" + pipe_name_suffix, + length_km=length_km, + diameter_m=diameter_m, + k_mm=k_mm, + ) + pandapipes.create_ext_grid(net, junction=j1, p_bar=10, t_k=t_source_k) + pandapipes.create_sink(net, junction=j3, mdot_kg_per_s=mdot_kg_per_s) + + @pytest.mark.parametrize("use_numba", [True, False]) def test_gas_internal_nodes(use_numba): """ @@ -28,23 +63,42 @@ def test_gas_internal_nodes(use_numba): d = 209.1e-3 pandapipes.create_junction(net, pn_bar=51, tfluid_k=285.15) pandapipes.create_junction(net, pn_bar=51, tfluid_k=285.15) - pandapipes.create_pipe_from_parameters(net, 0, 1, 12.0, d, k_mm=.5, sections=12) + pandapipes.create_pipe_from_parameters(net, 0, 1, 12.0, d, k_mm=0.5, sections=12) pandapipes.create_ext_grid(net, 0, p_bar=51 - 1.01325, t_k=285.15, type="pt") pandapipes.create_sink(net, 1, mdot_kg_per_s=0.82752 * 45000 / 3600) - _add_fluid_to_net(net, pandapipes.create_constant_fluid( - name="natural_gas", fluid_type="gas", viscosity=11.93e-6, heat_capacity=2185, - compressibility=1, der_compressibility=0, density=0.82752 - )) + _add_fluid_to_net( + net, + pandapipes.create_constant_fluid( + name="natural_gas", + fluid_type="gas", + viscosity=11.93e-6, + heat_capacity=2185, + compressibility=1, + der_compressibility=0, + density=0.82752, + ), + ) max_iter_hyd = 6 if use_numba else 6 - pandapipes.pipeflow(net, max_iter_hyd=max_iter_hyd, - stop_condition="tol", friction_model="nikuradse", - transient=False, nonlinear_method="automatic", tol_p=1e-4, tol_m=1e-4, - use_numba=use_numba) + pandapipes.pipeflow( + net, + max_iter_hyd=max_iter_hyd, + stop_condition="tol", + friction_model="nikuradse", + transient=False, + nonlinear_method="automatic", + tol_p=1e-4, + tol_m=1e-4, + use_numba=use_numba, + ) pipe_results = Pipe.get_internal_results(net, [0]) - data = pd.read_csv(os.path.join(data_path, "gas_sections_an.csv"), sep=';', header=0, - keep_default_na=False) + data = pd.read_csv( + os.path.join(data_path, "gas_sections_an.csv"), + sep=";", + header=0, + keep_default_na=False, + ) p_an = data["p1"] / 1e5 v_an = data["v"] v_an = v_an.drop([0]) @@ -85,7 +139,9 @@ def test_temperature_internal_nodes_single_pipe(use_numba): d = 75e-3 pandapipes.create_junction(net, pn_bar=5, tfluid_k=283) pandapipes.create_junction(net, pn_bar=5, tfluid_k=283) - pandapipes.create_pipe_from_parameters(net, 0, 1, 6, d, k_mm=.1, sections=6, alpha_w_per_m2k=5) + pandapipes.create_pipe_from_parameters( + net, 0, 1, 6, d, k_mm=0.1, sections=6, u_w_per_m2k=5 + ) pandapipes.create_ext_grid(net, 0, p_bar=5, t_k=330, type="pt") pandapipes.create_sink(net, 1, mdot_kg_per_s=1) @@ -93,15 +149,28 @@ def test_temperature_internal_nodes_single_pipe(use_numba): max_iter_hyd = 3 if use_numba else 3 max_iter_therm = 4 if use_numba else 4 - pandapipes.pipeflow(net, stop_condition="tol", max_iter_hyd=max_iter_hyd, - max_iter_therm=max_iter_therm, friction_model="nikuradse", - mode="all", transient=False, nonlinear_method="automatic", tol_p=1e-4, - tol_m=1e-4, use_numba=use_numba) + pandapipes.pipeflow( + net, + stop_condition="tol", + max_iter_hyd=max_iter_hyd, + max_iter_therm=max_iter_therm, + friction_model="nikuradse", + mode="sequential", + transient=False, + nonlinear_method="automatic", + tol_p=1e-4, + tol_m=1e-4, + use_numba=use_numba, + ) pipe_results = Pipe.get_internal_results(net, [0]) - data = pd.read_csv(os.path.join(data_path, "Temperature_one_pipe_an.csv"), sep=';', - header=0, keep_default_na=False) + data = pd.read_csv( + os.path.join(data_path, "Temperature_one_pipe_an.csv"), + sep=";", + header=0, + keep_default_na=False, + ) temp_an = data["T"] pipe_temp_data_idx = np.where(pipe_results["TINIT"][:, 0] == 0) @@ -140,21 +209,34 @@ def test_temperature_internal_nodes_tee_2ab_1zu(use_numba): pandapipes.create_sink(net, j2, mdot_kg_per_s=1) pandapipes.create_sink(net, j3, mdot_kg_per_s=1) - pandapipes.create_pipe_from_parameters(net, j0, j1, 2.5, d, k_mm=.1, alpha_w_per_m2k=5) - pandapipes.create_pipe_from_parameters(net, j1, j2, 2.5, d, k_mm=.1, alpha_w_per_m2k=5) - pandapipes.create_pipe_from_parameters(net, j1, j3, 2.5, d, k_mm=.1, alpha_w_per_m2k=5) + pandapipes.create_pipe_from_parameters(net, j0, j1, 2.5, d, k_mm=0.1, u_w_per_m2k=5) + pandapipes.create_pipe_from_parameters(net, j1, j2, 2.5, d, k_mm=0.1, u_w_per_m2k=5) + pandapipes.create_pipe_from_parameters(net, j1, j3, 2.5, d, k_mm=0.1, u_w_per_m2k=5) pandapipes.create_fluid_from_lib(net, "water", overwrite=True) max_iter_hyd = 4 if use_numba else 4 max_iter_therm = 4 if use_numba else 4 - pandapipes.pipeflow(net, stop_condition="tol", max_iter_hyd=max_iter_hyd, - max_iter_therm=max_iter_therm, friction_model="nikuradse", - mode='all', transient=False, nonlinear_method="automatic", tol_p=1e-4, - tol_m=1e-4, use_numba=use_numba) - - data = pd.read_csv(os.path.join(data_path, "Temperature_tee_2ab_1zu_an.csv"), - sep=';', header=0, keep_default_na=False) + pandapipes.pipeflow( + net, + stop_condition="tol", + max_iter_hyd=max_iter_hyd, + max_iter_therm=max_iter_therm, + friction_model="nikuradse", + mode="sequential", + transient=False, + nonlinear_method="automatic", + tol_p=1e-4, + tol_m=1e-4, + use_numba=use_numba, + ) + + data = pd.read_csv( + os.path.join(data_path, "Temperature_tee_2ab_1zu_an.csv"), + sep=";", + header=0, + keep_default_na=False, + ) temp_an = data["T"] temp_pandapipes = net.res_junction["t_k"] @@ -177,12 +259,15 @@ def test_temperature_internal_nodes_tee_2zu_1ab(use_numba): j2 = pandapipes.create_junction(net, pn_bar=5, tfluid_k=283) j3 = pandapipes.create_junction(net, pn_bar=5, tfluid_k=283) - pandapipes.create_pipe_from_parameters(net, j0, j2, 2.5, d, k_mm=.1, sections=3, - alpha_w_per_m2k=5) - pandapipes.create_pipe_from_parameters(net, j1, j2, 2.5, d, k_mm=.1, sections=3, - alpha_w_per_m2k=5) - pandapipes.create_pipe_from_parameters(net, j2, j3, 2.5, d, k_mm=.1, sections=3, - alpha_w_per_m2k=5) + pandapipes.create_pipe_from_parameters( + net, j0, j2, 2.5, d, k_mm=0.1, sections=3, u_w_per_m2k=5 + ) + pandapipes.create_pipe_from_parameters( + net, j1, j2, 2.5, d, k_mm=0.1, sections=3, u_w_per_m2k=5 + ) + pandapipes.create_pipe_from_parameters( + net, j2, j3, 2.5, d, k_mm=0.1, sections=3, u_w_per_m2k=5 + ) pandapipes.create_ext_grid(net, j0, p_bar=5, t_k=350, type="pt") pandapipes.create_ext_grid(net, j1, p_bar=5, t_k=350, type="pt") pandapipes.create_sink(net, j3, mdot_kg_per_s=1) @@ -191,13 +276,26 @@ def test_temperature_internal_nodes_tee_2zu_1ab(use_numba): max_iter_hyd = 3 if use_numba else 3 max_iter_therm = 4 if use_numba else 4 - pandapipes.pipeflow(net, stop_condition="tol", max_iter_hyd=max_iter_hyd, - max_iter_therm=max_iter_therm, friction_model="nikuradse", - mode='all', transient=False, nonlinear_method="automatic", tol_p=1e-4, - tol_m=1e-4, use_numba=use_numba) - - data = pd.read_csv(os.path.join(data_path, "Temperature_tee_2zu_1ab_an.csv"), - sep=';', header=0, keep_default_na=False) + pandapipes.pipeflow( + net, + stop_condition="tol", + max_iter_hyd=max_iter_hyd, + max_iter_therm=max_iter_therm, + friction_model="nikuradse", + mode="sequential", + transient=False, + nonlinear_method="automatic", + tol_p=1e-4, + tol_m=1e-4, + use_numba=use_numba, + ) + + data = pd.read_csv( + os.path.join(data_path, "Temperature_tee_2zu_1ab_an.csv"), + sep=";", + header=0, + keep_default_na=False, + ) temp_an = data["T"] temp_pandapipes = net.res_junction["t_k"] @@ -223,24 +321,40 @@ def test_temperature_internal_nodes_tee_2zu_1ab_direction_changed(use_numba): pandapipes.create_ext_grid(net, j1, p_bar=5, t_k=350, type="pt") pandapipes.create_sink(net, j3, mdot_kg_per_s=1) - pandapipes.create_pipe_from_parameters(net, j0, j2, 2.5, d, k_mm=.1, sections=5, - alpha_w_per_m2k=5) - pandapipes.create_pipe_from_parameters(net, j2, j1, 2.5, d, k_mm=.1, sections=5, - alpha_w_per_m2k=5) - pandapipes.create_pipe_from_parameters(net, j2, j3, 2.5, d, k_mm=.1, sections=5, - alpha_w_per_m2k=5) + pandapipes.create_pipe_from_parameters( + net, j0, j2, 2.5, d, k_mm=0.1, sections=5, u_w_per_m2k=5 + ) + pandapipes.create_pipe_from_parameters( + net, j2, j1, 2.5, d, k_mm=0.1, sections=5, u_w_per_m2k=5 + ) + pandapipes.create_pipe_from_parameters( + net, j2, j3, 2.5, d, k_mm=0.1, sections=5, u_w_per_m2k=5 + ) pandapipes.create_fluid_from_lib(net, "water", overwrite=True) max_iter_hyd = 6 if use_numba else 6 max_iter_therm = 4 if use_numba else 4 - pandapipes.pipeflow(net, stop_condition="tol", max_iter_hyd=max_iter_hyd, - max_iter_therm=max_iter_therm, friction_model="nikuradse", - mode='all', transient=False, nonlinear_method="automatic", tol_p=1e-4, - tol_m=1e-4, use_numba=use_numba) - - data = pd.read_csv(os.path.join(data_path, "Temperature_tee_2zu_1ab_an.csv"), - sep=';', header=0, keep_default_na=False) + pandapipes.pipeflow( + net, + stop_condition="tol", + max_iter_hyd=max_iter_hyd, + max_iter_therm=max_iter_therm, + friction_model="nikuradse", + mode="sequential", + transient=False, + nonlinear_method="automatic", + tol_p=1e-4, + tol_m=1e-4, + use_numba=use_numba, + ) + + data = pd.read_csv( + os.path.join(data_path, "Temperature_tee_2zu_1ab_an.csv"), + sep=";", + header=0, + keep_default_na=False, + ) temp_an = data["T"] temp_pandapipes = net.res_junction["t_k"] @@ -268,22 +382,35 @@ def test_temperature_internal_nodes_2zu_2ab(use_numba): pandapipes.create_sink(net, j3, mdot_kg_per_s=1) pandapipes.create_sink(net, j4, mdot_kg_per_s=1) - pandapipes.create_pipe_from_parameters(net, j0, j2, 2.5, d, k_mm=.1, alpha_w_per_m2k=5) - pandapipes.create_pipe_from_parameters(net, j1, j2, 2.5, d, k_mm=.1, alpha_w_per_m2k=5) - pandapipes.create_pipe_from_parameters(net, j2, j3, 2.5, d, k_mm=.1, alpha_w_per_m2k=5) - pandapipes.create_pipe_from_parameters(net, j2, j4, 2.5, d, k_mm=.1, alpha_w_per_m2k=5) + pandapipes.create_pipe_from_parameters(net, j0, j2, 2.5, d, k_mm=0.1, u_w_per_m2k=5) + pandapipes.create_pipe_from_parameters(net, j1, j2, 2.5, d, k_mm=0.1, u_w_per_m2k=5) + pandapipes.create_pipe_from_parameters(net, j2, j3, 2.5, d, k_mm=0.1, u_w_per_m2k=5) + pandapipes.create_pipe_from_parameters(net, j2, j4, 2.5, d, k_mm=0.1, u_w_per_m2k=5) pandapipes.create_fluid_from_lib(net, "water", overwrite=True) max_iter_hyd = 3 if use_numba else 3 - max_iter_therm = 4 if use_numba else 4 - pandapipes.pipeflow(net, stop_condition="tol", max_iter_hyd=max_iter_hyd, - max_iter_therm=max_iter_therm, friction_model="nikuradse", - mode='all', transient=False, nonlinear_method="automatic", tol_p=1e-4, - tol_m=1e-4, use_numba=use_numba) - - data = pd.read_csv(os.path.join(data_path, "Temperature_2zu_2ab_an.csv"), sep=';', - header=0, keep_default_na=False) + max_iter_therm = 5 if use_numba else 5 + pandapipes.pipeflow( + net, + stop_condition="tol", + max_iter_hyd=max_iter_hyd, + max_iter_therm=max_iter_therm, + friction_model="nikuradse", + mode="sequential", + transient=False, + nonlinear_method="automatic", + tol_p=1e-4, + tol_m=1e-4, + use_numba=use_numba, + ) + + data = pd.read_csv( + os.path.join(data_path, "Temperature_2zu_2ab_an.csv"), + sep=";", + header=0, + keep_default_na=False, + ) temp_an = data["T"] temp_pandapipes = net.res_junction["t_k"] @@ -306,14 +433,18 @@ def test_temperature_internal_nodes_masche_1load(use_numba): j2 = pandapipes.create_junction(net, pn_bar=5, tfluid_k=283) j3 = pandapipes.create_junction(net, pn_bar=5, tfluid_k=283) - pandapipes.create_pipe_from_parameters(net, j0, j1, 2.5, d, k_mm=.1, sections=6, - alpha_w_per_m2k=5) - pandapipes.create_pipe_from_parameters(net, j1, j2, 2.5, d, k_mm=.1, sections=6, - alpha_w_per_m2k=5) - pandapipes.create_pipe_from_parameters(net, j1, j3, 2.5, d, k_mm=.1, sections=6, - alpha_w_per_m2k=5) - pandapipes.create_pipe_from_parameters(net, j3, j2, 2.5, d, k_mm=.1, sections=6, - alpha_w_per_m2k=5) + pandapipes.create_pipe_from_parameters( + net, j0, j1, 2.5, d, k_mm=0.1, sections=6, u_w_per_m2k=5 + ) + pandapipes.create_pipe_from_parameters( + net, j1, j2, 2.5, d, k_mm=0.1, sections=6, u_w_per_m2k=5 + ) + pandapipes.create_pipe_from_parameters( + net, j1, j3, 2.5, d, k_mm=0.1, sections=6, u_w_per_m2k=5 + ) + pandapipes.create_pipe_from_parameters( + net, j3, j2, 2.5, d, k_mm=0.1, sections=6, u_w_per_m2k=5 + ) pandapipes.create_ext_grid(net, j0, p_bar=5, t_k=350, type="pt") pandapipes.create_sink(net, j2, mdot_kg_per_s=1) @@ -321,14 +452,27 @@ def test_temperature_internal_nodes_masche_1load(use_numba): pandapipes.create_fluid_from_lib(net, "water", overwrite=True) max_iter_hyd = 3 if use_numba else 3 - max_iter_therm = 4 if use_numba else 4 - pandapipes.pipeflow(net, stop_condition="tol", max_iter_hyd=max_iter_hyd, - max_iter_therm=max_iter_therm, friction_model="nikuradse", - mode='all', transient=False, nonlinear_method="automatic", tol_p=1e-4, - tol_m=1e-4, use_numba=use_numba) - - data = pd.read_csv(os.path.join(data_path, "Temperature_masche_1load_an.csv"), - sep=';', header=0, keep_default_na=False) + max_iter_therm = 5 if use_numba else 5 + pandapipes.pipeflow( + net, + stop_condition="tol", + max_iter_hyd=max_iter_hyd, + max_iter_therm=max_iter_therm, + friction_model="nikuradse", + mode="sequential", + transient=False, + nonlinear_method="automatic", + tol_p=1e-4, + tol_m=1e-4, + use_numba=use_numba, + ) + + data = pd.read_csv( + os.path.join(data_path, "Temperature_masche_1load_an.csv"), + sep=";", + header=0, + keep_default_na=False, + ) temp_an = data["T"] temp_pandapipes = net.res_junction["t_k"] @@ -350,12 +494,15 @@ def test_temperature_internal_nodes_masche_1load_changed_direction(use_numba): j2 = pandapipes.create_junction(net, pn_bar=5, tfluid_k=283) j3 = pandapipes.create_junction(net, pn_bar=5, tfluid_k=283) - pandapipes.create_pipe_from_parameters(net, j0, j2, 2.5, d, k_mm=.1, sections=5, - alpha_w_per_m2k=5) - pandapipes.create_pipe_from_parameters(net, j0, j3, 2.5, d, k_mm=.1, sections=5, - alpha_w_per_m2k=5) - pandapipes.create_pipe_from_parameters(net, j3, j2, 2.5, d, k_mm=.1, sections=5, - alpha_w_per_m2k=5) + pandapipes.create_pipe_from_parameters( + net, j0, j2, 2.5, d, k_mm=0.1, sections=5, u_w_per_m2k=5 + ) + pandapipes.create_pipe_from_parameters( + net, j0, j3, 2.5, d, k_mm=0.1, sections=5, u_w_per_m2k=5 + ) + pandapipes.create_pipe_from_parameters( + net, j3, j2, 2.5, d, k_mm=0.1, sections=5, u_w_per_m2k=5 + ) pandapipes.create_fluid_from_lib(net, "water", overwrite=True) @@ -364,14 +511,26 @@ def test_temperature_internal_nodes_masche_1load_changed_direction(use_numba): max_iter_hyd = 5 if use_numba else 5 max_iter_therm = 4 if use_numba else 4 - pandapipes.pipeflow(net, stop_condition="tol", max_iter_hyd=max_iter_hyd, - max_iter_therm=max_iter_therm, friction_model="nikuradse", - mode='all', transient=False, nonlinear_method="automatic", tol_p=1e-4, - tol_m=1e-4, use_numba=use_numba) - - data = pd.read_csv(os.path.join(data_path, - "Temperature_masche_1load_direction_an.csv"), - sep=';', header=0, keep_default_na=False) + pandapipes.pipeflow( + net, + stop_condition="tol", + max_iter_hyd=max_iter_hyd, + max_iter_therm=max_iter_therm, + friction_model="nikuradse", + mode="sequential", + transient=False, + nonlinear_method="automatic", + tol_p=1e-4, + tol_m=1e-4, + use_numba=use_numba, + ) + + data = pd.read_csv( + os.path.join(data_path, "Temperature_masche_1load_direction_an.csv"), + sep=";", + header=0, + keep_default_na=False, + ) temp_an = data["T"] temp_pandapipes = net.res_junction["t_k"] @@ -380,5 +539,51 @@ def test_temperature_internal_nodes_masche_1load_changed_direction(use_numba): assert np.all(temp_diff < 0.01) +def test_example_hot_water(): + mdot_kg_per_s = 10 + temps_k = [300, 350] + d_pipe = 0.1 + l_pipe = 1 + + net = pandapipes.create_empty_network("network", fluid="water") + + for t_fluid in temps_k: + for t_j_k in temps_k: + create_source_2pipes_sink( + net, + t_source_k=t_fluid, + t_junctions_k=t_j_k, + pipe_name_suffix=f"_tj_{t_j_k}_tf_{t_fluid}", + mdot_kg_per_s=mdot_kg_per_s, + diameter_m=d_pipe, + length_km=l_pipe, + ) + + pandapipes.pipeflow(net, mode="bidirectional", friction_model="colebrook") + + dp = net.res_pipe.p_from_bar - net.res_pipe.p_to_bar + + # Density (for velocity calculation) is calculated at 273.15 K, which is not the same as the actual temperature of the fluid + velocities_equal = net.res_pipe["v_mean_m_per_s"].nunique() == 1 + assert not velocities_equal + rho_from_v_mean = mdot_kg_per_s / (net.res_pipe.loc[:, "v_mean_m_per_s"] * np.pi * d_pipe**2 / 4).to_numpy() + assert np.allclose(rho_from_v_mean[[0, 4]], net.fluid.get_density(temps_k)) + + # dp is really calculated from v_mean, the default density and the various lambdas + dp_calc = ( + net.res_pipe.loc[:, "lambda"] + * l_pipe + * 1000 + / d_pipe + * 0.5 + * rho_from_v_mean + * net.res_pipe.loc[:, "v_mean_m_per_s"] ** 2 + / 10**5 + ) + assert np.allclose(dp, dp_calc) + + if __name__ == "__main__": - pytest.main([r'pandapipes/test/pipflow_internals/test_pipeflow_analytic_comparison.py']) + pytest.main( + [r"pandapipes/test/pipflow_internals/test_pipeflow_analytic_comparison.py"] + ) diff --git a/src/pandapipes/test/pipeflow_internals/test_pipeflow_modes.py b/src/pandapipes/test/pipeflow_internals/test_pipeflow_modes.py index c982dd8b4..58c86a2f5 100644 --- a/src/pandapipes/test/pipeflow_internals/test_pipeflow_modes.py +++ b/src/pandapipes/test/pipeflow_internals/test_pipeflow_modes.py @@ -25,7 +25,7 @@ def simple_test_net(): pandapipes.create_junction(net, pn_bar=5, tfluid_k=283) pandapipes.create_junction(net, pn_bar=5, tfluid_k=283) pandapipes.create_pipe_from_parameters(net, 0, 1, 6, diameter_m=d, k_mm=.1, sections=1, - alpha_w_per_m2k=5) + u_w_per_m2k=5) pandapipes.create_ext_grid(net, 0, p_bar=5, t_k=330, type="pt") pandapipes.create_sink(net, 1, mdot_kg_per_s=1) @@ -76,7 +76,7 @@ def test_heat_only(use_numba): pandapipes.create_junction(net, pn_bar=5, tfluid_k=283) pandapipes.create_junction(net, pn_bar=5, tfluid_k=283) pandapipes.create_pipe_from_parameters(net, 0, 1, 6, diameter_m=d, k_mm=.1, sections=6, - alpha_w_per_m2k=5) + u_w_per_m2k=5) pandapipes.create_ext_grid(net, 0, p_bar=5, t_k=330, type="pt") pandapipes.create_sink(net, 1, mdot_kg_per_s=1) @@ -86,14 +86,14 @@ def test_heat_only(use_numba): max_iter_therm = 4 if use_numba else 4 pandapipes.pipeflow(net, max_iter_hyd=max_iter_hyd, max_iter_therm=max_iter_therm, stop_condition="tol", friction_model="nikuradse", - nonlinear_method="automatic", mode="all", use_numba=use_numba) + nonlinear_method="automatic", mode='sequential', use_numba=use_numba) ntw = pandapipes.create_empty_network("net") d = 75e-3 pandapipes.create_junction(ntw, pn_bar=5, tfluid_k=283) pandapipes.create_junction(ntw, pn_bar=5, tfluid_k=283) pandapipes.create_pipe_from_parameters(ntw, 0, 1, 6, diameter_m=d, k_mm=.1, sections=6, - alpha_w_per_m2k=5) + u_w_per_m2k=5) pandapipes.create_ext_grid(ntw, 0, p_bar=5, t_k=330, type="pt") pandapipes.create_sink(ntw, 1, mdot_kg_per_s=1) diff --git a/src/pandapipes/test/plotting/test_collections.py b/src/pandapipes/test/plotting/test_collections.py index 5c3cd9014..c6091bb80 100644 --- a/src/pandapipes/test/plotting/test_collections.py +++ b/src/pandapipes/test/plotting/test_collections.py @@ -47,11 +47,11 @@ def test_collection_lengths(): geodata=[(4, 0), (6, 0)]) pandapipes.create_pipe_from_parameters(net, j5, j6, 0.2, diameter_m=d, k_mm=0.1, geodata=[(4, -2), (6, -2), (6, 0)]) - pandapipes.create_heat_exchanger(net, j6, j7, d, qext_w=20000) + pandapipes.create_heat_exchanger(net, j6, j7, qext_w=20000) pandapipes.create_pump_from_parameters(net, j7, j8, 'P1') pandapipes.create_pressure_control(net, j8, j9, j9, 10.) - pandapipes.create_flow_control(net, j9, j10, 0.5, 0.1) - pandapipes.create_flow_control(net, j9, j11, 0.5, 0.1, control_active=False) + pandapipes.create_flow_control(net, j9, j10, 0.5) + pandapipes.create_flow_control(net, j9, j11, 0.5, control_active=False) pipe_coll_direct = plot.create_pipe_collection(net, use_junction_geodata=True) pipe_coll_real = plot.create_pipe_collection(net) diff --git a/src/pandapipes/test/test_imports.py b/src/pandapipes/test/test_imports.py index ce19339d8..1a78a01d5 100644 --- a/src/pandapipes/test/test_imports.py +++ b/src/pandapipes/test/test_imports.py @@ -8,9 +8,14 @@ import pytest from pandapipes import pp_dir -from setuptools import find_packages +try: + from setuptools import find_packages + SETUPTOOLS_AVAILABLE = True +except ImportError: + SETUPTOOLS_AVAILABLE = False +@pytest.mark.skipif(not SETUPTOOLS_AVAILABLE, reason="setuptools not available") def test_import_packages(): all_packages = find_packages(pp_dir) for pck in all_packages: diff --git a/src/pandapipes/test/test_toolbox.py b/src/pandapipes/test/test_toolbox.py index 9d8193e49..91cefad30 100644 --- a/src/pandapipes/test/test_toolbox.py +++ b/src/pandapipes/test/test_toolbox.py @@ -264,7 +264,6 @@ def test_select_subnet(base_net_is_wo_pumps): assert len(net2["res_" + comp.table_name()]) == len(net2[comp.table_name()]) assert len(net.junction) == len(net2.junction) + 3 - def test_pit_extraction(): max_ver = max(found_versions) if version.parse(max_ver) >= version.parse(minimal_version_two_nets): @@ -275,7 +274,10 @@ def test_pit_extraction(): for name in names: filename = os.path.join(folder, "example_%s%s.json" % (max_ver, name)) net = pandapipes.from_json(filename) - max_iter_hyd = 10 if '_water' in name else 5 + if not "_gas" in name: + pandapipes.create_ext_grid(net, junction=4, p_bar=6, t_k=290, name="External Grid 2", index=None) + pandapipes.create_ext_grid(net, junction=5, p_bar=5, t_k=290, name="External Grid 3") + max_iter_hyd = 11 if '_water' in name else 5 pandapipes.pipeflow(net, max_iter_hyd=max_iter_hyd) node_table, branch_table = pandapipes.get_internal_tables_pandas(net) diff --git a/src/pandapipes/toolbox.py b/src/pandapipes/toolbox.py index e70a4bf71..610dfb0ce 100644 --- a/src/pandapipes/toolbox.py +++ b/src/pandapipes/toolbox.py @@ -8,7 +8,9 @@ import numpy as np import pandas as pd from networkx import has_path -from pandapower import get_indices, dataframes_equal, clear_result_tables +from pandapower.auxiliary import get_indices +from pandapower.toolbox import dataframes_equal +from pandapower.toolbox.result_info import clear_result_tables import pandapipes from pandapipes.component_models.abstract_models.branch_models import BranchComponent @@ -16,7 +18,7 @@ from pandapipes.create import create_empty_network from pandapipes.idx_branch import branch_cols from pandapipes.idx_node import node_cols, \ - T as TYPE_T, P as TYPE_P, PC as TYPE_PC, NONE as TYPE_NONE, L as TYPE_L + T as TYPE_T, P as TYPE_P, PC as TYPE_PC, L as TYPE_L from pandapipes.pandapipes_net import pandapipesNet from pandapipes.topology import create_nxgraph @@ -524,7 +526,7 @@ def check_pressure_controllability(net, to_junction, controlled_junction): # logger.info("dropped %d %s elements with %d switches" % (len(trafos), table, num_switches)) -pit_types = {TYPE_P: "P", TYPE_L: "L", TYPE_NONE: "NONE", TYPE_T: "T", TYPE_PC: "PC", 0: "NONE"} +pit_types = {TYPE_P: "P", TYPE_L: "L", TYPE_T: "T", TYPE_PC: "PC"} int_cols = ["FROM_NODE", "TO_NODE", "ELEMENT_IDX", "EXT_GRID_OCCURENCE", "EXT_GRID_OCCURENCE_T"] bool_cols = ["ACTIVE"] diff --git a/tutorials/circular_flow_in_a_district_heating_grid.ipynb b/tutorials/circular_flow_in_a_district_heating_grid.ipynb index a06e23669..0a57948ea 100644 --- a/tutorials/circular_flow_in_a_district_heating_grid.ipynb +++ b/tutorials/circular_flow_in_a_district_heating_grid.ipynb @@ -112,9 +112,9 @@ "outputs": [], "source": [ "pp.create_pipe_from_parameters(net, from_junction=j0, to_junction=j1, length_km=1,\n", - " diameter_m=200e-3, k_mm=.1, alpha_w_per_m2k=10, sections = 5, text_k=283)\n", + " diameter_m=200e-3, k_mm=.1, u_w_per_m2k=10, sections = 5, text_k=283)\n", "pp.create_pipe_from_parameters(net, from_junction=j2, to_junction=j3, length_km=1,\n", - " diameter_m=200e-3, k_mm=.1, alpha_w_per_m2k=10, sections = 5, text_k=283)" + " diameter_m=200e-3, k_mm=.1, u_w_per_m2k=10, sections = 5, text_k=283)" ] }, { @@ -131,7 +131,7 @@ "metadata": {}, "outputs": [], "source": [ - "pp.pipeflow(net, mode='all')" + "pp.pipeflow(net, mode='sequential')" ] }, { diff --git a/tutorials/height_difference_example.ipynb b/tutorials/height_difference_example.ipynb index 9ad39155f..eb989f3d9 100644 --- a/tutorials/height_difference_example.ipynb +++ b/tutorials/height_difference_example.ipynb @@ -33,23 +33,32 @@ }, { "cell_type": "code", - "execution_count": 1, "metadata": { - "scrolled": true + "scrolled": true, + "ExecuteTime": { + "end_time": "2024-08-19T14:00:37.229949Z", + "start_time": "2024-08-19T14:00:35.528051Z" + } }, - "outputs": [], "source": [ "import pandapipes as pp" - ] + ], + "outputs": [], + "execution_count": 1 }, { "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-19T14:00:37.270307Z", + "start_time": "2024-08-19T14:00:37.252995Z" + } + }, "source": [ "net = pp.create_empty_network(fluid=\"water\") # create an empty network" - ] + ], + "outputs": [], + "execution_count": 2 }, { "cell_type": "markdown", @@ -67,16 +76,21 @@ }, { "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-19T14:00:41.636793Z", + "start_time": "2024-08-19T14:00:41.620514Z" + } + }, "source": [ "junction1 = pp.create_junction(net, pn_bar=1.0, tfluid_k=293.15, height_m = 352, name=\"Junction 1\")\n", "junction2 = pp.create_junction(net, pn_bar=1.0, tfluid_k=293.15, height_m = 358, name=\"Junction 2\")\n", "junction3 = pp.create_junction(net, pn_bar=1.0, tfluid_k=293.15, height_m = 361, name=\"Junction 3\")\n", "junction4 = pp.create_junction(net, pn_bar=1.0, tfluid_k=293.15, height_m = 346, name=\"Junction 4\")\n", "junction5 = pp.create_junction(net, pn_bar=1.0, tfluid_k=293.15, height_m = 400, name=\"Junction 5\")" - ] + ], + "outputs": [], + "execution_count": 3 }, { "cell_type": "markdown", @@ -87,22 +101,110 @@ }, { "cell_type": "code", - "execution_count": 4, - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-19T14:00:46.600384Z", + "start_time": "2024-08-19T14:00:46.586735Z" + } + }, + "source": [ + "net.junction # show junction table" + ], "outputs": [ { "data": { - "text/plain": " name pn_bar tfluid_k height_m in_service type\n0 Junction 1 1.0 293.15 352.0 True junction\n1 Junction 2 1.0 293.15 358.0 True junction\n2 Junction 3 1.0 293.15 361.0 True junction\n3 Junction 4 1.0 293.15 346.0 True junction\n4 Junction 5 1.0 293.15 400.0 True junction", - "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
namepn_bartfluid_kheight_min_servicetype
0Junction 11.0293.15352.0Truejunction
1Junction 21.0293.15358.0Truejunction
2Junction 31.0293.15361.0Truejunction
3Junction 41.0293.15346.0Truejunction
4Junction 51.0293.15400.0Truejunction
\n
" + "text/plain": [ + " name pn_bar tfluid_k height_m in_service type\n", + "0 Junction 1 1.0 293.15 352.0 True junction\n", + "1 Junction 2 1.0 293.15 358.0 True junction\n", + "2 Junction 3 1.0 293.15 361.0 True junction\n", + "3 Junction 4 1.0 293.15 346.0 True junction\n", + "4 Junction 5 1.0 293.15 400.0 True junction" + ], + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namepn_bartfluid_kheight_min_servicetype
0Junction 11.0293.15352.0Truejunction
1Junction 21.0293.15358.0Truejunction
2Junction 31.0293.15361.0Truejunction
3Junction 41.0293.15346.0Truejunction
4Junction 51.0293.15400.0Truejunction
\n", + "
" + ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], - "source": [ - "net.junction # show junction table" - ] + "execution_count": 4 }, { "cell_type": "markdown", @@ -127,24 +229,72 @@ }, { "cell_type": "code", - "execution_count": 5, - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-19T14:00:49.779695Z", + "start_time": "2024-08-19T14:00:49.770055Z" + } + }, + "source": [ + "medium_pressure_grid = pp.create_ext_grid(net, junction=junction5, p_bar=0.5, t_k=293.15, name=\"Grid Connection\")\n", + "\n", + "net.ext_grid # show external grid table" + ], "outputs": [ { "data": { - "text/plain": " name junction p_bar t_k in_service type\n0 Grid Connection 4 0.5 293.15 True pt", - "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
namejunctionp_bart_kin_servicetype
0Grid Connection40.5293.15Truept
\n
" + "text/plain": [ + " name junction p_bar t_k in_service type\n", + "0 Grid Connection 4 0.5 293.15 True pt" + ], + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namejunctionp_bart_kin_servicetype
0Grid Connection40.5293.15Truept
\n", + "
" + ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], - "source": [ - "medium_pressure_grid = pp.create_ext_grid(net, junction=junction5, p_bar=0.5, t_k=293.15, name=\"Grid Connection\")\n", - "\n", - "net.ext_grid # show external grid table" - ] + "execution_count": 5 }, { "cell_type": "markdown", @@ -164,15 +314,20 @@ }, { "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-19T14:00:53.731512Z", + "start_time": "2024-08-19T14:00:53.716223Z" + } + }, "source": [ "pipe1 = pp.create_pipe_from_parameters(net, from_junction=junction1, to_junction=junction2, length_km=0.545, diameter_m=0.2, name=\"Pipe 1\")\n", "pipe2 = pp.create_pipe_from_parameters(net, from_junction=junction2, to_junction=junction3, length_km=0.095, diameter_m=0.15, name=\"Pipe 2\")\n", "pipe3 = pp.create_pipe_from_parameters(net, from_junction=junction1, to_junction=junction4, length_km=0.285, diameter_m=0.15, name=\"Pipe 3\")\n", "pipe4 = pp.create_pipe_from_parameters(net, from_junction=junction1, to_junction=junction5, length_km=0.43, diameter_m=0.15, k_mm=0.5, name=\"Pipe 4\")" - ] + ], + "outputs": [], + "execution_count": 6 }, { "cell_type": "markdown", @@ -183,22 +338,146 @@ }, { "cell_type": "code", - "execution_count": 7, - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-19T14:00:57.958470Z", + "start_time": "2024-08-19T14:00:57.948328Z" + } + }, + "source": [ + "net.pipe # show pipe table" + ], "outputs": [ { "data": { - "text/plain": " name from_junction to_junction std_type length_km diameter_m k_mm \\\n0 Pipe 1 0 1 None 0.545 0.20 1.0 \n1 Pipe 2 1 2 None 0.095 0.15 1.0 \n2 Pipe 3 0 3 None 0.285 0.15 1.0 \n3 Pipe 4 0 4 None 0.430 0.15 0.5 \n\n loss_coefficient alpha_w_per_m2k text_k qext_w sections in_service \\\n0 0.0 0.0 293.0 0.0 1 True \n1 0.0 0.0 293.0 0.0 1 True \n2 0.0 0.0 293.0 0.0 1 True \n3 0.0 0.0 293.0 0.0 1 True \n\n type \n0 pipe \n1 pipe \n2 pipe \n3 pipe ", - "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
namefrom_junctionto_junctionstd_typelength_kmdiameter_mk_mmloss_coefficientalpha_w_per_m2ktext_kqext_wsectionsin_servicetype
0Pipe 101None0.5450.201.00.00.0293.00.01Truepipe
1Pipe 212None0.0950.151.00.00.0293.00.01Truepipe
2Pipe 303None0.2850.151.00.00.0293.00.01Truepipe
3Pipe 404None0.4300.150.50.00.0293.00.01Truepipe
\n
" + "text/plain": [ + " name from_junction to_junction std_type length_km diameter_m k_mm \\\n", + "0 Pipe 1 0 1 None 0.545 0.20 0.2 \n", + "1 Pipe 2 1 2 None 0.095 0.15 0.2 \n", + "2 Pipe 3 0 3 None 0.285 0.15 0.2 \n", + "3 Pipe 4 0 4 None 0.430 0.15 0.5 \n", + "\n", + " loss_coefficient u_w_per_m2k text_k qext_w sections in_service type \n", + "0 0.0 0.0 NaN 0.0 1 True pipe \n", + "1 0.0 0.0 NaN 0.0 1 True pipe \n", + "2 0.0 0.0 NaN 0.0 1 True pipe \n", + "3 0.0 0.0 NaN 0.0 1 True pipe " + ], + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namefrom_junctionto_junctionstd_typelength_kmdiameter_mk_mmloss_coefficientu_w_per_m2ktext_kqext_wsectionsin_servicetype
0Pipe 101None0.5450.200.20.00.0NaN0.01Truepipe
1Pipe 212None0.0950.150.20.00.0NaN0.01Truepipe
2Pipe 303None0.2850.150.20.00.0NaN0.01Truepipe
3Pipe 404None0.4300.150.50.00.0NaN0.01Truepipe
\n", + "
" + ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], - "source": [ - "net.pipe # show pipe table" - ] + "execution_count": 7 }, { "cell_type": "markdown", @@ -257,16 +536,20 @@ }, { "cell_type": "code", - "execution_count": 9, "metadata": { "pycharm": { "name": "#%%\n" + }, + "ExecuteTime": { + "end_time": "2024-08-19T14:01:16.329041Z", + "start_time": "2024-08-19T14:01:12.912139Z" } }, - "outputs": [], "source": [ "pp.pipeflow(net, friction_model=\"nikuradse\")" - ] + ], + "outputs": [], + "execution_count": 8 }, { "cell_type": "markdown", @@ -281,49 +564,215 @@ }, { "cell_type": "code", - "execution_count": 10, "metadata": { "pycharm": { "name": "#%%\n" + }, + "ExecuteTime": { + "end_time": "2024-08-19T14:01:24.515012Z", + "start_time": "2024-08-19T14:01:24.508487Z" } }, + "source": [ + "net.res_junction # calculated pressure and temperature at junctions" + ], "outputs": [ { "data": { - "text/plain": " p_bar t_k\n0 5.194289 293.15\n1 4.607432 293.15\n2 4.314000 293.15\n3 5.780977 293.15\n4 0.500000 293.15", - "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
p_bart_k
05.194289293.15
14.607432293.15
24.314000293.15
35.780977293.15
40.500000293.15
\n
" + "text/plain": [ + " p_bar t_k\n", + "0 5.194647 293.15\n", + "1 4.607818 293.15\n", + "2 4.314403 293.15\n", + "3 5.781476 293.15\n", + "4 0.500000 293.15" + ], + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
p_bart_k
05.194647293.15
14.607818293.15
24.314403293.15
35.781476293.15
40.500000293.15
\n", + "
" + ] }, - "execution_count": 10, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], - "source": [ - "net.res_junction # calculated pressure and temperature at junctions" - ] + "execution_count": 9 }, { "cell_type": "code", - "execution_count": 11, "metadata": { "pycharm": { "name": "#%%\n" + }, + "ExecuteTime": { + "end_time": "2024-08-19T14:01:28.266605Z", + "start_time": "2024-08-19T14:01:28.253169Z" } }, + "source": [ + "net.res_pipe # velocities, mass flows through pipes and other results" + ], "outputs": [ { "data": { - "text/plain": " v_mean_m_per_s p_from_bar p_to_bar t_from_k t_to_k mdot_from_kg_per_s \\\n0 0.004433 5.194289 4.607432 293.15 293.15 0.139 \n1 0.007880 4.607432 4.314000 293.15 293.15 0.139 \n2 0.015704 5.194289 5.780977 293.15 293.15 0.277 \n3 -0.023584 5.194289 0.500000 293.15 293.15 -0.416 \n\n mdot_to_kg_per_s vdot_norm_m3_per_s reynolds lambda \n0 -0.139 0.000139 886.106589 0.102569 \n1 -0.139 0.000139 1181.475451 0.087337 \n2 -0.277 0.000278 2354.451079 0.060350 \n3 0.416 -0.000417 3535.926531 0.045036 ", - "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
v_mean_m_per_sp_from_barp_to_bart_from_kt_to_kmdot_from_kg_per_smdot_to_kg_per_svdot_norm_m3_per_sreynoldslambda
00.0044335.1942894.607432293.15293.150.139-0.1390.000139886.1065890.102569
10.0078804.6074324.314000293.15293.150.139-0.1390.0001391181.4754510.087337
20.0157045.1942895.780977293.15293.150.277-0.2770.0002782354.4510790.060350
3-0.0235845.1942890.500000293.15293.15-0.4160.416-0.0004173535.9265310.045036
\n
" + "text/plain": [ + " v_mean_m_per_s p_from_bar p_to_bar t_from_k t_to_k mdot_from_kg_per_s \\\n", + "0 0.0 5.194647 4.607818 293.15 293.15 0.0 \n", + "1 0.0 4.607818 4.314403 293.15 293.15 0.0 \n", + "2 0.0 5.194647 5.781476 293.15 293.15 0.0 \n", + "3 0.0 5.194647 0.500000 293.15 293.15 0.0 \n", + "\n", + " mdot_to_kg_per_s vdot_m3_per_s reynolds lambda \n", + "0 -0.0 0.0 0.0 0.019623 \n", + "1 -0.0 0.0 0.0 0.021072 \n", + "2 -0.0 0.0 0.0 0.021072 \n", + "3 -0.0 0.0 0.0 0.026936 " + ], + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
v_mean_m_per_sp_from_barp_to_bart_from_kt_to_kmdot_from_kg_per_smdot_to_kg_per_svdot_m3_per_sreynoldslambda
00.05.1946474.607818293.15293.150.0-0.00.00.00.019623
10.04.6078184.314403293.15293.150.0-0.00.00.00.021072
20.05.1946475.781476293.15293.150.0-0.00.00.00.021072
30.05.1946470.500000293.15293.150.0-0.00.00.00.026936
\n", + "
" + ] }, - "execution_count": 11, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], - "source": [ - "net.res_pipe # velocities, mass flows through pipes and other results" - ] + "execution_count": 10 }, { "cell_type": "markdown", @@ -336,8 +785,18 @@ }, { "cell_type": "code", - "execution_count": 12, - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-19T14:01:39.084519Z", + "start_time": "2024-08-19T14:01:38.996816Z" + } + }, + "source": [ + "import matplotlib\n", + "from pandapipes.plotting.simple_plot import simple_plot as sp\n", + "\n", + "sp(net, plot_sinks = True)" + ], "outputs": [ { "name": "stderr", @@ -348,27 +807,26 @@ }, { "data": { - "text/plain": "
", - "image/png": "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\n" + "text/plain": [ + "
" + ], + "image/png": "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gAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIIBABwAAgAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIIBABwAAgAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIIBABwAAgAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIIBABwAAgAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIIBABwAAgAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIIBABwAAgAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIIBABwAAgAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIIBABwAAgAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIIBABwAAgAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIIBABwAAgAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIIBABwAAgAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIIBABwAAgAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIIBABwAAgAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIIBABwAAgAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIIBABwAAgAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIIBABwAAgAACHQAAAAIIdAAAAAgg0AEAACCAQAcAAIAAAh0AAAACCHQAAAAIINABAAAggEAHAACAAAIdAAAAAgh0AAAACCDQAQAAIMD/A7bYsP/AHkiRAAAAAElFTkSuQmCC" }, "metadata": {}, "output_type": "display_data" }, { "data": { - "text/plain": "" + "text/plain": [ + "" + ] }, - "execution_count": 12, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], - "source": [ - "import matplotlib\n", - "from pandapipes.plotting.simple_plot import simple_plot as sp\n", - "\n", - "sp(net, plot_sinks = True)" - ] + "execution_count": 11 }, { "cell_type": "markdown", @@ -399,4 +857,4 @@ }, "nbformat": 4, "nbformat_minor": 2 -} \ No newline at end of file +} diff --git a/tutorials/temperature_calculation.ipynb b/tutorials/temperature_calculation.ipynb index 1cad6d87f..092634e75 100644 --- a/tutorials/temperature_calculation.ipynb +++ b/tutorials/temperature_calculation.ipynb @@ -11,7 +11,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This tutorial describes how temperatures inside pipes can be calculated. In comparison to the hydraulic property calculation, additional parameters must be specified for the pipes: The heat transfer coefficient (`alpha_w_per_m2k`), which determines how well or poorly the pipe insulates. Likewise the ambient temperature of the pipe (`text_k`) can be changed, which is 293 K by default. To increase the spatial resolution of the pipe, more than one section can be defined using the parameter `sections`.\n", + "This tutorial describes how temperatures inside pipes can be calculated. In comparison to the hydraulic property calculation, additional parameters must be specified for the pipes: The heat transfer coefficient (`u_w_per_m2k`), which determines how well or poorly the pipe insulates. Likewise the ambient temperature of the pipe (`text_k`) can be changed, which is 293 K by default. To increase the spatial resolution of the pipe, more than one section can be defined using the parameter `sections`.\n", "\n", "Please note that only incompressible media should be used for the heating network calculation and the [`mode`](https://pandapipes.readthedocs.io/en/latest/pipeflow/calculation_modes.html#temperature-calculations-pipeflow-option-mode-all-or-mode-heat) in the `pipeflow` function has to be set to \"all\" or \"heat\". In case `mode` equals \"heat\", the user must manually specify a solution vector for the hydraulic calculations. It should also be noted that the temperature calculations are currently still sequential. This means that the calculated temperature values do not influence the fluid properties of the medium (density and viscosity). Therefore, the calculations are only valid if the properties are not very temperature-dependent or if there are minor changes in temperature.\n", " \n", @@ -104,15 +104,15 @@ "\n", "# create pipes\n", "pandapipes.create_pipe_from_parameters(net, from_junction=junction1, to_junction=junction2, length_km=0.1,\n", - " diameter_m=0.075, k_mm=0.025, sections=5, alpha_w_per_m2k=100,\n", + " diameter_m=0.075, k_mm=0.025, sections=5, u_w_per_m2k=100,\n", " text_k=298.15, name=\"Pipe 1\")\n", "\n", "pandapipes.create_pipe_from_parameters(net, from_junction=junction2, to_junction=junction3, length_km=2,\n", - " diameter_m=0.05, k_mm=0.025, sections=4, alpha_w_per_m2k=100,\n", + " diameter_m=0.05, k_mm=0.025, sections=4, u_w_per_m2k=100,\n", " text_k=298.15, name=\"Pipe 2\")\n", "\n", "pandapipes.create_pipe_from_parameters(net, from_junction=junction2, to_junction=junction4, length_km=1,\n", - " diameter_m=0.1, k_mm=0.025, sections=8, alpha_w_per_m2k=50,\n", + " diameter_m=0.1, k_mm=0.025, sections=8, u_w_per_m2k=50,\n", " text_k=298.15, name=\"Pipe 3\")" ] },