diff --git a/.codespellrc b/.codespellrc deleted file mode 100644 index d31c98b..0000000 --- a/.codespellrc +++ /dev/null @@ -1,4 +0,0 @@ -[codespell] -skip = *.po,*.ts,./docs/build/*,./build/*,./dist/*,./.git -count = -quiet-level = 3 diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml index aba2bdd..8615838 100644 --- a/.github/workflows/black.yml +++ b/.github/workflows/black.yml @@ -9,7 +9,5 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: psf/black@stable - with: - options: "--verbose" \ No newline at end of file diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index d9b44f2..d30c39b 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -15,27 +15,23 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.7', '3.8', '3.9', '3.10'] + python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} + - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install flake8 pytest + python -m pip install pytest python -m pip install numpy if [ -f requirements.txt ]; then pip install -r requirements.txt; fi python -m pip install . - - name: Lint with flake8 - run: | - # stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --ignore=C901,E201,E203,E501,N801,N802,N803,N806,E241 --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - name: Test with pytest run: | pytest diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index b2ed530..72c34f7 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -13,9 +13,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: '3.x' - name: Install dependencies @@ -27,5 +27,5 @@ jobs: TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} run: | - python setup.py sdist bdist_wheel + pip wheel -w dist . twine upload dist/* diff --git a/.gitignore b/.gitignore index d8fc1a9..1ef042a 100644 --- a/.gitignore +++ b/.gitignore @@ -110,3 +110,4 @@ venv.bak/ *.todo /extern_docs .vscode/ +docs/source/README.md \ No newline at end of file diff --git a/.pylintrc b/.pylintrc deleted file mode 100644 index 323b9d7..0000000 --- a/.pylintrc +++ /dev/null @@ -1,589 +0,0 @@ -[MASTER] - -# A comma-separated list of package or module names from where C extensions may -# be loaded. Extensions are loading into the active Python interpreter and may -# run arbitrary code. -extension-pkg-whitelist=math - -# Specify a score threshold to be exceeded before program exits with error. -fail-under=10.0 - -# Add files or directories to the blacklist. They should be base names, not -# paths. -ignore=CVS - -# Add files or directories matching the regex patterns to the blacklist. The -# regex matches against base names, not paths. -ignore-patterns= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the -# number of processors available to use. -jobs=0 - -# Control the amount of potential inferred values when inferring a single -# object. This can help the performance when dealing with large functions or -# complex, nested conditions. -limit-inference-results=100 - -# List of plugins (as comma separated values of python module names) to load, -# usually to register additional checkers. -load-plugins= - -# Pickle collected data for later comparisons. -persistent=yes - -# When enabled, pylint would attempt to guess common misconfiguration and emit -# user-friendly hints instead of false-positive error messages. -suggestion-mode=yes - -# Allow loading of arbitrary C extensions. Extensions are imported into the -# active Python interpreter and may run arbitrary code. -unsafe-load-any-extension=no - - -[MESSAGES CONTROL] - -# Only show warnings with the listed confidence levels. Leave empty to show -# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED. -confidence= - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifiers separated by comma (,) or put this -# option multiple times (only on the command line, not in the configuration -# file where it should appear only once). You can also use "--disable=all" to -# disable everything first and then reenable specific checks. For example, if -# you want to run only the similarities checker, you can use "--disable=all -# --enable=similarities". If you want to run only the classes checker, but have -# no Warning level messages displayed, use "--disable=all --enable=classes -# --disable=W". -disable=print-statement, - parameter-unpacking, - unpacking-in-except, - old-raise-syntax, - backtick, - long-suffix, - old-ne-operator, - old-octal-literal, - import-star-module-level, - non-ascii-bytes-literal, - raw-checker-failed, - bad-inline-option, - locally-disabled, - file-ignored, - suppressed-message, - useless-suppression, - deprecated-pragma, - use-symbolic-message-instead, - apply-builtin, - basestring-builtin, - buffer-builtin, - cmp-builtin, - coerce-builtin, - execfile-builtin, - file-builtin, - long-builtin, - raw_input-builtin, - reduce-builtin, - standarderror-builtin, - unicode-builtin, - xrange-builtin, - coerce-method, - delslice-method, - getslice-method, - setslice-method, - no-absolute-import, - old-division, - dict-iter-method, - dict-view-method, - next-method-called, - metaclass-assignment, - indexing-exception, - raising-string, - reload-builtin, - oct-method, - hex-method, - nonzero-method, - cmp-method, - input-builtin, - round-builtin, - intern-builtin, - unichr-builtin, - map-builtin-not-iterating, - zip-builtin-not-iterating, - range-builtin-not-iterating, - filter-builtin-not-iterating, - using-cmp-argument, - eq-without-hash, - div-method, - idiv-method, - rdiv-method, - exception-message-attribute, - invalid-str-codec, - sys-max-int, - bad-python3-import, - deprecated-string-function, - deprecated-str-translate-call, - deprecated-itertools-function, - deprecated-types-field, - next-method-defined, - dict-items-not-iterating, - dict-keys-not-iterating, - dict-values-not-iterating, - deprecated-operator-function, - deprecated-urllib-function, - xreadlines-attribute, - deprecated-sys-function, - exception-escape, - comprehension-escape, - invalid_name - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time (only on the command line, not in the configuration file where -# it should appear only once). See also the "--disable" option for examples. -enable=c-extension-no-member - - -[REPORTS] - -# Python expression which should return a score less than or equal to 10. You -# have access to the variables 'error', 'warning', 'refactor', and 'convention' -# which contain the number of messages in each category, as well as 'statement' -# which is the total number of statements analyzed. This score is used by the -# global evaluation report (RP0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Template used to display messages. This is a python new-style format string -# used to format the message information. See doc for all details. -#msg-template= - -# Set the output format. Available formats are text, parseable, colorized, json -# and msvs (visual studio). You can also give a reporter class, e.g. -# mypackage.mymodule.MyReporterClass. -output-format=text - -# Tells whether to display a full report or only the messages. -reports=no - -# Activate the evaluation score. -score=yes - - -[REFACTORING] - -# Maximum number of nested blocks for function / method body -max-nested-blocks=5 - -# Complete name of functions that never returns. When checking for -# inconsistent-return-statements if a never returning function is called then -# it will be considered as an explicit return statement and no message will be -# printed. -never-returning-functions=sys.exit - - -[BASIC] - -# Naming style matching correct argument names. -argument-naming-style=any # changed because of historical consistancy - -# Regular expression matching correct argument names. Overrides argument- -# naming-style. -#argument-rgx= - -# Naming style matching correct attribute names. -attr-naming-style=snake_case - -# Regular expression matching correct attribute names. Overrides attr-naming- -# style. -#attr-rgx= - -# Bad variable names which should always be refused, separated by a comma. -bad-names=foo, - bar, - baz, - toto, - tutu, - tata - -# Bad variable names regexes, separated by a comma. If names match any regex, -# they will always be refused -bad-names-rgxs= - -# Naming style matching correct class attribute names. -class-attribute-naming-style=any - -# Regular expression matching correct class attribute names. Overrides class- -# attribute-naming-style. -#class-attribute-rgx= - -# Naming style matching correct class names. -class-naming-style=any # changed because of historical consistancy - -# Regular expression matching correct class names. Overrides class-naming- -# style. -#class-rgx= - -# Naming style matching correct constant names. -const-naming-style=UPPER_CASE - -# Regular expression matching correct constant names. Overrides const-naming- -# style. -#const-rgx= - -# Minimum line length for functions/classes that require docstrings, shorter -# ones are exempt. -docstring-min-length=-1 - -# Naming style matching correct function names. -function-naming-style=any # changed because of historical consistancy - -# Regular expression matching correct function names. Overrides function- -# naming-style. -#function-rgx= - -# Good variable names which should always be accepted, separated by a comma. -good-names=i, - j, - k, - ex, - Run, - _ - -# Good variable names regexes, separated by a comma. If names match any regex, -# they will always be accepted -good-names-rgxs= - -# Include a hint for the correct naming format with invalid-name. -include-naming-hint=no - -# Naming style matching correct inline iteration names. -inlinevar-naming-style=any - -# Regular expression matching correct inline iteration names. Overrides -# inlinevar-naming-style. -#inlinevar-rgx= - -# Naming style matching correct method names. -method-naming-style=any # changed because of historical consistancy - -# Regular expression matching correct method names. Overrides method-naming- -# style. -#method-rgx= - -# Naming style matching correct module names. -module-naming-style=any # changed because of historical consistancy - -# Regular expression matching correct module names. Overrides module-naming- -# style. -#module-rgx= - -# Colon-delimited sets of names that determine each other's naming style when -# the name regexes allow several styles. -name-group= - -# Regular expression which should only match function or class names that do -# not require a docstring. -no-docstring-rgx=^_ - -# List of decorators that produce properties, such as abc.abstractproperty. Add -# to this list to register other decorators that produce valid properties. -# These decorators are taken in consideration only for invalid-name. -property-classes=abc.abstractproperty - -# Naming style matching correct variable names. -variable-naming-style=any # changed because of historical consistancy - -# Regular expression matching correct variable names. Overrides variable- -# naming-style. -#variable-rgx= - - -[FORMAT] - -# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. -expected-line-ending-format= - -# Regexp for a line that is allowed to be longer than the limit. -ignore-long-lines=^\s*(# )??$ - -# Number of spaces of indent required inside a hanging or continued line. -indent-after-paren=4 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - -# Maximum number of characters on a single line. -max-line-length=88 # match default value of black - -# Maximum number of lines in a module. -max-module-lines=1000 - -# Allow the body of a class to be on the same line as the declaration if body -# contains single statement. -single-line-class-stmt=no - -# Allow the body of an if to be on the same line as the test if there is no -# else. -single-line-if-stmt=no - - -[LOGGING] - -# The type of string formatting that logging methods do. `old` means using % -# formatting, `new` is for `{}` formatting. -logging-format-style=old - -# Logging modules to check that the string format arguments are in logging -# function parameter format. -logging-modules=logging - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME, - XXX, - TODO - -# Regular expression of note tags to take in consideration. -#notes-rgx= - - -[SIMILARITIES] - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - -# Ignore imports when computing similarities. -ignore-imports=no - -# Minimum lines number of a similarity. -min-similarity-lines=4 - - -[SPELLING] - -# Limits count of emitted suggestions for spelling mistakes. -max-spelling-suggestions=4 - -# Spelling dictionary name. Available dictionaries: none. To make it work, -# install the python-enchant package. -spelling-dict= - -# List of comma separated words that should not be checked. -spelling-ignore-words= - -# A path to a file that contains the private dictionary; one word per line. -spelling-private-dict-file= - -# Tells whether to store unknown words to the private dictionary (see the -# --spelling-private-dict-file option) instead of raising a message. -spelling-store-unknown-words=no - - -[STRING] - -# This flag controls whether inconsistent-quotes generates a warning when the -# character used as a quote delimiter is used inconsistently within a module. -check-quote-consistency=no - -# This flag controls whether the implicit-str-concat should generate a warning -# on implicit string concatenation in sequences defined over several lines. -check-str-concat-over-line-jumps=no - - -[TYPECHECK] - -# List of decorators that produce context managers, such as -# contextlib.contextmanager. Add to this list to register other decorators that -# produce valid context managers. -contextmanager-decorators=contextlib.contextmanager - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E1101 when accessed. Python regular -# expressions are accepted. -generated-members=struct.* - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# Tells whether to warn about missing members when the owner of the attribute -# is inferred to be None. -ignore-none=yes - -# This flag controls whether pylint should warn about no-member and similar -# checks whenever an opaque object is returned when inferring. The inference -# can return multiple potential results while evaluating a Python object, but -# some branches might not be evaluated, which results in partial inference. In -# that case, it might be useful to still emit no-member and other checks for -# the rest of the inferred objects. -ignore-on-opaque-inference=yes - -# List of class names for which member attributes should not be checked (useful -# for classes with dynamically set attributes). This supports the use of -# qualified names. -ignored-classes=optparse.Values,thread._local,_thread._local - -# List of module names for which member attributes should not be checked -# (useful for modules/projects where namespaces are manipulated during runtime -# and thus existing member attributes cannot be deduced by static analysis). It -# supports qualified module names, as well as Unix pattern matching. -ignored-modules= - -# Show a hint with possible names when a member name was not found. The aspect -# of finding the hint is based on edit distance. -missing-member-hint=yes - -# The minimum edit distance a name should have in order to be considered a -# similar match for a missing member name. -missing-member-hint-distance=1 - -# The total number of similar names that should be taken in consideration when -# showing a hint for a missing member. -missing-member-max-choices=1 - -# List of decorators that change the signature of a decorated function. -signature-mutators= - - -[VARIABLES] - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid defining new builtins when possible. -additional-builtins= - -# Tells whether unused global variables should be treated as a violation. -allow-global-unused-variables=yes - -# List of strings which can identify a callback function by name. A callback -# name must start or end with one of those strings. -callbacks=cb_, - _cb - -# A regular expression matching the name of dummy variables (i.e. expected to -# not be used). -dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore. -ignored-argument-names=_.*|^ignored_|^unused_ - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# List of qualified module names which can have objects that can redefine -# builtins. -redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io - - -[CLASSES] - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__, - __new__, - setUp, - __post_init__ - -# List of member names, which should be excluded from the protected access -# warning. -exclude-protected=_asdict, - _fields, - _replace, - _source, - _make - -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls - -# List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=cls - - -[DESIGN] - -# Maximum number of arguments for function / method. -max-args=5 - -# Maximum number of attributes for a class (see R0902). -max-attributes=7 - -# Maximum number of boolean expressions in an if statement (see R0916). -max-bool-expr=5 - -# Maximum number of branch for function / method body. -max-branches=12 - -# Maximum number of locals for function / method body. -max-locals=15 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - -# Maximum number of return / yield for function / method body. -max-returns=6 - -# Maximum number of statements in function / method body. -max-statements=50 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=2 - - -[IMPORTS] - -# List of modules that can be imported at any level, not just the top level -# one. -allow-any-import-level= - -# Allow wildcard imports from modules that define __all__. -allow-wildcard-with-all=no - -# Analyse import fallback blocks. This can be used to support both Python 2 and -# 3 compatible code, which means that the block might have code that exists -# only in one or another interpreter, leading to false positives when analysed. -analyse-fallback-blocks=no - -# Deprecated modules which should not be used, separated by a comma. -deprecated-modules=optparse,tkinter.tix - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled). -ext-import-graph= - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled). -import-graph= - -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled). -int-import-graph= - -# Force import order to recognize a module as part of the standard -# compatibility libraries. -known-standard-library= - -# Force import order to recognize a module as part of a third party library. -known-third-party=enchant - -# Couples of modules and preferred modules, separated by a comma. -preferred-modules= - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when being caught. Defaults to -# "BaseException, Exception". -overgeneral-exceptions=BaseException, - Exception diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100755 index ab7135e..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,3 +0,0 @@ -include *.txt -include *.md -recursive-include docs *.rst diff --git a/NEWS.txt b/NEWS.txt index 9704211..7f7711b 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,3 +1,12 @@ +## TODO v0.5.0, xx.yyyy +* increase minimal python version to 3.8 +* add type hints to all functions +* improve docstrings to include type hints +* replace magic numbers for ice type, diagram region and unit system with enumerations +* restructure imports +* switch to pyproject.toml +** move file location of demo scripts + ## v0.4.9, 05.2022 * fix issue with missing unit conversion in h_px and h_tx * add tests for fixed bugs diff --git a/README.md b/README.md index 0043f09..ebf8180 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,22 @@ -# XSteam +# pyXSteam -Original Released by Magnus Holmgren for Matlab and Excel: - and/or +pyXSteam is a Python library designed for calculating thermodynamic properties of water and steam based on the [IAPWS](http://www.iapws.org) (International Association for the Properties of Water and Steam) formulations. -At [this github repository](https://github.com/stu314159/xsteam) you can find the/a matlab version. +This library was ported from the original Matlab released by Magnus Holmgren. The original can be founbd at [Sourceforge](http://xsteam.sourceforge.net) and/or . -XSteam provides (mostly) accurate steam and water properties from 0 - -1000 bar and from 0 - 2000 °C according to the [IAPWS release IF-97](http://www.iapws.org/relguide/IF97-Rev.pdf). For -accuracy of the functions in different regions see IF-97 Page 4 +pyXSteam and XSteam provide (mostly) accurate steam and water properties from 0 - 1000 bar and from 0 - 2000 °C according to the [IAPWS release IF-97 (R7-97(2012))](http://www.iapws.org/relguide/IF97-Rev.pdf) . For accuracy of the functions in different regions see IF-97 Page 4. We take no responsibilities for any errors in the code or damage thereby! -Also includes thermal conductivity and viscosity, which are not part of -the IF97 release. -* Thermal Conductivity: (IAPWS 1998) - -* Viscosity: (2003) +Also included are functions for thermal conductivity and viscosity which are not part of R7-97(2012). -Some effort has been made to include the refined function of more recent releases -and also functions for calculations on heavy water. This includes: -* IAPWS R4 -* IAPWS R14 + - [IAPWS R15-11: Thermal Conductivity of Ordinary Water Substance](http://www.iapws.org/relguide/ThCond.pdf) + - [IAPWS R12-08: Viscosity of Ordinary Water Substance](http://www.iapws.org/relguide/visc.pdf) + - [IAPWS R1-76(2014): Surface Tension of Ordinary Water Substance](https://www.iapws.org/relguide/Surf-H2O-2014.pdf) + +Some effort has been made to include the refined function of more recent releases and also functions for calculations on heavy water. This implementation is still in progress, these function should not be used. This includes: + + - IAPWS R4 (deprecated) + - IAPWS R5-85(1994) + - IAPWS R14 ## Contributors @@ -30,75 +28,107 @@ In chronological order: - gonmolina - xjtu-blacksmith +## Documentation -## Requirements - -There are no requirements for installing pyXSteam with Python 3.6 and up. +Check out [pyXSteam at readthedocs](https://pyxsteam.readthedocs.io) -Tests require numpy, demos require numpy and matplotlib +## Requirements -## Install +There are no requirements for installing pyXSteam with Python 3.8 and up. The demos require `numpy` and `matplotlib`. -run `python3 setup.py install` +### Tests -To run unittests you need two additional packages: `pytest` and `numpy`. After installing both, just run pytest in -the base directory. The tests use some fixed values from the documentation to make sure that every coefficient -and formula works as intended. +Tests require `pytest` and `numpy` -To test if setup was successful, run `python3 bin/pyXSteamDemo.py`. This will require numpy and matplotlib to be installed. +## Install -## Nomenclature +run `pip install pyXSteam` -All Functions follow the same naming schema: First the wanted property, -then a underscore `_`, then the wanted input properties Example: -`t_ph` is temperature as a function of pressure and enthalpy. For a list -of valid functions se below: +To run unittests you need two additional packages: `pytest` and `numpy`. After installing both, just run pytest in the base directory. The tests use some fixed values from the documentation to make sure that every coefficient and formula works as intended. -| Property | Description | -|----------|--------------------------------------------------------------| -| t | Temperature (°C or °F) | -| p | Pressure (bar or psi) | -| h | Enthalpy (kJ/kg or btu/lb) | -| v | Specific volume (m3/kg or ft\^3/lb) | -| rho | Density (kg/m3 or lb/ft\^3) | -| s | Specific entropy (kJ/(kg °C) or btu/(lb °F)) | -| u | Specific internal energy (kJ/kg or btu/lb) | -| Cp | Specific isobaric heat capacity (kJ/(kg °C) or btu/(lb °F)) | -| Cv | Specific isochoric heat capacity (kJ/(kg °C) or btu/(lb °F)) | -| w | Speed of sound (m/s or ft/s) | -| my | Viscosity (N s/m\^2 or lbm/ft/hr) | -| tc | Thermal Conductivity (W/(m °C) or btu/(h ft °F)) | -| st | Surface Tension (N/m or lb/ft) | -| x | Vapor fraction | -| vx | Vapor Volume Fraction | +To test if setup was successful, run `pyXSteamDemo`. This will require numpy and matplotlib to be installed. ## Usage Simple Example: +``` from pyXSteam.XSteam import XSteam steamTable = XSteam(XSteam.UNIT_SYSTEM_MKS) print(steamTable.hL_p(220.0)) +``` By using the unitSystem Parameter, you can tell XSteam witch Unit System you are using. +``` steamTable = XSteam(XSteam.UNIT_SYSTEM_MKS) # m/kg/sec/°C/bar/W steamTable = XSteam(XSteam.UNIT_SYSTEM_FLS) # ft/lb/sec/°F/psi/btu steamTable = XSteam(XSteam.UNIT_SYSTEM_BARE) # m/kg/sec/K/MPa/W +``` To enable logging, add the following lines to your code: +``` import logging logging.basicConfig(level=logging.INFO) +``` or alternatively +``` import logging logger = logging.getLogger('pyXSteam') logger.setLevel(logging.DEBUG) sh = logging.StreamHandler() sh.setFormatter(logging.Formatter('%(name)s - %(levelname)s - %(message)s')) logger.addHandler(sh) +``` + +## Related projects + +Implementations of the IAPWS releases are also available for other programming languages: + +- Matlab and Excel: [xsteam](http://xsteam.sourceforge.net) +- Matlab: [xsteam](https://github.com/stu314159/xsteam) +- .NET: [XSteamNET](https://github.com/rogerlew/XSteamNET) + + +## Notes + +### Density (rho) + +Density is calculated as 1/v. See section for Specific volume + +### Viscosity + +Viscosity is not part of IAPWS Steam IF97. Equations from "Revised Release on the IAPWS Formulation 1985 for the Viscosity of Ordinary Water Substance", 2003 are used. Viscosity in the mixed region (4) is interpolated according to the density. This is not true since it will be two phases. + +### Thermal conductivity + +Revised release on the IAPS Formulation 1985 for the Thermal Conductivity of ordinary water substance (IAPWS 1998) + +## Nomenclature + +All Functions follow the same naming schema: First the wanted property, then a underscore `_`, then the wanted input properties Example: `t_ph` is temperature as a function of pressure and enthalpy. For a list of valid functions se below: + +| Property | Description | +|----------|--------------------------------------------------------------| +| t | Temperature (°C or °F) | +| p | Pressure (bar or psi) | +| h | Enthalpy (kJ/kg or btu/lb) | +| v | Specific volume (m3/kg or ft\^3/lb) | +| rho | Density (kg/m3 or lb/ft\^3) | +| s | Specific entropy (kJ/(kg °C) or btu/(lb °F)) | +| u | Specific internal energy (kJ/kg or btu/lb) | +| Cp | Specific isobaric heat capacity (kJ/(kg °C) or btu/(lb °F)) | +| Cv | Specific isochoric heat capacity (kJ/(kg °C) or btu/(lb °F)) | +| w | Speed of sound (m/s or ft/s) | +| my | Viscosity (N s/m\^2 or lbm/ft/hr) | +| tc | Thermal Conductivity (W/(m °C) or btu/(h ft °F)) | +| st | Surface Tension (N/m or lb/ft) | +| x | Vapor fraction | +| vx | Vapor Volume Fraction | + ## Available Functions @@ -239,25 +269,18 @@ or alternatively | x_ph | vapor fraction as a function of pressure and enthalpy | | x_ps | vapor fraction as a function of pressure and entropy | -## vapor volume fraction +### vapor volume fraction | Function | Description | |----------|--------------------------------------------------------------| | vx_ph | vapor volume fraction as a function of pressure and enthalpy | | vx_ps | vapor volume fraction as a function of pressure and entropy | -## Pressure along the Melting and Sublimation Curves -| Function | Description | -|--------------|--------------------------------------------------------------------| -| pmelt_t | Pressure along the melting curve as a function of temperature | -| vx_psubl_tps | Pressure along the sublimation curve as a function of temperature | - -# Available Functions for Heavy Water -| Function | Description | -|----------|---------------------------------------------------------------| -| my_rhoT | Viscosity as a function of density and temperature | -| tc_rhoT | Thermal conductivity as a function of density and temperature | - +### Pressure along the Melting and Sublimation Curves +| Function | Description | +|----------|--------------------------------------------------------------------| +| pmelt_t | Pressure along the melting curve as a function of temperature | +| psubl_t | Pressure along the sublimation curve as a function of temperature | -# Development +## Development - pull requests are always wellcome! - code style is enforced by black diff --git a/docs/Makefile b/docs/Makefile index 69fe55e..cf87ce8 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -16,4 +16,5 @@ help: # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile + cp -f ../README.md ./source/ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py index 0c63d11..b26022d 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -42,6 +42,8 @@ extensions = [ "sphinx.ext.autodoc", "sphinx.ext.githubpages", + "sphinx_autodoc_typehints", + "myst_parser", ] # Add any paths that contain templates here, relative to this directory. @@ -66,7 +68,7 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = [] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # The name of the Pygments (syntax highlighting) style to use. pygments_style = None @@ -183,3 +185,14 @@ # -- Extension configuration ------------------------------------------------- + +set_type_checking_flag = True + +# -- Options for sphinx_autodoc_typehints ------------------------------------ +typehints_fully_qualified = False +always_document_param_types = True +typehints_document_rtype = True +typehints_use_rtype = True +typehints_defaults = "comma" +simplify_optional_unions = True +typehints_formatter = None diff --git a/docs/source/index.rst b/docs/source/index.rst index 244e6d3..6334f79 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,87 +1,18 @@ -.. pyXSteam documentation master file, created by - sphinx-quickstart on Fri Mar 8 16:32:11 2019. - -Welcome to pyXSteam's documentation! -#################################### - -Original Released by Magnus Holmgren for Matlab and Excel: - and/or - -XSteam provides (mostly) accurate steam and water properties from 0 - -1000 bar and from 0 - 2000 °C according to the [IAPWS release IF-97](http://www.iapws.org/relguide/IF97-Rev.pdf). For -accuracy of the functions in different regions see IF-97 Page 4 - -Also includes thermal conductivity and viscosity, which are not part of -the IF97 release. -* `Thermal Conductivity: (IAPWS 1998) `_ - -This Python Library is based on the original XSteam Library for Matlab and Excel -from Magnus Holmgren, www.x-eng.com. -We take no responsibilities for any errors in the code or damage thereby! -See README.md for examples - -Some effort has been made to include the refined function of more recent releases -and also functions for calculations on heavy water. This includes: -* IAPWS R4 -* IAPWS R14 - -Usage Examples -************** -Check out the examples given in :doc:`pyXSteamDemo` for a quick overview of how to use pyXSteam in different use cases. - -Notes -***** -Density (rho) -============= -Density is calculated as 1/v. See section 1.5 Volume - -Viscosity -========= -Viscosity is not part of IAPWS Steam IF97. Equations from "Revised Release -on the IAPWS Formulation 1985 for the Viscosity of Ordinary Water -Substance", 2003 are used. Viscosity in the mixed region (4) is interpolated -according to the density. This is not true since it will be two phases. - -Thermal conductivity -==================== -Revised release on the IAPS Formulation 1985 for the Thermal Conductivity -of ordinary water substance (IAPWS 1998) - -Nomenclature -============ -All Functions follow the same naming schema: First the wanted property, -then a underscore `_`, then the wanted input properties Example: -`t_ph` is temperature as a function of pressure and enthalpy. For a list -of valid functions se below: - -======== ============================================================ -Property Description -======== ============================================================ -t Temperature (°C or °F) -p Pressure (bar or psi) -h Enthalpy (kJ/kg or btu/lb) -v Specific volume (m3/kg or ft\^3/lb)| -rho Density (kg/m3 or lb/ft\^3) -s Specific entropy (kJ/(kg °C) or btu/(lb °F)) -u Specific internal energy (kJ/kg or btu/lb) -Cp Specific isobaric heat capacity (kJ/(kg °C) or btu/(lb °F)) -Cv Specific isochoric heat capacity (kJ/(kg °C) or btu/(lb °F)) -w Speed of sound (m/s or ft/s) -my Viscosity (N s/m\^2 or lbm/ft/hr) -tc Thermal Conductivity (W/(m °C) or btu/(h ft °F)) -st Surface Tension (N/m or lb/ft) -x Vapor fraction -vx Vapor Volume Fraction -======== ============================================================ +====================================== + Welcome to pyXSteam's documentation! +====================================== .. toctree:: :maxdepth: 2 :caption: Contents: - pyXSteamAvailibleFunctions + README.md pyXSteam pyXSteamDemo +.. automodule:: pyXSteam.XSteam + :noindex: + Indices and tables ================== diff --git a/docs/source/pyXSteamAvailibleFunctions.rst b/docs/source/pyXSteamAvailibleFunctions.rst deleted file mode 100644 index 667f5ac..0000000 --- a/docs/source/pyXSteamAvailibleFunctions.rst +++ /dev/null @@ -1,207 +0,0 @@ -Available Functions -################### - -Temperature -+++++++++++ -======== ================================================= -Function Description -======== ================================================= -tsat_p Saturation temperature -t_ph Temperature as a function of pressure and enthalpy -t_ps Temperature as a function of pressure and entropy -t_hs Temperature as a function of enthalpy and entropy -======== ================================================= - -Pressure -++++++++ -======== ================================================= -Function Description -======== ================================================= -psat_t Saturation pressure -p_hs Pressure as a function of h and s. -p_hrho Pressure as a function of h and rho. Very inaccurate for solid water region since it's almost incompressible! -======== ================================================= - -Enthalpy -++++++++ -======== ================================================= -Function Description -======== ================================================= -hV_p Saturated vapor enthalpy -hL_p Saturated liquid enthalpy -hV_t Saturated vapor enthalpy -hL_t Saturated liquid enthalpy -h_pt Enthalpy as a function of pressure and temperature -h_ps Enthalpy as a function of pressure and entropy -h_px Enthalpy as a function of pressure and vapor fraction -h_prho Enthalpy as a function of pressure and density. Observe for low temperatures (liquid) this equation has 2 solutions -h_tx Enthalpy as a function of temperature and vapor fraction -======== ================================================= - -Specific volume -+++++++++++++++ -======== ================================================= -Function Description -======== ================================================= -vV_p Saturated vapor volume -vL_p Saturated liquid volume -vV_t Saturated vapor volume -vL_t Saturated liquid volume -v_pt Specific volume as a function of pressure and temperature -v_ph Specific volume as a function of pressure and enthalpy -v_ps Specific volume as a function of pressure and entropy -======== ================================================= - -Density -+++++++ -======== ================================================= -Function Description -======== ================================================= -rhoV_p Saturated vapor density -rhoL_p Saturated liquid density -rhoV_t Saturated vapor density -rhoL_t Saturated liquid density -rho_pt Density as a function of pressure and temperature -rho_ph Density as a function of pressure and enthalpy -rho_ps Density as a function of pressure and entropy -======== ================================================= - -Specific entropy -++++++++++++++++ -======== ================================================= -Function Description -======== ================================================= -sV_p Saturated vapor entropy -sL_p Saturated liquid entropy -sV_t Saturated vapor entropy -sL_t Saturated liquid entropy -s_pt Specific entropy as a function of pressure and temperature (Returns saturated vapor enthalpy if mixture) -s_ph Specific entropy as a function of pressure and enthalpy -======== ================================================= - -Specific internal energy -++++++++++++++++++++++++ -======== ================================================= -Function Description -======== ================================================= -uV_p Saturated vapor internal energy -uL_p Saturated liquid internal energy -uV_t Saturated vapor internal energy -uL_t Saturated liquid internal energy -u_pt Specific internal energy as a function of pressure and temperature -u_ph Specific internal energy as a function of pressure and enthalpy -u_ps Specific internal energy as a function of pressure and entropy -======== ================================================= - -Specific isobaric heat capacity -+++++++++++++++++++++++++++++++ -======== ================================================= -Function Description -======== ================================================= -CpV_p Saturated vapor heat capacity -CpL_p Saturated liquid heat capacity -CpV_t Saturated vapor heat capacity -CpL_t Saturated liquid heat capacity -Cp_pt Specific isobaric heat capacity as a function of pressure and temperature -Cp_ph Specific isobaric heat capacity as a function of pressure and enthalpy -Cp_ps Specific isobaric heat capacity as a function of pressure and entropy -======== ================================================= - -Specific isochoric heat capacity -++++++++++++++++++++++++++++++++ -======== ================================================= -Function Description -======== ================================================= -CvV_p Saturated vapor isochoric heat capacity -CvL_p Saturated liquid isochoric heat capacity -CvV_t Saturated vapor isochoric heat capacity -CvL_t Saturated liquid isochoric heat capacity -Cv_pt Specific isochoric heat capacity as a function of pressure and temperature -Cv_ph Specific isochoric heat capacity as a function of pressure and enthalpy -Cv_ps Specific isochoric heat capacity as a function of pressure and entropy -======== ================================================= - -Speed of sound -++++++++++++++ -======== ================================================= -Function Description -======== ================================================= -wV_p Saturated vapor speed of sound -wL_p Saturated liquid speed of sound -wV_t Saturated vapor speed of sound -wL_t Saturated liquid speed of sound -w_pt Speed of sound as a function of pressure and temperature -w_ph Speed of sound as a function of pressure and enthalpy -w_ps Speed of sound as a function of pressure and entropy -======== ================================================= - -Viscosity -+++++++++ -======== ================================================= -Function Description -======== ================================================= -my_pt Viscosity as a function of pressure and temperature -my_ph Viscosity as a function of pressure and enthalpy -my_ps Viscosity as a function of pressure and entropy -======== ================================================= - -Thermal Conductivity -++++++++++++++++++++ -======== ================================================= -Function Description -======== ================================================= -tcL_p Saturated vapor thermal conductivity -tcV_p Saturated liquid thermal conductivity -tcL_t Saturated vapor thermal conductivity -tcV_t Saturated liquid thermal conductivity -tc_pt Thermal conductivity as a function of pressure and temperature -tc_ph Thermal conductivity as a function of pressure and enthalpy -tc_hs Thermal conductivity as a function of enthalpy and entropy -======== ================================================= - -Surface tension -+++++++++++++++ -======== ================================================= -Function Description -======== ================================================= -st_t Surface tension for two phase water/steam as a function of T -st_p Surface tension for two phase water/steam as a function of p -======== ================================================= - -vapor fraction -++++++++++++++ -======== ================================================= -Function Description -======== ================================================= -x_ph vapor fraction as a function of pressure and enthalpy -x_ps vapor fraction as a function of pressure and entropy -======== ================================================= - -vapor volume fraction -+++++++++++++++++++++ -======== ================================================= -Function Description -======== ================================================= -vx_ph vapor volume fraction as a function of pressure and enthalpy -vx_ps vapor volume fraction as a function of pressure and entropy -======== ================================================= - -Pressure along the Melting and Sublimation Curves -+++++++++++++++++++++++++++++++++++++++++++++++++ -======== ================================================= -Function Description -======== ================================================= -pmelt_t Pressure along the melting curve as a function of temperature -psubl_t Pressure along the sublimation curve as a function of temperature -======== ================================================= - - -Available Functions for Heavy Water -################################### - -======== ================================================= -Function Description -======== ================================================= -my_rhoT Viscosity as a function of density and temperature -tc_rhoT Thermal conductivity as a function of density and temperature -======== ================================================= diff --git a/docs/source/pyXSteamDemo.rst b/docs/source/pyXSteamDemo.rst index 7d99a8b..b0b14a4 100644 --- a/docs/source/pyXSteamDemo.rst +++ b/docs/source/pyXSteamDemo.rst @@ -16,14 +16,6 @@ By using the unitSystem Parameter, you can tell XSteam witch Unit System you are steam_table = XSteam(XSteam.UNIT_SYSTEM_FLS) # ft/lb/sec/°F/psi/btu steam_table = XSteam(XSteam.UNIT_SYSTEM_BARE) # m/kg/sec/K/MPa/W -To enable logging, add the following lines to your code:: - - import logging - logger = logging.getLogger('pyXSteam') - logger.setLevel(logging.DEBUG) sh = logging.StreamHandler() - sh.setFormatter(logging.Formatter('%(name)s - %(levelname)s - %(message)s')) - logger.addHandler(sh) - Calculate single values ======================= This is a simple example:: @@ -42,7 +34,7 @@ By converting one to the functions to a NumPy universal function it is easy to u >>> npv_pt = np.frompyfunc(steam_table.v_pt, 2, 1) * `NumPy documentation for frombyfunc `_ -* `pyXSteamDemo.py `_ +* `pyXSteamDemo.py `_ Usage with pandas ================= @@ -75,7 +67,18 @@ Example: To draw a T(p) diagram showing the saturation curve:: pyplot.setp(line1, linewidth=1, color='b') pyplot.show() -For more demos, see `pyXSteamDemo.py `_ +For more demos, see `pyXSteamDemo.py `_ + +More Diagrams +------------- + +For even more examples of diagrams generated with pyXSteam, see the repositories by Richard J Smith + + - `steam-properties `_ + - `steam-cycles-Ideal `_ + - `steam-cycles-non-ideal `_ + - `steam-cycles-regenerative `_ + Heavy Water functions ===================== @@ -91,7 +94,7 @@ Content of the demo files Main demo file pyXSteamDemo.py ============================== -.. literalinclude:: ../../bin/pyXSteamDemo.py +.. literalinclude:: ../../pyXSteam/scripts/pyXSteamDemo.py :language: python Example on how to calculate the values for a rankine cycle @@ -99,5 +102,5 @@ Example on how to calculate the values for a rankine cycle Matlab example from converted example from Stu Blair converted to python Original can be found at `his github page `_ -.. literalinclude:: ../../bin/pyXSteamRankineDemo.py +.. literalinclude:: ../../pyXSteam/scripts/pyXSteamRankineDemo.py :language: python diff --git a/pyXSteam/Constants.py b/pyXSteam/Constants.py index 989b38a..134ebd5 100755 --- a/pyXSteam/Constants.py +++ b/pyXSteam/Constants.py @@ -4,40 +4,94 @@ Constants for the calculation of water steam properties Sources: - -* IAPWS Industrial formulation 1997 for the Thermodynamic Properties of Water and Steam, September 1997 - -* IAWPS Release on Vaues of Temperature, Pressure and Density of Ordinary and Heavy Water Substances at their Respective Critical Points Released September 1992, Revision of the Release of 1992 - +* IAPWS Industrial formulation 1997 for the Thermodynamic Properties of Waterand Steam, September 1997 +* IAWPS R2-83(1992) Values of Temperature, Pressure and Density of Ordinary and Heavy Water Substances at their Respective Critical Points +* IAPWS R15-11 +* IAPWS R17 and IAPWS R18 +* https://doi.org/10.1063/1.5053993 """ +from enum import IntEnum -__SPECIFIC_GAS_CONSTANT__ = 0.461526 # kJ kg^-1 K^-1 -__CRITICAL_TEMPERATURE__ = 647.096 # K -__CRITICAL_PRESSURE__ = 22.06395 # MPa -__CRITICAL_DENSITY__ = 322 # kg m^-1 -__TRIPLE_POINT_TEMPERATURE__ = 273.16 # K (Eq9 Page 7) -__TRIPLE_POINT_PRESSURE__ = 0.000611657 # MPa (Eq9 Page 7) -__TRIPLE_POINT_SPECIFIC_ENTHALPY__ = 0.611783e-3 # kJ kg^-1 (Eq10 Page 7) +SPECIFIC_GAS_CONSTANT = 0.461526 # kJ / (kg K) +CRITICAL_TEMPERATURE = 647.096 # K +CRITICAL_PRESSURE = 22.06395 # MPa +CRITICAL_DENSITY = 322.0 # kg / m +TRIPLE_POINT_TEMPERATURE = 273.16 # K (Eq9 Page 7) +TRIPLE_POINT_PRESSURE = 0.000611657 # MPa (Eq9 Page 7) +TRIPLE_POINT_SPECIFIC_ENTHALPY = 0.611783e-3 # kJ / kg (Eq10 Page 7) +FREEZING_TEMPERATURE_H2O = 273.15 # K -# IAWPS Release on Vaues of Temperature, Pressure and Density of Ordinary and -# Heavy Water Substances at their Respective Critical Points -# Released September 1992, Revision of the Release of 1992 -__CRITICAL_TEMPERATURE_H20_1992__ = 647.096 # +-0.1 K -__CRITICAL_PRESSURE_H20_1992__ = 22.067 # + 0.27*(+-0.1)+-0.005 MPa -__CRITICAL_DENSITY_H20_1992__ = 322 # +-3 kg m^-1 -__CRITICAL_TEMPERATURE_D20_1992__ = 643.847 # +-0.2 K -__CRITICAL_PRESSURE_D20_1992__ = 21.671 # + 0.27*(+-0.2)+-0.01 MPa -__CRITICAL_DENSITY_D20_1992__ = 356 # +-5 kg m^-1 +# IAWPS R2-83(1992) Release on Values of Temperature, Pressure and Density of Ordinary and Heavy Water Substances at their +# Respective Critical Points, Released September 1992, Revision of the Release of 1983 +# http://www.iapws.org/relguide/crits.pdf +CRITICAL_TEMPERATURE_H20_1992 = 647.096 # +-0.1 K +CRITICAL_PRESSURE_H20_1992 = 22.067 # +0.27*(+-0.1)+-0.005 MPa +CRITICAL_DENSITY_H20_1992 = 322.0 # +-3 kg / m +CRITICAL_TEMPERATURE_D20_1992 = 643.847 # +-0.2 K +CRITICAL_PRESSURE_D20_1992 = 21.671 # +0.27*(+-0.2)+-0.01 MPa +CRITICAL_DENSITY_D20_1992 = 356.0 # +-5 kg / m # Other common constants used in calculations -__ABSOLUTE_ZERO_CELSIUS__ = -273.15 # °C -__ABSOLUTE_ZERO_FAHRENHEIT__ = -459.67 # °F - +ABSOLUTE_ZERO_CELSIUS = -273.15 # °C +ABSOLUTE_ZERO_FAHRENHEIT = -459.67 # °F # IAPWS R15-11 __SPECIFIC_GAS_CONSTANT_IAPWS_R15_11__ = 0.46151805 # kJ kg^-1 K^-1 __CRITICAL_TEMPERATURE_IAPWS_R15_11__ = 647.096 # K __CRITICAL_DENSITY_IAPWS_R15_11__ = 322.0 # kg m^-1 + +# IAPWS R17 and IAPWS R18 +__REFERENCE_TEMPERATURE_D20_R17_R18__ = 643.847 # T* in K +__REFERENCE_PREASSURE_D20_R17_R18__ = 21.6618 # p* in MPa +__REFERENCE_DENSITY_D20_R17_R18__ = 356.0 # ρ* in kg m-3 +__REFERENCE_VISCOSITY_D20_R17_R18__ = 1.00e-6 # μ* Pa s +__REFERENCE_THERMAL_CONDUCTIVITY_D20_R18__ = 1e-3 # λ* in W m-1 K-1 +__SPECIFIC_GAS_CONSTANT_D20_R17_R18__ = 0.41515199 # R in kJ kg-1 K-1 + + +# https://doi.org/10.1063/1.5053993 +__TRIPLE_POINT_TEMPERATURE_D2O_RESHW_2018__ = 276.969 # K +__TRIPLE_POINT_PRESSURE_D20_RESHW_2018__ = 0.00061159 # MPa + + +class UnitSystem(IntEnum): + """enum for supported unit systems""" + + BARE = 1 # m/kg/sec/K/MPa/W + MKS = 1 # m/kg/sec/°C/bar/W + FLS = 2 # ft/lb/sec/°F/psi/btu + + @classmethod + def has_value(cls, value: int): + """check if value is member of enum""" + return value in cls._value2member_map_ + + +class IceType(IntEnum): + """enum for the types of ice""" + + Ih = 1 + III = 3 + V = 5 + VI = 6 + VII = 7 + NONE = -1 + + @classmethod + def has_value(cls, value: int): + """check if value is member of enum""" + return value in cls._value2member_map_ + + +class DiagramRegion(IntEnum): + """enum for the regions""" + + NILL = 0 # Error, Outside valid area + R1 = 1 + R2 = 2 + R3 = 3 + R4 = 4 + R5 = 5 diff --git a/pyXSteam/IAPWS_R12.py b/pyXSteam/IAPWS_R12.py new file mode 100644 index 0000000..1df632e --- /dev/null +++ b/pyXSteam/IAPWS_R12.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +IAPWS R12-08(2008) +Release on the IAPWS Formulation 2008 for the Viscosity of Ordinary Water Substance +http://www.iapws.org/relguide/visc.pdf +""" +import math +import logging + +logger = logging.getLogger(__name__) + + +def _my_dash_0(T_dash: float) -> float: + # viscosity in the dilute-gas limit, eq 11, page 5 + H = [1.67752, 2.20462, 0.6366564, -0.241605] + numerator = 100 * math.sqrt(T_dash) + denominator = 0 + for i in range(0, 4): + denominator += H[i] / T_dash**i + return numerator / denominator + + +def _my_dash_1(T_dash: float, rho_dash: float) -> float: + # contribution to viscosity due to finite density, eq 12, page 5 + # first index is i, second index is j + H = [[0.0 for j in range(0, 7)] for i in range(0, 6)] + H[0][0] = 5.20094e-1 + H[1][0] = 8.50895e-2 + H[2][0] = -1.08374 + H[3][0] = -2.89555e-1 + H[0][1] = 2.22531e-1 + H[1][1] = 9.99115e-1 + H[2][1] = 1.88797 + H[3][1] = 1.26613 + H[5][1] = 1.20573e-1 + H[0][2] = -2.81378e-1 + H[1][2] = -9.06851e-1 + H[2][2] = -7.72479e-1 + H[3][2] = -4.89837e-1 + H[4][2] = -2.57040e-1 + H[0][3] = 1.61913e-1 + H[1][3] = 2.57399e-1 + H[0][4] = -3.25372e-2 + H[3][4] = 6.98452e-2 + H[4][5] = 8.72102e-3 + H[3][6] = -4.35673e-3 + H[5][6] = -5.93264e-4 + + sum_t = 0 + for i in range(0, 6): # i + sum_rho = 0 + for j in range(0, 7): # j + sum_rho += H[i][j] * ((rho_dash - 1) ** j) + sum_t += (((1 / T_dash) - 1) ** i) * sum_rho + return math.exp(rho_dash * sum_t) + + +def _l(w: float, q_C: float, xi: float) -> float: + # eq 18 + if (q_C * xi) > 1: + return math.log((1 + w) / (1 - w)) + return 2 * math.atan(abs(w)) + + +def _y(xi: float) -> float: + inv_q_C = 1.9 # table 3, critical-region constants + inv_q_D = 1.1 # table 3, critical-region constants + q_C = 1 / inv_q_C + q_D = 1 / inv_q_D + + if 0 <= xi <= 0.3817016416: + coefficient_0 = (1 / 5) * q_C * xi * (q_D * xi) ** 5 + summand_0 = q_C * xi + summand_1 = (q_C * xi) ** 2 + summand_2 = (765 / 504) * ((q_D * xi) ** 2) + coefficient_1 = 1 - summand_0 + summand_1 - summand_2 + return coefficient_0 * coefficient_1 + + psi_D = math.acos((1 + (q_D**2) * (xi**2)) ** (-1 / 2)) # ep 17 + + summand_0 = 1 / 12 * math.sin(3 * psi_D) # ep16, part 1 + + summand_1 = (1 / (4 * q_C * xi)) * math.sin(2 * psi_D) # ep16, part 2 + + summand_2 = (1 / (q_C * xi) ** 2) * (1 - (5 / 4) * (q_C * xi) ** 2) * math.sin(psi_D) # ep16, part 3 + + w = abs((q_C * xi - 1) / (q_C * xi + 1)) ** (1 / 2) * math.tan(psi_D / 2) # ep 19 + sum3_sub0 = (1 - (3 / 2 * (q_C * xi) ** 2)) * psi_D + sum3_sub1 = abs((q_C * xi) ** 2 - 1) ** 3 / 2 * _l(w, q_C, xi) + summand_3 = (1 / (q_C * xi) ** 3) * (sum3_sub0 - sum3_sub1) # ep16, part 4 + + y_total = summand_0 - summand_1 + summand_2 - summand_3 # ep 16 + + logger.debug("value for Y: %f", y_total) + + return y_total + + +def _sigma(rho_dash: float, T_dash: float) -> float: + # eq 21a + # TODO + logger.debug("rho_dash %f T_dash %f", rho_dash, T_dash) + raise NotImplementedError("use derivative of density on pressure at constant temperature") + + +def _delta_chi_dash(rho_dash: float, T_dash: float) -> float: + T_dash_R = 1.5 # table 3, critical-region constants + + sigma_0 = _sigma(rho_dash, T_dash) + sigma_1 = _sigma(rho_dash, T_dash_R) + + return rho_dash * (sigma_0 - sigma_1 * (T_dash_R / T_dash)) + + +def _my_dash_2(T: float, rho: float, T_dash: float, rho_dash: float) -> float: + if 645.91 < T < 650.77 and 245.8 < rho < 405.3: # eq 13, page 6 + logger.debug("values for T and rho are within critical region") + # critical region + x_my = 0.068 # critical exponent for viscosity + + ny = 0.630 # table 3, critical-region constants + gamma = 1.239 # table 3, critical-region constants + xi_0 = 1.239 # table 3, critical-region constants + gamma_0 = 0.06 # table 3, critical-region constants + + delta_chi_dash = _delta_chi_dash(rho_dash, T_dash) + + if delta_chi_dash < 0: + delta_chi_dash = 0 + + xi = xi_0 * (delta_chi_dash / gamma_0) ** (ny / gamma) + + my_dash_2 = math.exp(x_my * _y(xi)) # eq 14 + logger.debug("value for my_dash_2:%f", my_dash_2) + return my_dash_2 + + logger.debug("values for T and rho are outside of critical region, use my_dash_2=1.0") + return 1.0 # section 2.8, page 8 + + +def eq10(T: float, rho: float, industrial: bool = True) -> float: + """equation 10""" + logger.debug("input values T=%fK rho=%fkm/m^3", T, rho) + # p_t = Constants.__TRIPLE_POINT_PRESSURE__ + # T_t = Constants.__TRIPLE_POINT_TEMPERATURE__ + + # T_m = -1 # TODO: pressure-dependent melting temperature + + T_star = 647.096 + rho_star = 322.0 + # p_star = 22.064 + my_star = 1.00e-6 + + T_dash = T / T_star + rho_dash = rho / rho_star + # p_dash = p / p_star + + # if 0 < p < p_t and T_t <= T <= 1173.15: + # pass + # elif p_t <= p <= 300 and T_m <= T <= 1173.15: + # pass + # elif 300 < p <= 350 and T_m <= T <= 873.15: + # pass + # elif 350 < p <= 500 and T_m <= T <= 433.15: + # pass + # elif 500 <= p <= 1000 and T_m <= T <= 373.15: + # pass + # else: + # logger.warning("eq10 not valid for p=%f and T=%f", p, T) + + my_dash_0 = _my_dash_0(T_dash) + my_dash_1 = _my_dash_1(T_dash, rho_dash) + + if industrial: # section 3 + my_dash_2 = 1.0 + else: + my_dash_2 = _my_dash_2(T, rho, T_dash, rho_dash) + + my_dash = my_dash_0 * my_dash_1 * my_dash_2 # eq 10 + + logger.debug("calculated values µ_0=%f µ_1=%f µ_2=%f µ_dash=%f", my_dash_0, my_dash_1, my_dash_2, my_dash) + + my = my_dash * my_star # eq8, value is in µPa*s + # my = my * 10E6 # in Pa*s + return my diff --git a/pyXSteam/IAPWS_R14.py b/pyXSteam/IAPWS_R14.py index 231a359..78e7763 100755 --- a/pyXSteam/IAPWS_R14.py +++ b/pyXSteam/IAPWS_R14.py @@ -10,66 +10,98 @@ logger = logging.getLogger(__name__) -__TYPE_ICE_Ih__ = 1 -__TYPE_ICE_III__ = 3 -__TYPE_ICE_V__ = 5 -__TYPE_ICE_VI__ = 6 -__TYPE_ICE_VII__ = 7 - -def pmelt_T_iceIh(T): +def pmelt_T_iceIh(T: float) -> float: """ - EQ 1 / Melting pressure of ice Ih + Melting pressure of ice of type Ih + based on IAPWS R14-08(2011) EQ 1 + + :param T: temperature in [K] + + :return: melting preasure in [MPa] """ + logger.debug("calculating 'melting preasure of ice type Ih' for T=%f", T) T_star = 273.16 p_star = 611.657e-6 theta = T / T_star - a = (0.119539337e7, 0.808183159e5, 0.333826860e4) - b = (0.300000e1, 0.257500e2, 0.103750e3) + a = [0.119539337e7, 0.808183159e5, 0.333826860e4] + b = [0.300000e1, 0.257500e2, 0.103750e3] temp_sum = 0 for i in range(0, 3): temp_sum += a[i] * (1 - theta ** b[i]) pi_melt = 1 + temp_sum - return pi_melt * p_star + p_melt = pi_melt * p_star + logger.debug("result for 'melting preasure of ice type Ih': %f", p_melt) + return p_melt -def pmelt_T_iceIII(T): +def pmelt_T_iceIII(T: float) -> float: """ - EQ 2 / Melting pressure of ice III + Melting pressure of ice of type III + based on IAPWS R14-08(2011) EQ 2 + + :param T: temperature in [K] + + :return: melting preasure in [MPa] """ + logger.debug("calculating 'melting preasure of ice type III' for T=%f", T) T_star = 251.165 p_star = 208.566 theta = T / T_star pi_melt = 1 - 0.299948 * (1.0 - theta**60) - return pi_melt * p_star + p_melt = pi_melt * p_star + logger.debug("result for 'melting preasure of ice type III': %f", p_melt) + return p_melt -def pmelt_T_iceV(T): +def pmelt_T_iceV(T: float) -> float: """ - EQ 3 / Melting pressure of ice V + Melting pressure of ice of type V + based on IAPWS R14-08(2011) EQ 3 + + :param T: temperature in [K] + + :return: melting preasure in [MPa] """ + logger.debug("calculating 'melting preasure of ice type V' for T=%f", T) T_star = 256.164 p_star = 350.1 theta = T / T_star pi_melt = 1 - 1.18721 * (1.0 - theta**8) - return pi_melt * p_star + p_melt = pi_melt * p_star + logger.debug("result for 'melting preasure of ice type V': %f", p_melt) + return p_melt -def pmelt_T_iceVI(T): +def pmelt_T_iceVI(T: float) -> float: """ - EQ 4 / Melting pressure of ice VI + Melting pressure of ice of type VI + based on IAPWS R14-08(2011) EQ 4 + + :param T: temperature in [K] + + :return: melting preasure in [MPa] """ + logger.debug("calculating 'melting preasure of ice type VI' for T=%f", T) T_star = 273.31 p_star = 632.4 theta = T / T_star pi_melt = 1 - 1.07476 * (1.0 - theta**4.6) - return pi_melt * p_star + p_melt = pi_melt * p_star + logger.debug("result for 'melting preasure of ice type VI': %f", p_melt) + return p_melt -def pmelt_T_iceVII(T): +def pmelt_T_iceVII(T: float) -> float: """ - EQ 5 / Melting pressure of ice VII + Melting pressure of ice of type VII + based on IAPWS R14-08(2011) EQ 5 + + :param T: temperature in [K] + + :return: melting preasure in [MPa] """ + logger.debug("calculating 'melting preasure of ice type VII' for T=%f", T) T_star = 355.0 p_star = 2216.0 theta = T / T_star @@ -77,20 +109,30 @@ def pmelt_T_iceVII(T): p2 = 0.544606e-1 * (1 - (theta**5)) p3 = 0.806106e-7 * (1 - (theta**22)) pi_melt = math.exp(p1 - p2 + p3) - return pi_melt * p_star + p_melt = pi_melt * p_star + logger.debug("result for 'melting preasure of ice type VII': %f", p_melt) + return p_melt -def psubl_T(T): +def psubl_T(T: float) -> float: """ - EQ 6 / Sublimation Pressure + Sublimation Pressure of ice + based on IAPWS R14-08(2011) EQ 6 + + :param T: temperature in [K] + + :return: sublimation preasure in [MPa] """ + logger.debug("calculating 'sublimation preasure of ice' for T=%f", T) T_star = 273.16 p_star = 611.657e-6 - a = (-0.212144006e2, 0.273203819e2, -0.610598130e1) - b = (0.333333333e-2, 0.120666667e1, 0.170333333e1) + a = [-0.212144006e2, 0.273203819e2, -0.610598130e1] + b = [0.333333333e-2, 0.120666667e1, 0.170333333e1] theta = T / T_star temp_sum = 0 for i in range(0, 3): temp_sum += a[i] * theta ** b[i] pi_subl = math.exp((theta**-1) * temp_sum) - return pi_subl * p_star + p_subl = pi_subl * p_star + logger.debug("result for 'sublimation preasure of ice': %f", p_subl) + return p_subl diff --git a/pyXSteam/IAPWS_R4.py b/pyXSteam/IAPWS_R4.py index 845b244..79b996e 100755 --- a/pyXSteam/IAPWS_R4.py +++ b/pyXSteam/IAPWS_R4.py @@ -11,21 +11,25 @@ logger = logging.getLogger(__name__) -def myHW_rhoT_R4(rho, T): - """Viscosity as a function of density and temperature for heavy water - substance +def myHW_rhoT(rho: float, T: float) -> float: + pass - Args: - rho (float): density value for heavy water - T (float): temperature value for heavy water - Returns: - my (float): viscosity or NaN if arguments are out of range +def myHW_rhoT_R4(rho: float, T: float) -> float: """ - logger.debug("myHW_rhoT_R4 input: ρ %f kg/m^3, T %f K", rho, T) + Viscosity as a function of density and temperature for heavy water substance. + Returns NaN if arguments are out of range + + :param rho: density value for heavy water in [kg / m³] + :param T: temperature value for heavy water in [K] + + :return: viscosity µ or NaN if arguments are out of range, in [Pa s] + """ + raise DeprecationWarning("R4-84 was superseded by R17 and R18!") + logger.debug("calculating 'viscosity of heavy water' for ρ=%f and T=%f", rho, T) T_star = 643.847 # K - rho_star = 358 # kg / m^3 + rho_star = 358 # kg / m³ my_star = 55.2651 # µ Pa s T_dash = T / T_star @@ -37,17 +41,15 @@ def myHW_rhoT_R4(rho, T): sum_A_T += A[i] / (T_dash**i) my_0_dash = math.sqrt(T_dash) / sum_A_T - B = list() - B.append( - [0.4864192, -0.2448372, -0.8702035, 0.8716056, -1.051126, 0.3458395] - ) # j= 0 - B.append([0.3509007, 1.315436, 1.297752, 1.353448, 0.0, 0.0]) # j= 1 - B.append([-0.2847572, -1.037026, -1.287846, 0.0, 0.0, -0.02148229]) # j= 2 - B.append([0.07013759, 0.4660127, 0.2292075, -0.4857462, 0.0, 0.0]) # j= 3 - B.append([0.01641220, -0.02884911, 0.0, 0.1607171, 0.0, -0.009603846]) # j= 4 - B.append([-0.01163815, -0.008239587, 0.0, 0.0, 0.0, 0.004559914]) # j= 5 - B.append([0.0, 0.0, 0.0, -0.003886659, 0.0, 0.0]) # j= 6 - + B = [ + [0.4864192, -0.2448372, -0.8702035, 0.8716056, -1.051126, 0.3458395], + [0.3509007, 1.315436, 1.297752, 1.353448, 0.0, 0.0], + [-0.2847572, -1.037026, -1.287846, 0.0, 0.0, -0.02148229], + [0.07013759, 0.4660127, 0.2292075, -0.4857462, 0.0, 0.0], + [0.01641220, -0.02884911, 0.0, 0.1607171, 0.0, -0.009603846], + [-0.01163815, -0.008239587, 0.0, 0.0, 0.0, 0.004559914], + [0.0, 0.0, 0.0, -0.003886659, 0.0, 0.0], + ] temp_sum = 0 for i in range(0, 6): part_T = ((1.0 / T_dash) - 1.0) ** i @@ -62,28 +64,30 @@ def myHW_rhoT_R4(rho, T): my_dash = my_0_dash * my_1_dash my = my_dash * my_star - logger.debug("myHW_rhoT_R4 result: my %f", my) - + logger.debug("result for 'viscosity of heavy water': %f", my) return my -def tcHW_rhoT_R4(rho, T): - """Thermal conductivity as a function of density and temperature for heavy water - substance +def tcHW_rhoT_R4(rho: float, T: float) -> float: + """ + Thermal conductivity as a function of density and temperature for heavy + water substance. + Returns NaN if arguments are out of range - Note: using tc instead of lambda to minimize the confusion with the python function + Note: function name is using tc instead of lambda to minimize the confusion + with the python + function of the same name. - Args: - rho (float): density value for heavy water - T (float): temperature value for heavy water + :param rho: density value for heavy water in [kg / m³] + :param T: temperature value for heavy water in [K] - Returns: - λ (float): thermal conductivity or NaN if arguments are out of range + :return: thermal conductivity λ or NaN, in [W / (m * K)] """ - logger.debug("tcHW_rhoT_R4 input: ρ %f kg/m^3, T %f K", rho, T) + raise DeprecationWarning("R4-84 was superseded by R17 and R18!") + logger.debug("calculating 'thermal conductivity of heavy water' for ρ=%f and T=%f", rho, T) T_star = 643.847 # K - rho_star = 358 # kg / m^3 + rho_star = 358 # kg / m³ tc_star = 0.742128 # mW/(m K) T_dash = T / T_star @@ -103,9 +107,7 @@ def tcHW_rhoT_R4(rho, T): D_1 = -741.112 tau = T_dash / (math.fabs(T_dash - 1.1) + 1.1) # B15 f_1 = math.exp(C_T1 * T_dash + C_T2 * (T_dash**2)) # B12 - f_2 = math.exp(C_R1 * (rho_dash - 1.0) ** 2) + C_R2 * math.exp( - C_R3 * (rho_dash - rho_r1) ** 2 - ) # B13 + f_2 = math.exp(C_R1 * (rho_dash - 1.0) ** 2) + C_R2 * math.exp(C_R3 * (rho_dash - rho_r1) ** 2) # B13 f_3 = 1 + math.exp(60.0 * (tau - 1.0) + 20.0) # B14 f_4 = 1 + math.exp(100.0 * (tau - 1.0) + 15.0) # B14 part_C2 = (C_2 * f_1**4) / f_3 @@ -133,5 +135,6 @@ def tcHW_rhoT_R4(rho, T): tc_dash = tc_o + delta_tc + delta_tc_c + delta_tc_L tc = tc_dash * tc_star - logger.debug("tcHW_rhoT_R4 result: λ %f", tc) + + logger.debug("calculating 'thermal conductivity of heavy water': %f", tc) return tc diff --git a/pyXSteam/RegionBorders.py b/pyXSteam/RegionBorders.py index b2b9eae..5e9101d 100755 --- a/pyXSteam/RegionBorders.py +++ b/pyXSteam/RegionBorders.py @@ -3,207 +3,118 @@ """ Section 4: Region Borders """ +import math +import logging +from .Tables import R7_97, SR2_01, SR3_03, SR4_04 -def B23p_T(T): - """function B23p_T = B23p_T(T) +logger = logging.getLogger(__name__) + + +def pB23_T(T: float) -> float: + """ + calculate preasure from temperature for boundary between region 2 and 3 Section 4.1 Boundary between region 2 and 3. - Release on the IAPWS Industrial formulation 1997 for the Thermodynamic Properties of Water and Steam 1997 Section 4 Auxiliary Equation for the Boundary between Regions 2 and 3 + Release on the IAPWS Industrial formulation 1997 for the Thermodynamic Properties + of Water and Steam 1997 Section 4 Auxiliary Equation for the Boundary + between Regions 2 and 3 Eq 5, Page 5 + + :param T: temperature in [K] + + :return: preasure in [MPa] """ - return 348.05185628969 - 1.1671859879975 * T + 1.0192970039326e-03 * (T**2) + return R7_97.Table1_n[0] + R7_97.Table1_n[1] * T + R7_97.Table1_n[2] * (T**2) -def B23T_p(p): - """function B23T_p = B23T_p(p) +def TB23_p(p: float) -> float: + """ + calculate temperature from preasure for boundary between region 2 and 3 Section 4.1 Boundary between region 2 and 3. - Release on the IAPWS Industrial formulation 1997 for the Thermodynamic Properties of Water and Steam 1997 Section 4 Auxiliary Equation for the Boundary between Regions 2 and 3 + Release on the IAPWS Industrial formulation 1997 for the Thermodynamic Properties + of Water and Steam 1997 Section 4 Auxiliary Equation for the Boundary + between Regions 2 and 3 Eq 6, Page 6 - """ - return 572.54459862746 + ((p - 13.91883977887) / 1.0192970039326e-03) ** 0.5 + :param p: preasure in [MPa] + + :return: temperature in [K] + """ + return R7_97.Table1_n[3] + ((p - R7_97.Table1_n[4]) / R7_97.Table1_n[2]) ** 0.5 -def p3sat_h(h): - """function p3sat_h = p3sat_h(h) - Section 4.2 Region 3. pSat_h & pSat_s +def hB13_s(s: float) -> float: + """SR4-04(2014) Eq 7 calculate enthalpy from specific entropy for border between region 1 and 3 - Revised Supplementary Release on Backward Equations for the functions T(p,h), v(p,h) s& T(p,s), v(p,s) for Region 3 of the IAPWS Industrial formulation 1997 for the Thermodynamic Properties of Water & Steam 2004 Section 4 Boundary Equations psat(h) & psat(s) for the Saturation Lines of Region 3 + :param s: specific entropy in [kJ / (kg K)] - See pictures Page 17, Eq 10, Table 17, Page 18 - """ - Ii = [0, 1, 1, 1, 1, 5, 7, 8, 14, 20, 22, 24, 28, 36] - Ji = [0, 1, 3, 4, 36, 3, 0, 24, 16, 16, 3, 18, 8, 24] - ni = [ - 0.600073641753024, - -9.36203654849857, - 24.6590798594147, - -107.014222858224, - -91582131580576.8, - -8623.32011700662, - -23.5837344740032, - 2.52304969384128e17, - -3.89718771997719e18, - -3.33775713645296e22, - 35649946963.6328, - -1.48547544720641e26, - 3.30611514838798e18, - 8.13641294467829e37, - ] - hs = h / 2600 - ps = 0 - for i in range(0, 14): - ps = ps + ni[i] * (hs - 1.02) ** Ii[i] * (hs - 0.608) ** Ji[i] - return ps * 22 - - -def p3sat_s(s): - """function p3sat_s = p3sat_s(s) - - Section 4.2 Region 3. pSat_h & pSat_s + :return: enthalpy in [kJ / kg] """ - Ii = [0, 1, 1, 4, 12, 12, 16, 24, 28, 32] - Ji = [0, 1, 32, 7, 4, 14, 36, 10, 0, 18] - ni = [ - 0.639767553612785, - -12.9727445396014, - -2.24595125848403e15, - 1774667.41801846, - 7170793495.71538, - -3.78829107169011e17, - -9.55586736431328e34, - 1.87269814676188e23, - 119254746466.473, - 1.10649277244882e36, - ] - Sigma = s / 5.2 - Pi = 0 - for i in range(0, 10): - Pi = Pi + ni[i] * (Sigma - 1.03) ** Ii[i] * (Sigma - 0.699) ** Ji[i] - return Pi * 22 - - -def hB13_s(s): - """function hB13_s = hB13_s(s) - - Section 4.3 Region boundary 1 to 3 & 3to2 as a functions of s - - Supplementary Release on Backward Equations ( ) , p h s for Region 3, Chapter 4.5 page 23. - """ - Ii = [0, 1, 1, 3, 5, 6] - Ji = [0, -2, 2, -12, -4, -3] - ni = [ - 0.913965547600543, - -4.30944856041991e-05, - 60.3235694765419, - 1.17518273082168e-18, - 0.220000904781292, - -69.0815545851641, - ] Sigma = s / 3.8 eta = 0 - for i in range(0, 6): - eta = eta + ni[i] * (Sigma - 0.884) ** Ii[i] * (Sigma - 0.864) ** Ji[i] + for I, J, n in zip(SR4_04.Table23_I, SR4_04.Table23_J, SR4_04.Table23_n): + eta += n * (Sigma - 0.884) ** I * (Sigma - 0.864) ** J # Eq7 return eta * 1700 -def TB23_hs(h, s): - """function TB23_hs = TB23_hs(h, s) +def TB23_hs(h: float, s: float) -> float: + """SR4-04(2014) Eq 8 calculate temperature from specific entropy and enthalpy for border between region 2 and 3 - Section 4.3 Region boundary 1to3 & 3to2 as a functions of s + :param h: enthalpy in [kJ / kg] + :param s: Specific entropy in [kJ / (kg K)] - Supplementary Release on Backward Equations () , p h s for Region 3, Chapter 4.6 page 25. + :return: temperature in [K] """ - Ii = [ - -12, - -10, - -8, - -4, - -3, - -2, - -2, - -2, - -2, - 0, - 1, - 1, - 1, - 3, - 3, - 5, - 6, - 6, - 8, - 8, - 8, - 12, - 12, - 14, - 14, - ] - Ji = [ - 10, - 8, - 3, - 4, - 3, - -6, - 2, - 3, - 4, - 0, - -3, - -2, - 10, - -2, - -1, - -5, - -6, - -3, - -8, - -2, - -1, - -12, - -1, - -12, - 1, - ] - ni = [ - 6.2909626082981e-04, - -8.23453502583165e-04, - 5.15446951519474e-08, - -1.17565945784945, - 3.48519684726192, - -5.07837382408313e-12, - -2.84637670005479, - -2.36092263939673, - 6.01492324973779, - 1.48039650824546, - 3.60075182221907e-04, - -1.26700045009952e-02, - -1221843.32521413, - 0.149276502463272, - 0.698733471798484, - -2.52207040114321e-02, - 1.47151930985213e-02, - -1.08618917681849, - -9.36875039816322e-04, - 81.9877897570217, - -182.041861521835, - 2.61907376402688e-06, - -29162.6417025961, - 1.40660774926165e-05, - 7832370.62349385, - ] - Sigma = s / 5.3 + sigma = s / 5.3 eta = h / 3000 teta = 0 - for i in range(0, 25): - teta = teta + ni[i] * (eta - 0.727) ** Ii[i] * (Sigma - 0.864) ** Ji[i] + for I, J, n in zip(SR4_04.Table25_I, SR4_04.Table25_J, SR4_04.Table25_n): + teta += n * (eta - 0.727) ** I * (sigma - 0.864) ** J # Eq 8 return teta * 900 + + +def pB2bc_h(h: float) -> float: + """R7-97(2012) Eq 2 + + :param h: enthalpy in [kJ / kg] + + :return: preasure in [MPa] + """ + return R7_97.Table19_n[0] + R7_97.Table19_n[1] * h + R7_97.Table19_n[2] * h**2 + + +def hB2bc_p(p: float) -> float: + """R7-97(2012) Eq 21 + + :param p: preasure in [MPa] + + :return: enthalpy in [kJ / kg] + """ + # TODO: this functions isn't used .... + return R7_97.Table19_n[3] + math.sqrt((p - R7_97.Table19_n[4]) / R7_97.Table19_n[2]) + + +def hB2bc_s(s: float) -> float: + """SR2-02(2016) Ep 2 + + :param s: Specific entropy in [kJ / (kg K)] + + :return: enthalpy in [kJ / kg] + """ + return SR2_01.Table5_n[0] + SR2_01.Table5_n[1] * s + SR2_01.Table5_n[2] * s**2 + SR2_01.Table5_n[3] * s**3 + + +def hB3ab_p(p: float) -> float: + """SR3-03(2014) Eq 1 + + :param p: preasure in [MPa] + + :return: enthalpy in [kJ / kg] + """ + return SR3_03.Table2_n[0] + SR3_03.Table2_n[1] * p + SR3_03.Table2_n[2] * p**2 + SR3_03.Table2_n[3] * p**3 diff --git a/pyXSteam/RegionSelection.py b/pyXSteam/RegionSelection.py index 659c004..0435086 100755 --- a/pyXSteam/RegionSelection.py +++ b/pyXSteam/RegionSelection.py @@ -5,332 +5,337 @@ """ import math import logging -from . import RegionBorders +from .RegionBorders import pB23_T, TB23_p, hB13_s, TB23_hs from .Regions import Region1, Region2, Region3, Region4, Region5 +from .Constants import ( + CRITICAL_TEMPERATURE, + TRIPLE_POINT_PRESSURE, + FREEZING_TEMPERATURE_H2O, + DiagramRegion, +) +from .Tables import SR3_03, SR4_04 logger = logging.getLogger(__name__) -"""Section 3.1 Regions as a function of pT""" +def select_region_pT(p: float, T: float) -> DiagramRegion: + """ + Section 3.1 Regions as a function of p and T + Select diagram region based on values of preasure and temperature + Returns `DiagramRegion.NILL` if arguments lead to no valid region + + :param p: preasure in [MPa] + :param T: temperature in [K] -def region_pT(p, T): - """function region_pT = region_pT(p, T)""" - if (T > 1073.15) and (p < 50.0) and (T < 2273.15) and (p > 0.000611): - region_pT_number = 5 - elif (T <= 1073.15) and (T > 273.15) and (p <= 100) and (p > 0.000611): + :return: diagram region + """ + if 0.000611 < p < 50.0 and 1073.15 < T < 2273.15: + return DiagramRegion.R5 + if FREEZING_TEMPERATURE_H2O < T <= 1073.15 and 0.000611 < p <= 100: if T > 623.15: - if p > RegionBorders.B23p_T(T): - region_pT_number = 3 - if T < 647.096: + if p > pB23_T(T): + region_pT_number = DiagramRegion.R3 + if T < CRITICAL_TEMPERATURE: ps = Region4.p4_T(T) if math.fabs(p - ps) < 0.00001: - region_pT_number = 4 + region_pT_number = DiagramRegion.R4 else: - region_pT_number = 2 + region_pT_number = DiagramRegion.R2 else: ps = Region4.p4_T(T) if math.fabs(p - ps) < 0.00001: - region_pT_number = 4 + region_pT_number = DiagramRegion.R4 elif p > ps: - region_pT_number = 1 + region_pT_number = DiagramRegion.R1 else: - region_pT_number = 2 + region_pT_number = DiagramRegion.R2 else: logger.warning("Temperature outside valid area") - region_pT_number = 0 # **Error, Outside valid area + region_pT_number = DiagramRegion.NILL return region_pT_number -def region_ph(p, h): - """unction region_ph = region_ph(p, h) +def select_region_ph(p: float, h: float) -> DiagramRegion: + """ + Section 3.2 Regions as a function of p and h + Select diagram region based on values of preasure and enthalpy + Returns DiagramRegion.NILL if arguments lead to no valid region + + :param p: preasure in [MPa] + :param h: enthalpy in [kJ / kg] - Section 3.2 Regions as a function of ph + :return: diagram region """ # Check if outside pressure limits - if (p < 0.000611657) or (p > 100): + if (p < TRIPLE_POINT_PRESSURE) or (p > 100): logger.warning("Preasure outside valid area") - return 0 + return DiagramRegion.NILL + # Check if outside low h. - if h < (0.963 * p + 2.2): # Linear adaption to h1_pt()+2 to speed up calculations. - if h < Region1.h1_pT(p, 273.15): + # Linear adaption to h1_pt()+2 to speed up calculations. + if h < (0.963 * p + 2.2): + if h < Region1.h1_pT(p, FREEZING_TEMPERATURE_H2O): logger.warning("Enthalpy outside valid area") - return 0 + return DiagramRegion.NILL + if p < 16.5292: # Below region 3, Check region 1, 4, 2, 5 # Check Region 1 Ts = Region4.T4_p(p) - hL = ( - 109.6635 * math.log(p) + 40.3481 * p + 734.58 - ) # Approximate function for hL_p - if ( - math.fabs(h - hL) < 100 - ): # if approximate is not god enough use real function + hL = 109.6635 * math.log(p) + 40.3481 * p + 734.58 # Approximate function for hL_p + if math.fabs(h - hL) < 100: # if approximate is not god enough use real function hL = Region1.h1_pT(p, Ts) if h <= hL: - return 1 + return DiagramRegion.R1 # Check Region 4 - hV = ( - 45.1768 * math.log(p) - 20.158 * p + 2804.4 - ) # Approximate function for hV_p + hV = 45.1768 * math.log(p) - 20.158 * p + 2804.4 # Approximate function for hV_p if math.fabs(h - hV) < 50: # if approximate is not god enough use real function hV = Region2.h2_pT(p, Ts) if h < hV: - return 4 + return DiagramRegion.R4 # Check upper limit of region 2 Quick Test if h < 4000: - return 2 + return DiagramRegion.R2 # Check region 2 (Real value) h_45 = Region2.h2_pT(p, 1073.15) if h <= h_45: - return 2 + return DiagramRegion.R2 # Check region 5 if p > 10: logger.warning("Preasure outside valid area") - return 0 + return DiagramRegion.NILL h_5u = Region5.h5_pT(p, 2273.15) if h < h_5u: - return 5 + return DiagramRegion.R5 logger.warning("Enthalpy outside valid area") - return 0 - else: # for p > 16.5292 - # Check if in region1 - if h < Region1.h1_pT(p, 623.15): - # region_ph = 1; - return 1 - # Check if in region 3 or 4 (Below Reg 2) - if h < Region2.h2_pT(p, RegionBorders.B23T_p(p)): - # Region 3 or 4 - if p > RegionBorders.p3sat_h(h): - return 3 - else: - return 4 - # Check if region 2 - if h < Region2.h2_pT(p, 1073.15): - return 2 + return DiagramRegion.NILL + # for p > 16.5292 + # Check if in region1 + if h < Region1.h1_pT(p, 623.15): + return DiagramRegion.R1 + # Check if in region 3 or 4 (Below Reg 2) + if h < Region2.h2_pT(p, TB23_p(p)): + # Region 3 or 4 + if p > Region3.psat3_h(h): + return DiagramRegion.R3 + return DiagramRegion.R4 + # Check if region 2 + if h < Region2.h2_pT(p, 1073.15): + return DiagramRegion.R2 logger.warning("Preasure outside valid area") - return 0 + return DiagramRegion.NILL + +def select_region_ps(p: float, s: float) -> DiagramRegion: + """ + Section 3.3 Regions as a function of p and s + Select diagram region based on values of preasure and specific entropy + Returns `DiagramRegion.NILL` if arguments lead to no valid region -def region_ps(p, s): - """function region_ps = region_ps(p, s) + :param p: preasure in [MPa] + :param s: specific entropy in [kJ / (kg K)] - Section 3.3 Regions as a function of ps + :return: diagram region """ - if (p < 0.000611657) or (p > 100) or (s < 0) or (s > Region5.s5_pT(p, 2273.15)): + if (p < TRIPLE_POINT_PRESSURE) or (p > 100) or (s < 0) or (s > Region5.s5_pT(p, 2273.15)): logger.warning("Preasure or Entropy outside valid area") - return 0 + return DiagramRegion.NILL # Check region 5 if s > Region2.s2_pT(p, 1073.15): if p <= 10: - return 5 - else: - logger.warning("Preasure outside valid area") - return 0 + return DiagramRegion.R5 + logger.warning("Preasure outside valid area") + return DiagramRegion.NILL # Check region 2 if p > 16.529: - ss = Region2.s2_pT( - p, RegionBorders.B23T_p(p) - ) # Between 5.047 & 5.261. Use to speed up ! + # Between 5.047 & 5.261. Use to speed up ! + ss = Region2.s2_pT(p, TB23_p(p)) else: ss = Region2.s2_pT(p, Region4.T4_p(p)) if s > ss: - return 2 + return DiagramRegion.R2 # Check region 3 ss = Region1.s1_pT(p, 623.15) if (p > 16.529) and (s > ss): - if p > RegionBorders.p3sat_s(s): - return 3 - else: - return 4 + if p > Region3.psat3_s(s): + return DiagramRegion.R3 + return DiagramRegion.R4 # Check region 4 (Not inside region 3) if (p < 16.529) and (s > Region1.s1_pT(p, Region4.T4_p(p))): - return 4 + return DiagramRegion.R4 # Check region 1 - if (p > 0.000611657) and (s > Region1.s1_pT(p, 273.15)): - return 1 - return 1 + if (p > TRIPLE_POINT_PRESSURE) and (s > Region1.s1_pT(p, FREEZING_TEMPERATURE_H2O)): + return DiagramRegion.R1 + # ToDo: Check if Defaulting to region 1 is correct here + return DiagramRegion.R1 + +def select_region_hs(h: float, s: float) -> DiagramRegion: + """ + Section 3.4 Regions as a function of h and s + Select diagram region based on values of enthalpy and specific entropy + Returns `DiagramRegion.NILL` if arguments lead to no valid region -def region_hs(h, s): - """function region_hs = region_hs(h, s) + :param h: enthalpy in [kJ / kg] + :param s: specific entropy in [kJ / (kg K)] - Section 3.4 Regions as a function of hs + :return: diagram region """ - if s < -0.0001545495919: + if s < SR4_04.s_dash_low: logger.warning("Entropy outside valid area") - return 0 + return DiagramRegion.NILL # Check linear adaption to p=0.000611. if below region 4. hMin = ((-0.0415878 - 2500.89262) / (-0.00015455 - 9.155759)) * s - if (s < 9.155759395) and (h < hMin): + if (s < SR4_04.s_doubledash) and (h < hMin): logger.warning("Entalpy or Entropy outside valid area") - return 0 + return DiagramRegion.NILL # Kolla 1 eller 4. (+liten bit ???ver B13) - if (s >= -0.0001545495919) and (s <= 3.77828134): + if SR4_04.s_dash_low <= s <= SR4_04.s_dash_heigh: if h < Region4.h4_s(s): - return 4 - elif s < 3.397782955: # 100MPa line is limiting + return DiagramRegion.R4 + if s < SR4_04.s_heigh_mpa: # 100MPa line is limiting TMax = Region1.T1_ps(100, s) hMax = Region1.h1_pT(100, TMax) if h < hMax: - return 1 - else: - logger.warning("Entalpy outside valid area") - return 0 - else: # The point is either in region 4,1,3. Check B23 - hB = RegionBorders.hB13_s(s) - if h < hB: - return 1 - TMax = Region3.T3_ps(100, s) - vmax = Region3.v3_ps(100, s) - hMax = Region3.h3_rhoT(1 / vmax, TMax) - if h < hMax: - return 3 - else: - logger.warning("Entalpy outside valid area") - return 0 + return DiagramRegion.R1 + logger.warning("Entalpy outside valid area") + return DiagramRegion.NILL + # The point is either in region 4,1,3. Check B23 + hB = hB13_s(s) + if h < hB: + return DiagramRegion.R1 + TMax = Region3.T3_ps(100, s) + vmax = Region3.v3_ps(100, s) + hMax = Region3.h3_rhoT(1 / vmax, TMax) + if h < hMax: + return DiagramRegion.R3 + logger.warning("Entalpy outside valid area") + return DiagramRegion.NILL # Kolla region 2 eller 4. (???vre delen av omr???de b23-> max) - if (s >= 5.260578707) and (s <= 11.9212156897728): - if s > 9.155759395: # Above region 4 + if SR4_04.s_max_B23 <= s <= 11.9212156897728: + if s > SR4_04.s_doubledash: # Above region 4 Tmin = Region2.T2_ps(0.000611, s) hMin = Region2.h2_pT(0.000611, Tmin) # function adapted to h(1073.15,s) - hMax = ( - -0.07554022 * s**4 - + 3.341571 * s**3 - - 55.42151 * s**2 - + 408.515 * s - + 3031.338 - ) - if (h > hMin) and (h < hMax): - return 2 - else: - logger.warning("Entalpy outside valid area") - return 0 + hMax = -0.07554022 * s**4 + 3.341571 * s**3 - 55.42151 * s**2 + 408.515 * s + 3031.338 + if hMin < h < hMax: + return DiagramRegion.R2 + logger.warning("Entalpy outside valid area") + return DiagramRegion.NILL hV = Region4.h4_s(s) if h < hV: # Region 4. Under region 3. - return 4 + return DiagramRegion.R4 if s < 6.04048367171238: TMax = Region2.T2_ps(100, s) hMax = Region2.h2_pT(100, TMax) else: # function adapted to h(1073.15,s) - hMax = ( - -2.988734 * s**4 - + 121.4015 * s**3 - - 1805.15 * s**2 - + 11720.16 * s - - 23998.33 - ) + hMax = -2.988734 * s**4 + 121.4015 * s**3 - 1805.15 * s**2 + 11720.16 * s - 23998.33 if h < hMax: # Region 2. ???ver region 4. - return 2 - else: - logger.warning("Entalpy outside valid area") - return 0 - # Kolla region 3 eller 4. Under kritiska punkten. - if (s >= 3.77828134) and (s <= 4.41202148223476): + return DiagramRegion.R2 + logger.warning("Entalpy outside valid area") + return DiagramRegion.NILL + # Check region 3 or 4 below the critical point. + if SR4_04.s_dash_heigh <= s <= SR3_03.s_c: hL = Region4.h4_s(s) if h < hL: - return 4 + return DiagramRegion.R4 TMax = Region3.T3_ps(100, s) vmax = Region3.v3_ps(100, s) hMax = Region3.h3_rhoT(1 / vmax, TMax) if h < hMax: - return 3 - else: - logger.warning("Entalpy outside valid area") - return 0 - # Kolla region 3 eller 4 fr???n kritiska punkten till ???vre delen av b23 - if (s >= 4.41202148223476) and (s <= 5.260578707): + return DiagramRegion.R3 + logger.warning("Entalpy outside valid area") + return DiagramRegion.NILL + # Check region 3 or 4 from the critical point to the upper part of B23 + if SR4_04.s_c <= s <= SR4_04.s_max_B23: hV = Region4.h4_s(s) if h < hV: - return 4 - # Kolla om vi ???r under b23 giltighetsomr???de. - if s <= 5.048096828: + return DiagramRegion.R4 + # Check if we are under the B23 validity area. + if s <= SR4_04.s_min_B23: TMax = Region3.T3_ps(100, s) vmax = Region3.v3_ps(100, s) hMax = Region3.h3_rhoT(1 / vmax, TMax) if h < hMax: - return 3 - else: + return DiagramRegion.R3 + logger.warning("Entalpy outside valid area") + return DiagramRegion.NILL + # In the area of B23 in s area. + if h > 2812.942061: # Above B23 in h_led + if s > 5.09796573397125: + TMax = Region2.T2_ps(100, s) + hMax = Region2.h2_pT(100, TMax) + if h < hMax: + return DiagramRegion.R2 logger.warning("Entalpy outside valid area") - return 0 - else: # Inom omr???det f???r B23 i s led. - if h > 2812.942061: # Ovanf???r B23 i h_led - if s > 5.09796573397125: - TMax = Region2.T2_ps(100, s) - hMax = Region2.h2_pT(100, TMax) - if h < hMax: - return 2 - else: - logger.warning("Entalpy outside valid area") - return 0 - else: - logger.warning("Entropy outside valid area") - return 0 - if ( - h < 2563.592004 - ): # Nedanf???r B23 i h_led men vi har redan kollat ovanf???r hV2c3b - return 3 - # Vi ???r inom b23 omr???det i b???de s och h led. - Tact = RegionBorders.TB23_hs(h, s) - pact = Region2.p2_hs(h, s) - pBound = RegionBorders.B23p_T(Tact) - if pact > pBound: - return 3 - else: - return 2 + return DiagramRegion.NILL + logger.warning("Entropy outside valid area") + return DiagramRegion.NILL + if h < SR3_03.h_doubledash: # Below B23 in h_led but we have already checked above for hV2c3b + return DiagramRegion.R3 + # We are in the B23 field in both s and h joints. + Tact = TB23_hs(h, s) + pact = Region2.p2_hs(h, s) + pBound = pB23_T(Tact) + if pact > pBound: + return DiagramRegion.R3 + return DiagramRegion.R2 logger.warning("Entropy and Entalpy outside valid area") - return 0 + return DiagramRegion.NILL -def region_prho(p, rho): - """function region_prho = region_prho(p, rho) - +def select_region_prho(p: float, rho: float) -> DiagramRegion: + """ Section 3.5 Regions as a function of p and rho + Select diagram region based on values of preasure and density + Returns `DiagramRegion.NILL` if arguments lead to no valid region + + :param p: preasure in [MPa] + :param rho: density in [kg / m³] + + :return: diagram region """ v = 1 / rho - if (p < 0.000611657) or (p > 100): + if (p < TRIPLE_POINT_PRESSURE) or (p > 100): logger.warning("Preasure outside valid area") - return 0 + return DiagramRegion.NILL if p < 16.5292: # Below region 3, Check region 1,4,2 - if v < Region1.v1_pT( - p, 273.15 - ): # Observe that this is not actually min of v. Not valid Water of 4???C is ligther. + if v < Region1.v1_pT(p, FREEZING_TEMPERATURE_H2O): + # Observe that this is not actually min of v. Not valid for Water + # if temperature is smaller than 4°C since it is ligther. logger.warning("Specific volume outside valid area") - return 0 + return DiagramRegion.NILL if v <= Region1.v1_pT(p, Region4.T4_p(p)): - return 1 + return DiagramRegion.R1 if v < Region2.v2_pT(p, Region4.T4_p(p)): - return 4 + return DiagramRegion.R4 if v <= Region2.v2_pT(p, 1073.15): - return 2 + return DiagramRegion.R2 if p > 10: # Above region 5 logger.warning("Preasure outside valid area") - return 0 + return DiagramRegion.NILL if v <= Region5.v5_pT(p, 2073.15): - return 5 + return DiagramRegion.R5 else: # Check region 1,3,4,3,2 (Above the lowest point of region 3.) - if v < Region1.v1_pT( - p, 273.15 - ): # Observe that this is not actually min of v. Not valid Water of 4???C is ligther. + if v < Region1.v1_pT(p, FREEZING_TEMPERATURE_H2O): + # Observe that this is not actually min of v. Not valid for Water + # if temperature is smaller than 4°C since it is ligther. logger.warning("Specific volume outside valid area") - return 0 + return DiagramRegion.NILL if v < Region1.v1_pT(p, 623.15): - return 1 + return DiagramRegion.R1 # Check if in region 3 or 4 (Below Reg 2) - if v < Region2.v2_pT(p, RegionBorders.B23T_p(p)): + if v < Region2.v2_pT(p, TB23_p(p)): # Region 3 or 4 if p > 22.064: # Above region 4 - return 3 - if (v < Region3.v3_ph(p, Region4.h4L_p(p))) or ( - v > Region3.v3_ph(p, Region4.h4V_p(p)) - ): # Uses iteration!! - return 3 - else: - return 4 + return DiagramRegion.R3 + if (v < Region3.v3_ph(p, Region4.h4L_p(p))) or (v > Region3.v3_ph(p, Region4.h4V_p(p))): # Uses iteration!! + return DiagramRegion.R3 + return DiagramRegion.R4 # Check if region 2 if v < Region2.v2_pT(p, 1073.15): - return 2 + return DiagramRegion.R2 logger.warning("Preasure and Density outside valid area") - return 0 + return DiagramRegion.NILL diff --git a/pyXSteam/Regions.py b/pyXSteam/Regions.py index 5133741..c30d448 100755 --- a/pyXSteam/Regions.py +++ b/pyXSteam/Regions.py @@ -5,1087 +5,289 @@ """ import math import logging -from . import RegionBorders -from . import Constants +from .RegionBorders import TB23_p, pB2bc_h, hB2bc_s, hB3ab_p +from .Constants import ( + TRIPLE_POINT_PRESSURE, + FREEZING_TEMPERATURE_H2O, +) +from .Constants import SPECIFIC_GAS_CONSTANT as _R +from .Constants import CRITICAL_TEMPERATURE as _tc +from .Constants import CRITICAL_PRESSURE as _pc +from .Constants import CRITICAL_DENSITY as _rhoc + +from .Tables import R7_97, SR2_01, SR3_03, SR4_04 class Region1: """ - Section 2.1: IAPWS IF 97 Calling functions to calculate the properties of water in Region 1 + Section 2.1: IAPWS IF 97 Calling functions to calculate the properties + of water in Region 1 - Release on the IAPWS Industrial formulation 1997 for the Thermodynamic Properties of Water and Steam, September 1997 + Release on the IAPWS Industrial formulation 1997 for the Thermodynamic + Properties of Water and Steam, September 1997 """ - @staticmethod - def v1_pT(p, T): + _logger = logging.getLogger(__name__) + + @classmethod + def v1_pT(cls, p: float, T: float) -> float: """function v1_pT = v1_pT(p, T) 5 Equations for Region 1, Section. 5.1 Basic Equation Equation 7, Table 3, Page 6 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: specific volume in [m³ / kg] """ - I1 = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 4, - 4, - 4, - 5, - 8, - 8, - 21, - 23, - 29, - 30, - 31, - 32, - ] - J1 = [ - -2, - -1, - 0, - 1, - 2, - 3, - 4, - 5, - -9, - -7, - -1, - 0, - 1, - 3, - -3, - 0, - 1, - 3, - 17, - -4, - 0, - 6, - -5, - -2, - 10, - -8, - -11, - -6, - -29, - -31, - -38, - -39, - -40, - -41, - ] - n1 = [ - 0.14632971213167, - -0.84548187169114, - -3.756360367204, - 3.3855169168385, - -0.95791963387872, - 0.15772038513228, - -0.016616417199501, - 8.1214629983568e-04, - 2.8319080123804e-04, - -6.0706301565874e-04, - -0.018990068218419, - -0.032529748770505, - -0.021841717175414, - -5.283835796993e-05, - -4.7184321073267e-04, - -3.0001780793026e-04, - 4.7661393906987e-05, - -4.4141845330846e-06, - -7.2694996297594e-16, - -3.1679644845054e-05, - -2.8270797985312e-06, - -8.5205128120103e-10, - -2.2425281908e-06, - -6.5171222895601e-07, - -1.4341729937924e-13, - -4.0516996860117e-07, - -1.2734301741641e-09, - -1.7424871230634e-10, - -6.8762131295531e-19, - 1.4478307828521e-20, - 2.6335781662795e-23, - -1.1947622640071e-23, - 1.8228094581404e-24, - -9.3537087292458e-26, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ - Pi = p / 16.53 # 16.53 MPa - tau = 1386 / T # 1386 K + Pi = p / 16.53 + tau = 1386 / T + gamma_der_pi = 0 - for i in range(0, 34): - gamma_der_pi = ( - gamma_der_pi - - n1[i] * I1[i] * (7.1 - Pi) ** (I1[i] - 1) * (tau - 1.222) ** J1[i] - ) - return R * T / p * Pi * gamma_der_pi / 1000 + for I, J, n in zip(R7_97.Table2_I, R7_97.Table2_J, R7_97.Table2_n): + gamma_der_pi = gamma_der_pi - n * I * (7.1 - Pi) ** (I - 1) * (tau - 1.222) ** J - @staticmethod - def h1_pT(p, T): + return _R * T / p * Pi * gamma_der_pi / 1000 + + @classmethod + def h1_pT(cls, p: float, T: float) -> float: """ - function h1_pT = h1_pT(p, T) + calculate enthalpy from preasure and temperature in region 1 5 Equations for Region 1, Section. 5.1 Basic Equation Equation 7, Table 3, Page 6 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: enthalpy in [kJ / kg] """ - I1 = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 4, - 4, - 4, - 5, - 8, - 8, - 21, - 23, - 29, - 30, - 31, - 32, - ] - J1 = [ - -2, - -1, - 0, - 1, - 2, - 3, - 4, - 5, - -9, - -7, - -1, - 0, - 1, - 3, - -3, - 0, - 1, - 3, - 17, - -4, - 0, - 6, - -5, - -2, - 10, - -8, - -11, - -6, - -29, - -31, - -38, - -39, - -40, - -41, - ] - n1 = [ - 0.14632971213167, - -0.84548187169114, - -3.756360367204, - 3.3855169168385, - -0.95791963387872, - 0.15772038513228, - -0.016616417199501, - 8.1214629983568e-04, - 2.8319080123804e-04, - -6.0706301565874e-04, - -0.018990068218419, - -0.032529748770505, - -0.021841717175414, - -5.283835796993e-05, - -4.7184321073267e-04, - -3.0001780793026e-04, - 4.7661393906987e-05, - -4.4141845330846e-06, - -7.2694996297594e-16, - -3.1679644845054e-05, - -2.8270797985312e-06, - -8.5205128120103e-10, - -2.2425281908e-06, - -6.5171222895601e-07, - -1.4341729937924e-13, - -4.0516996860117e-07, - -1.2734301741641e-09, - -1.7424871230634e-10, - -6.8762131295531e-19, - 1.4478307828521e-20, - 2.6335781662795e-23, - -1.1947622640071e-23, - 1.8228094581404e-24, - -9.3537087292458e-26, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ Pi = p / 16.53 tau = 1386 / T + gamma_der_tau = 0 - for i in range(0, 34): - gamma_der_tau = gamma_der_tau + ( - n1[i] * (7.1 - Pi) ** I1[i] * J1[i] * (tau - 1.222) ** (J1[i] - 1) - ) - return R * T * tau * gamma_der_tau + for I, J, n in zip(R7_97.Table2_I, R7_97.Table2_J, R7_97.Table2_n): + gamma_der_tau = gamma_der_tau + (n * (7.1 - Pi) ** I * J * (tau - 1.222) ** (J - 1)) - @staticmethod - def u1_pT(p, T): + return _R * T * tau * gamma_der_tau + + @classmethod + def u1_pT(cls, p: float, T: float) -> float: """function u1_pT = u1_pT(p, T) 5 Equations for Region 1, Section. 5.1 Basic Equation Equation 7, Table 3, Page 6 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: specific internal energy in [kJ / kg] """ - I1 = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 4, - 4, - 4, - 5, - 8, - 8, - 21, - 23, - 29, - 30, - 31, - 32, - ] - J1 = [ - -2, - -1, - 0, - 1, - 2, - 3, - 4, - 5, - -9, - -7, - -1, - 0, - 1, - 3, - -3, - 0, - 1, - 3, - 17, - -4, - 0, - 6, - -5, - -2, - 10, - -8, - -11, - -6, - -29, - -31, - -38, - -39, - -40, - -41, - ] - n1 = [ - 0.14632971213167, - -0.84548187169114, - -3.756360367204, - 3.3855169168385, - -0.95791963387872, - 0.15772038513228, - -0.016616417199501, - 8.1214629983568e-04, - 2.8319080123804e-04, - -6.0706301565874e-04, - -0.018990068218419, - -0.032529748770505, - -0.021841717175414, - -5.283835796993e-05, - -4.7184321073267e-04, - -3.0001780793026e-04, - 4.7661393906987e-05, - -4.4141845330846e-06, - -7.2694996297594e-16, - -3.1679644845054e-05, - -2.8270797985312e-06, - -8.5205128120103e-10, - -2.2425281908e-06, - -6.5171222895601e-07, - -1.4341729937924e-13, - -4.0516996860117e-07, - -1.2734301741641e-09, - -1.7424871230634e-10, - -6.8762131295531e-19, - 1.4478307828521e-20, - 2.6335781662795e-23, - -1.1947622640071e-23, - 1.8228094581404e-24, - -9.3537087292458e-26, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ Pi = p / 16.53 tau = 1386 / T + gamma_der_tau = 0 gamma_der_pi = 0 - for i in range(0, 34): - gamma_der_pi = ( - gamma_der_pi - - n1[i] * I1[i] * (7.1 - Pi) ** (I1[i] - 1) * (tau - 1.222) ** J1[i] - ) - gamma_der_tau = gamma_der_tau + ( - n1[i] * (7.1 - Pi) ** I1[i] * J1[i] * (tau - 1.222) ** (J1[i] - 1) - ) - return R * T * (tau * gamma_der_tau - Pi * gamma_der_pi) + for I, J, n in zip(R7_97.Table2_I, R7_97.Table2_J, R7_97.Table2_n): + gamma_der_pi = gamma_der_pi - n * I * (7.1 - Pi) ** (I - 1) * (tau - 1.222) ** J + gamma_der_tau = gamma_der_tau + (n * (7.1 - Pi) ** I * J * (tau - 1.222) ** (J - 1)) - @staticmethod - def s1_pT(p, T): + return _R * T * (tau * gamma_der_tau - Pi * gamma_der_pi) + + @classmethod + def s1_pT(cls, p: float, T: float) -> float: """function s1_pT = s1_pT(p, T) 5 Equations for Region 1, Section. 5.1 Basic Equation Equation 7, Table 3, Page 6 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: specific entropy in [kJ / (kg K)] """ - I1 = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 4, - 4, - 4, - 5, - 8, - 8, - 21, - 23, - 29, - 30, - 31, - 32, - ] - J1 = [ - -2, - -1, - 0, - 1, - 2, - 3, - 4, - 5, - -9, - -7, - -1, - 0, - 1, - 3, - -3, - 0, - 1, - 3, - 17, - -4, - 0, - 6, - -5, - -2, - 10, - -8, - -11, - -6, - -29, - -31, - -38, - -39, - -40, - -41, - ] - n1 = [ - 0.14632971213167, - -0.84548187169114, - -3.756360367204, - 3.3855169168385, - -0.95791963387872, - 0.15772038513228, - -0.016616417199501, - 8.1214629983568e-04, - 2.8319080123804e-04, - -6.0706301565874e-04, - -0.018990068218419, - -0.032529748770505, - -0.021841717175414, - -5.283835796993e-05, - -4.7184321073267e-04, - -3.0001780793026e-04, - 4.7661393906987e-05, - -4.4141845330846e-06, - -7.2694996297594e-16, - -3.1679644845054e-05, - -2.8270797985312e-06, - -8.5205128120103e-10, - -2.2425281908e-06, - -6.5171222895601e-07, - -1.4341729937924e-13, - -4.0516996860117e-07, - -1.2734301741641e-09, - -1.7424871230634e-10, - -6.8762131295531e-19, - 1.4478307828521e-20, - 2.6335781662795e-23, - -1.1947622640071e-23, - 1.8228094581404e-24, - -9.3537087292458e-26, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ Pi = p / 16.53 tau = 1386 / T + gamma = 0 gamma_der_tau = 0 - for i in range(0, 34): - gamma_der_tau = gamma_der_tau + ( - n1[i] * (7.1 - Pi) ** I1[i] * J1[i] * (tau - 1.222) ** (J1[i] - 1) - ) - gamma = gamma + n1[i] * (7.1 - Pi) ** I1[i] * (tau - 1.222) ** J1[i] - return R * tau * gamma_der_tau - R * gamma + for I, J, n in zip(R7_97.Table2_I, R7_97.Table2_J, R7_97.Table2_n): + gamma_der_tau = gamma_der_tau + (n * (7.1 - Pi) ** I * J * (tau - 1.222) ** (J - 1)) + gamma = gamma + n * (7.1 - Pi) ** I * (tau - 1.222) ** J - @staticmethod - def Cp1_pT(p, T): + return _R * tau * gamma_der_tau - _R * gamma + + @classmethod + def Cp1_pT(cls, p: float, T: float) -> float: """function Cp1_pT = Cp1_pT(p, T) 5 Equations for Region 1, Section. 5.1 Basic Equation Equation 7, Table 3, Page 6 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: specific isobaric heat capacity in [kJ / (kg K)] """ - I1 = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 4, - 4, - 4, - 5, - 8, - 8, - 21, - 23, - 29, - 30, - 31, - 32, - ] - J1 = [ - -2, - -1, - 0, - 1, - 2, - 3, - 4, - 5, - -9, - -7, - -1, - 0, - 1, - 3, - -3, - 0, - 1, - 3, - 17, - -4, - 0, - 6, - -5, - -2, - 10, - -8, - -11, - -6, - -29, - -31, - -38, - -39, - -40, - -41, - ] - n1 = [ - 0.14632971213167, - -0.84548187169114, - -3.756360367204, - 3.3855169168385, - -0.95791963387872, - 0.15772038513228, - -0.016616417199501, - 8.1214629983568e-04, - 2.8319080123804e-04, - -6.0706301565874e-04, - -0.018990068218419, - -0.032529748770505, - -0.021841717175414, - -5.283835796993e-05, - -4.7184321073267e-04, - -3.0001780793026e-04, - 4.7661393906987e-05, - -4.4141845330846e-06, - -7.2694996297594e-16, - -3.1679644845054e-05, - -2.8270797985312e-06, - -8.5205128120103e-10, - -2.2425281908e-06, - -6.5171222895601e-07, - -1.4341729937924e-13, - -4.0516996860117e-07, - -1.2734301741641e-09, - -1.7424871230634e-10, - -6.8762131295531e-19, - 1.4478307828521e-20, - 2.6335781662795e-23, - -1.1947622640071e-23, - 1.8228094581404e-24, - -9.3537087292458e-26, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ Pi = p / 16.53 tau = 1386 / T + gamma_der_tautau = 0 - for i in range(0, 34): - gamma_der_tautau = gamma_der_tautau + ( - n1[i] - * (7.1 - Pi) ** I1[i] - * J1[i] - * (J1[i] - 1) - * (tau - 1.222) ** (J1[i] - 2) - ) - return -R * tau**2 * gamma_der_tautau + for I, J, n in zip(R7_97.Table2_I, R7_97.Table2_J, R7_97.Table2_n): + gamma_der_tautau = gamma_der_tautau + (n * (7.1 - Pi) ** I * J * (J - 1) * (tau - 1.222) ** (J - 2)) - @staticmethod - def Cv1_pT(p, T): + return -_R * tau**2 * gamma_der_tautau + + @classmethod + def Cv1_pT(cls, p: float, T: float) -> float: """function Cv1_pT = Cv1_pT(p, T) 5 Equations for Region 1, Section. 5.1 Basic Equation Equation 7, Table 3, Page 6 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: specific isochoric heat capacity in [kJ / (kg K)] """ - I1 = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 4, - 4, - 4, - 5, - 8, - 8, - 21, - 23, - 29, - 30, - 31, - 32, - ] - J1 = [ - -2, - -1, - 0, - 1, - 2, - 3, - 4, - 5, - -9, - -7, - -1, - 0, - 1, - 3, - -3, - 0, - 1, - 3, - 17, - -4, - 0, - 6, - -5, - -2, - 10, - -8, - -11, - -6, - -29, - -31, - -38, - -39, - -40, - -41, - ] - n1 = [ - 0.14632971213167, - -0.84548187169114, - -3.756360367204, - 3.3855169168385, - -0.95791963387872, - 0.15772038513228, - -0.016616417199501, - 8.1214629983568e-04, - 2.8319080123804e-04, - -6.0706301565874e-04, - -0.018990068218419, - -0.032529748770505, - -0.021841717175414, - -5.283835796993e-05, - -4.7184321073267e-04, - -3.0001780793026e-04, - 4.7661393906987e-05, - -4.4141845330846e-06, - -7.2694996297594e-16, - -3.1679644845054e-05, - -2.8270797985312e-06, - -8.5205128120103e-10, - -2.2425281908e-06, - -6.5171222895601e-07, - -1.4341729937924e-13, - -4.0516996860117e-07, - -1.2734301741641e-09, - -1.7424871230634e-10, - -6.8762131295531e-19, - 1.4478307828521e-20, - 2.6335781662795e-23, - -1.1947622640071e-23, - 1.8228094581404e-24, - -9.3537087292458e-26, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ Pi = p / 16.53 tau = 1386 / T + gamma_der_pi = 0 gamma_der_pipi = 0 gamma_der_pitau = 0 gamma_der_tautau = 0 - for i in range(0, 34): - gamma_der_pi = ( - gamma_der_pi - - n1[i] * I1[i] * (7.1 - Pi) ** (I1[i] - 1) * (tau - 1.222) ** J1[i] - ) - gamma_der_pipi = ( - gamma_der_pipi - + n1[i] - * I1[i] - * (I1[i] - 1) - * (7.1 - Pi) ** (I1[i] - 2) - * (tau - 1.222) ** J1[i] - ) - gamma_der_pitau = gamma_der_pitau - n1[i] * I1[i] * (7.1 - Pi) ** ( - I1[i] - 1 - ) * J1[i] * (tau - 1.222) ** (J1[i] - 1) - gamma_der_tautau = gamma_der_tautau + n1[i] * (7.1 - Pi) ** I1[i] * J1[ - i - ] * (J1[i] - 1) * (tau - 1.222) ** (J1[i] - 2) - return R * ( - -(tau**2) * gamma_der_tautau - + (gamma_der_pi - tau * gamma_der_pitau) ** 2 / gamma_der_pipi - ) + for I, J, n in zip(R7_97.Table2_I, R7_97.Table2_J, R7_97.Table2_n): + gamma_der_pi = gamma_der_pi - n * I * (7.1 - Pi) ** (I - 1) * (tau - 1.222) ** J + gamma_der_pipi = gamma_der_pipi + n * I * (I - 1) * (7.1 - Pi) ** (I - 2) * (tau - 1.222) ** J + gamma_der_pitau = gamma_der_pitau - n * I * (7.1 - Pi) ** (I - 1) * J * (tau - 1.222) ** (J - 1) + gamma_der_tautau = gamma_der_tautau + n * (7.1 - Pi) ** I * J * (J - 1) * (tau - 1.222) ** (J - 2) - @staticmethod - def w1_pT(p, T): + return _R * (-(tau**2) * gamma_der_tautau + (gamma_der_pi - tau * gamma_der_pitau) ** 2 / gamma_der_pipi) + + @classmethod + def w1_pT(cls, p: float, T: float) -> float: """function w1_pT = w1_pT(p, T) 5 Equations for Region 1, Section. 5.1 Basic Equation Equation 7, Table 3, Page 6 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: speed of sound in [m / s] """ - I1 = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 4, - 4, - 4, - 5, - 8, - 8, - 21, - 23, - 29, - 30, - 31, - 32, - ] - J1 = [ - -2, - -1, - 0, - 1, - 2, - 3, - 4, - 5, - -9, - -7, - -1, - 0, - 1, - 3, - -3, - 0, - 1, - 3, - 17, - -4, - 0, - 6, - -5, - -2, - 10, - -8, - -11, - -6, - -29, - -31, - -38, - -39, - -40, - -41, - ] - n1 = [ - 0.14632971213167, - -0.84548187169114, - -3.756360367204, - 3.3855169168385, - -0.95791963387872, - 0.15772038513228, - -0.016616417199501, - 8.1214629983568e-04, - 2.8319080123804e-04, - -6.0706301565874e-04, - -0.018990068218419, - -0.032529748770505, - -0.021841717175414, - -5.283835796993e-05, - -4.7184321073267e-04, - -3.0001780793026e-04, - 4.7661393906987e-05, - -4.4141845330846e-06, - -7.2694996297594e-16, - -3.1679644845054e-05, - -2.8270797985312e-06, - -8.5205128120103e-10, - -2.2425281908e-06, - -6.5171222895601e-07, - -1.4341729937924e-13, - -4.0516996860117e-07, - -1.2734301741641e-09, - -1.7424871230634e-10, - -6.8762131295531e-19, - 1.4478307828521e-20, - 2.6335781662795e-23, - -1.1947622640071e-23, - 1.8228094581404e-24, - -9.3537087292458e-26, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ Pi = p / 16.53 tau = 1386 / T + gamma_der_pi = 0 gamma_der_pipi = 0 gamma_der_pitau = 0 gamma_der_tautau = 0 - for i in range(0, 34): - gamma_der_pi = ( - gamma_der_pi - - n1[i] * I1[i] * (7.1 - Pi) ** (I1[i] - 1) * (tau - 1.222) ** J1[i] - ) - gamma_der_pipi = ( - gamma_der_pipi - + n1[i] - * I1[i] - * (I1[i] - 1) - * (7.1 - Pi) ** (I1[i] - 2) - * (tau - 1.222) ** J1[i] - ) - gamma_der_pitau = gamma_der_pitau - n1[i] * I1[i] * (7.1 - Pi) ** ( - I1[i] - 1 - ) * J1[i] * (tau - 1.222) ** (J1[i] - 1) - gamma_der_tautau = gamma_der_tautau + n1[i] * (7.1 - Pi) ** I1[i] * J1[ - i - ] * (J1[i] - 1) * (tau - 1.222) ** (J1[i] - 2) + for I, J, n in zip(R7_97.Table2_I, R7_97.Table2_J, R7_97.Table2_n): + gamma_der_pi = gamma_der_pi - n * I * (7.1 - Pi) ** (I - 1) * (tau - 1.222) ** J + gamma_der_pipi = gamma_der_pipi + n * I * (I - 1) * (7.1 - Pi) ** (I - 2) * (tau - 1.222) ** J + gamma_der_pitau = gamma_der_pitau - n * I * (7.1 - Pi) ** (I - 1) * J * (tau - 1.222) ** (J - 1) + gamma_der_tautau = gamma_der_tautau + n * (7.1 - Pi) ** I * J * (J - 1) * (tau - 1.222) ** (J - 2) + return ( - 1000 - * R - * T - * gamma_der_pi**2 - / ( - (gamma_der_pi - tau * gamma_der_pitau) ** 2 - / (tau**2 * gamma_der_tautau) - - gamma_der_pipi - ) + 1000 * _R * T * gamma_der_pi**2 / ((gamma_der_pi - tau * gamma_der_pitau) ** 2 / (tau**2 * gamma_der_tautau) - gamma_der_pipi) ) ** 0.5 - @staticmethod - def T1_ph(p, h): + @classmethod + def T1_ph(cls, p: float, h: float) -> float: """function T1_ph = T1_ph(p, h) - 5 Equations for Region 1, Section. 5.1 Basic Equation, 5.2.1 The Backward Equation T (p, h) + 5 Equations for Region 1, Section. 5.1 Basic Equation, 5.2.1 The Backward + Equation T (p, h) Equation 11, Table 6, Page 10 + + :param p: preasure in [MPa] + :param h: enthalpy in [kJ / kg] + + :return: temperature in [K] """ - I1 = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5, 6] - J1 = [0, 1, 2, 6, 22, 32, 0, 1, 2, 3, 4, 10, 32, 10, 32, 10, 32, 32, 32, 32] - n1 = [ - -238.72489924521, - 404.21188637945, - 113.49746881718, - -5.8457616048039, - -1.528548241314e-04, - -1.0866707695377e-06, - -13.391744872602, - 43.211039183559, - -54.010067170506, - 30.535892203916, - -6.5964749423638, - 9.3965400878363e-03, - 1.157364750534e-07, - -2.5858641282073e-05, - -4.0644363084799e-09, - 6.6456186191635e-08, - 8.0670734103027e-11, - -9.3477771213947e-13, - 5.8265442020601e-15, - -1.5020185953503e-17, - ] Pi = p / 1 eta = h / 2500 + T = 0 - for i in range(0, 20): - T = T + n1[i] * Pi ** I1[i] * (eta + 1) ** J1[i] + for I, J, n in zip(R7_97.Table6_I, R7_97.Table6_J, R7_97.Table6_n): + T = T + n * Pi**I * (eta + 1) ** J + return T - @staticmethod - def T1_ps(p, s): + @classmethod + def T1_ps(cls, p: float, s: float) -> float: """function T1_ps = T1_ps(p, s) - 5 Equations for Region 1, Section. 5.1 Basic Equation, 5.2.2 The Backward Equation T (p, s) + 5 Equations for Region 1, Section. 5.1 Basic Equation, 5.2.2 The Backward + Equation T (p, s) Equation 13, Table 8, Page 11 + + :param p: preasure in [MPa] + :param s: specific entropy in [kJ / (kg K)] + + :return: temperature in [K] """ - I1 = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 4] - J1 = [0, 1, 2, 3, 11, 31, 0, 1, 2, 3, 12, 31, 0, 1, 2, 9, 31, 10, 32, 32] - n1 = [ - 174.78268058307, - 34.806930892873, - 6.5292584978455, - 0.33039981775489, - -1.9281382923196e-07, - -2.4909197244573e-23, - -0.26107636489332, - 0.22592965981586, - -0.064256463395226, - 7.8876289270526e-03, - 3.5672110607366e-10, - 1.7332496994895e-24, - 5.6608900654837e-04, - -3.2635483139717e-04, - 4.4778286690632e-05, - -5.1322156908507e-10, - -4.2522657042207e-26, - 2.6400441360689e-13, - 7.8124600459723e-29, - -3.0732199903668e-31, - ] Pi = p / 1 Sigma = s / 1 + T = 0 - for i in range(0, 20): - T = T + n1[i] * Pi ** I1[i] * (Sigma + 2) ** J1[i] + for I, J, n in zip(R7_97.Table8_I, R7_97.Table8_J, R7_97.Table8_n): + T = T + n * Pi**I * (Sigma + 2) ** J + return T - @staticmethod - def p1_hs(h, s): + @classmethod + def p1_hs(cls, h: float, s: float) -> float: """function p1_hs = p1_hs(h, s) - Supplementary Release on Backward Equations for Pressure as a Function of Enthalpy and Entropy p(h, s) to the IAPWS Industrial formulation 1997 for the Thermodynamic Properties of Water and Steam + Supplementary Release on Backward Equations for Pressure as a Function of + Enthalpy and Entropy p(h, s) to the IAPWS Industrial formulation 1997 for + the Thermodynamic Properties of Water and Steam 5 Backward Equation p(h, s) for Region 1 Equation 1, Table 2, Page 5 + + :param h: enthalpy in [kJ / kg] + :param s: specific entropy in [kJ / (kg K)] + + :return: preasure in [MPa] """ - I1 = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 4, 4, 5] - J1 = [0, 1, 2, 4, 5, 6, 8, 14, 0, 1, 4, 6, 0, 1, 10, 4, 1, 4, 0] - n1 = [ - -0.691997014660582, - -18.361254878756, - -9.28332409297335, - 65.9639569909906, - -16.2060388912024, - 450.620017338667, - 854.68067822417, - 6075.23214001162, - 32.6487682621856, - -26.9408844582931, - -319.9478483343, - -928.35430704332, - 30.3634537455249, - -65.0540422444146, - -4309.9131651613, - -747.512324096068, - 730.000345529245, - 1142.84032569021, - -436.407041874559, - ] eta = h / 3400 Sigma = s / 7.6 + p = 0 - for i in range(0, 19): - p = p + n1[i] * (eta + 0.05) ** I1[i] * (Sigma + 0.05) ** J1[i] + for I, J, n in zip(SR2_01.Table2_I, SR2_01.Table2_J, SR2_01.Table2_n): + p = p + n * (eta + 0.05) ** I * (Sigma + 0.05) ** J + return p * 100 - @staticmethod - def T1_prho(p, rho): + @classmethod + def T1_prho(cls, p: float, rho: float) -> float: """function T1_prho = T1_prho(p , rho) - Solve by iteration. Observe that for low temperatures this equation has 2 solutions. Solve with half interval method + Solve by iteration. Observe that for low temperatures this equation + has 2 solutions. Solve with half interval method + + :param p: pressure in [MPa] + :param rho: density in [kg / m³] + + :return: temperature in [K] """ - logger = logging.getLogger("pyXSteam") - Low_Bound = 273.15 + Ts = float("NaN") + Low_Bound = FREEZING_TEMPERATURE_H2O High_Bound = Region4.T4_p(p) rhos = -1000 step_counter = 0 @@ -1097,7 +299,7 @@ def T1_prho(p, rho): rhos = 1 / Region1.v1_pT(p, Ts) if last_rhos == rhos: - logger.warning( + cls._logger.warning( "T1_prho stopped iterating after %d steps because values did not converge", step_counter, ) @@ -1112,160 +314,57 @@ def T1_prho(p, rho): class Region2: """ - Section 2.2: IAPWS IF 97 Calling functions to calculate the properties of water in Region 3 + Section 2.2: IAPWS IF 97 Calling functions to calculate the properties + of water in Region 2 """ - @staticmethod - def v2_pT(p, T): + _logger = logging.getLogger(__name__) + + @classmethod + def v2_pT(cls, p: float, T: float) -> float: """function v2_pT = v2_pT(p, T) 6 Equations for Region 2, Section. 6.1 Basic Equation Table 11 and 12, Page 14 and 15 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: specific volume in [m³ / kg] """ - Ir = [ - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 5, - 6, - 6, - 6, - 7, - 7, - 7, - 8, - 8, - 9, - 10, - 10, - 10, - 16, - 16, - 18, - 20, - 20, - 20, - 21, - 22, - 23, - 24, - 24, - 24, - ] - Jr = [ - 0, - 1, - 2, - 3, - 6, - 1, - 2, - 4, - 7, - 36, - 0, - 1, - 3, - 6, - 35, - 1, - 2, - 3, - 7, - 3, - 16, - 35, - 0, - 11, - 25, - 8, - 36, - 13, - 4, - 10, - 14, - 29, - 50, - 57, - 20, - 35, - 48, - 21, - 53, - 39, - 26, - 40, - 58, - ] - nr = [ - -1.7731742473213e-03, - -0.017834862292358, - -0.045996013696365, - -0.057581259083432, - -0.05032527872793, - -3.3032641670203e-05, - -1.8948987516315e-04, - -3.9392777243355e-03, - -0.043797295650573, - -2.6674547914087e-05, - 2.0481737692309e-08, - 4.3870667284435e-07, - -3.227767723857e-05, - -1.5033924542148e-03, - -0.040668253562649, - -7.8847309559367e-10, - 1.2790717852285e-08, - 4.8225372718507e-07, - 2.2922076337661e-06, - -1.6714766451061e-11, - -2.1171472321355e-03, - -23.895741934104, - -5.905956432427e-18, - -1.2621808899101e-06, - -0.038946842435739, - 1.1256211360459e-11, - -8.2311340897998, - 1.9809712802088e-08, - 1.0406965210174e-19, - -1.0234747095929e-13, - -1.0018179379511e-09, - -8.0882908646985e-11, - 0.10693031879409, - -0.33662250574171, - 8.9185845355421e-25, - 3.0629316876232e-13, - -4.2002467698208e-06, - -5.9056029685639e-26, - 3.7826947613457e-06, - -1.2768608934681e-15, - 7.3087610595061e-29, - 5.5414715350778e-17, - -9.436970724121e-07, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ - Pi = p - tau = 540 / T + Pi = p # Eq 1 + tau = 540 / T # Eq 1 + + g0_pi = 1 / Pi # see table 13 + + gr_pi = 0 + for I, J, n in zip(R7_97.Table11_I, R7_97.Table11_J, R7_97.Table11_n): + gr_pi = gr_pi + n * I * Pi ** (I - 1) * (tau - 0.5) ** J # see table 14 + + return _R * T / p * Pi * (g0_pi + gr_pi) / 1000 # see table 12 + + @staticmethod + def v2_pT_meta(p, T): + """ + 6 Equations for Region 2, Section. 6.2 Supplementary Equation for the Metastable-Vapor Region + + Table 16, Page 18 + + specific volume + """ + Pi = p # Eq 1 + tau = 540 / T # Eq 1 + + # table 13 - dimensionless gibbs free energy - gamma 0 pi g0_pi = 1 / Pi + + # table 14 - residual dimensionless gibbs free energy - part r pi gr_pi = 0 - for i in range(0, 43): - gr_pi = gr_pi + nr[i] * Ir[i] * Pi ** (Ir[i] - 1) * (tau - 0.5) ** Jr[i] - return R * T / p * Pi * (g0_pi + gr_pi) / 1000 + for I, J, n in zip(R7_97.Table16_I, R7_97.Table16_J, R7_97.Table16_n): + gr_pi = gr_pi + n * I * Pi ** (I - 1) * (tau - 0.5) ** J + + return _R * T / p * Pi * (g0_pi + gr_pi) / 1000 # see table 12 @staticmethod def h2_pT(p, T): @@ -1274,164 +373,48 @@ def h2_pT(p, T): 6 Equations for Region 2, Section. 6.1 Basic Equation Table 11 and 12, Page 14 and 15 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: enthalpy in [kJ / kg] """ - J0 = [0, 1, -5, -4, -3, -2, -1, 2, 3] - n0 = [ - -9.6927686500217, - 10.086655968018, - -0.005608791128302, - 0.071452738081455, - -0.40710498223928, - 1.4240819171444, - -4.383951131945, - -0.28408632460772, - 0.021268463753307, - ] - Ir = [ - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 5, - 6, - 6, - 6, - 7, - 7, - 7, - 8, - 8, - 9, - 10, - 10, - 10, - 16, - 16, - 18, - 20, - 20, - 20, - 21, - 22, - 23, - 24, - 24, - 24, - ] - Jr = [ - 0, - 1, - 2, - 3, - 6, - 1, - 2, - 4, - 7, - 36, - 0, - 1, - 3, - 6, - 35, - 1, - 2, - 3, - 7, - 3, - 16, - 35, - 0, - 11, - 25, - 8, - 36, - 13, - 4, - 10, - 14, - 29, - 50, - 57, - 20, - 35, - 48, - 21, - 53, - 39, - 26, - 40, - 58, - ] - nr = [ - -1.7731742473213e-03, - -0.017834862292358, - -0.045996013696365, - -0.057581259083432, - -0.05032527872793, - -3.3032641670203e-05, - -1.8948987516315e-04, - -3.9392777243355e-03, - -0.043797295650573, - -2.6674547914087e-05, - 2.0481737692309e-08, - 4.3870667284435e-07, - -3.227767723857e-05, - -1.5033924542148e-03, - -0.040668253562649, - -7.8847309559367e-10, - 1.2790717852285e-08, - 4.8225372718507e-07, - 2.2922076337661e-06, - -1.6714766451061e-11, - -2.1171472321355e-03, - -23.895741934104, - -5.905956432427e-18, - -1.2621808899101e-06, - -0.038946842435739, - 1.1256211360459e-11, - -8.2311340897998, - 1.9809712802088e-08, - 1.0406965210174e-19, - -1.0234747095929e-13, - -1.0018179379511e-09, - -8.0882908646985e-11, - 0.10693031879409, - -0.33662250574171, - 8.9185845355421e-25, - 3.0629316876232e-13, - -4.2002467698208e-06, - -5.9056029685639e-26, - 3.7826947613457e-06, - -1.2768608934681e-15, - 7.3087610595061e-29, - 5.5414715350778e-17, - -9.436970724121e-07, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ Pi = p tau = 540 / T + g0_tau = 0 - for i in range(0, 9): - g0_tau = g0_tau + n0[i] * J0[i] * tau ** (J0[i] - 1) + for J, n in zip(R7_97.Table10_J0, R7_97.Table10_n0_a): + g0_tau = g0_tau + n * J * tau ** (J - 1) + gr_tau = 0 - for i in range(0, 43): - gr_tau = gr_tau + nr[i] * Pi ** Ir[i] * Jr[i] * (tau - 0.5) ** (Jr[i] - 1) - return R * T * tau * (g0_tau + gr_tau) + for I, J, n in zip(R7_97.Table11_I, R7_97.Table11_J, R7_97.Table11_n): + gr_tau = gr_tau + n * Pi**I * J * (tau - 0.5) ** (J - 1) + + return _R * T * tau * (g0_tau + gr_tau) + + @staticmethod + def h2_pT_meta(p, T): + """ + 6 Equations for Region 2, Section. 6.2 Supplementary Equation for the Metastable-Vapor Region + + Table 16, Page 18 + + specific volume + """ + Pi = p # Eq 1 + tau = 540 / T # Eq 1 + + # table 13 - dimensionless gibbs free energy - gamma 0 tau + g0_tau = 0 + for J, n in zip(R7_97.Table10_J0, R7_97.Table10_n0_b): + g0_tau += n * J * tau ** (J - 1) + + # table 14 - residual dimensionless gibbs free energy - part r tau + gr_tau = 0 + for I, J, n in zip(R7_97.Table16_I, R7_97.Table16_J, R7_97.Table16_n): + gr_tau += n * Pi**I * J * (tau - 0.5) ** (J - 1) + + return _R * T * tau * (g0_tau + gr_tau) # h2_pT @staticmethod def u2_pT(p, T): @@ -1440,167 +423,59 @@ def u2_pT(p, T): 6 Equations for Region 2, Section. 6.1 Basic Equation Table 11 and 12, Page 14 and 15 + + :param p: preasure in [MPa] + :param T: temperature in [K] + :return: specific internal energy in [kJ / kg] """ - J0 = [0, 1, -5, -4, -3, -2, -1, 2, 3] - n0 = [ - -9.6927686500217, - 10.086655968018, - -0.005608791128302, - 0.071452738081455, - -0.40710498223928, - 1.4240819171444, - -4.383951131945, - -0.28408632460772, - 0.021268463753307, - ] - Ir = [ - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 5, - 6, - 6, - 6, - 7, - 7, - 7, - 8, - 8, - 9, - 10, - 10, - 10, - 16, - 16, - 18, - 20, - 20, - 20, - 21, - 22, - 23, - 24, - 24, - 24, - ] - Jr = [ - 0, - 1, - 2, - 3, - 6, - 1, - 2, - 4, - 7, - 36, - 0, - 1, - 3, - 6, - 35, - 1, - 2, - 3, - 7, - 3, - 16, - 35, - 0, - 11, - 25, - 8, - 36, - 13, - 4, - 10, - 14, - 29, - 50, - 57, - 20, - 35, - 48, - 21, - 53, - 39, - 26, - 40, - 58, - ] - nr = [ - -1.7731742473213e-03, - -0.017834862292358, - -0.045996013696365, - -0.057581259083432, - -0.05032527872793, - -3.3032641670203e-05, - -1.8948987516315e-04, - -3.9392777243355e-03, - -0.043797295650573, - -2.6674547914087e-05, - 2.0481737692309e-08, - 4.3870667284435e-07, - -3.227767723857e-05, - -1.5033924542148e-03, - -0.040668253562649, - -7.8847309559367e-10, - 1.2790717852285e-08, - 4.8225372718507e-07, - 2.2922076337661e-06, - -1.6714766451061e-11, - -2.1171472321355e-03, - -23.895741934104, - -5.905956432427e-18, - -1.2621808899101e-06, - -0.038946842435739, - 1.1256211360459e-11, - -8.2311340897998, - 1.9809712802088e-08, - 1.0406965210174e-19, - -1.0234747095929e-13, - -1.0018179379511e-09, - -8.0882908646985e-11, - 0.10693031879409, - -0.33662250574171, - 8.9185845355421e-25, - 3.0629316876232e-13, - -4.2002467698208e-06, - -5.9056029685639e-26, - 3.7826947613457e-06, - -1.2768608934681e-15, - 7.3087610595061e-29, - 5.5414715350778e-17, - -9.436970724121e-07, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ Pi = p tau = 540 / T + + g0_pi = 1 / Pi + + g0_tau = 0 + for J, n in zip(R7_97.Table10_J0, R7_97.Table10_n0_a): + g0_tau = g0_tau + n * J * tau ** (J - 1) + + gr_pi = 0 + gr_tau = 0 + for I, J, n in zip(R7_97.Table11_I, R7_97.Table11_J, R7_97.Table11_n): + gr_pi = gr_pi + n * I * Pi ** (I - 1) * (tau - 0.5) ** J + gr_tau = gr_tau + n * Pi**I * J * (tau - 0.5) ** (J - 1) + + return _R * T * (tau * (g0_tau + gr_tau) - Pi * (g0_pi + gr_pi)) + + @staticmethod + def u2_pT_meta(p, T): + """ + 6 Equations for Region 2, Section. 6.2 Supplementary Equation for the Metastable-Vapor Region + + Table 16, Page 18 + + specific volume + """ + Pi = p # Eq 1 + tau = 540 / T # Eq 1 + + # table 13 - dimensionless gibbs free energy - gamma 0 pi g0_pi = 1 / Pi + + # table 13 - dimensionless gibbs free energy - gamma 0 tau g0_tau = 0 - for i in range(0, 9): - g0_tau = g0_tau + n0[i] * J0[i] * tau ** (J0[i] - 1) + for J, n in zip(R7_97.Table10_J0, R7_97.Table10_n0_b): + g0_tau += n * J * tau ** (J - 1) + + # table 14 - residual dimensionless gibbs free energy - part r pi gr_pi = 0 + for I, J, n in zip(R7_97.Table16_I, R7_97.Table16_J, R7_97.Table16_n): + gr_pi = gr_pi + n * I * Pi ** (I - 1) * (tau - 0.5) ** J + + # table 14 - residual dimensionless gibbs free energy - part r tau gr_tau = 0 - for i in range(0, 43): - gr_pi = gr_pi + nr[i] * Ir[i] * Pi ** (Ir[i] - 1) * (tau - 0.5) ** Jr[i] - gr_tau = gr_tau + nr[i] * Pi ** Ir[i] * Jr[i] * (tau - 0.5) ** (Jr[i] - 1) - return R * T * (tau * (g0_tau + gr_tau) - Pi * (g0_pi + gr_pi)) + for I, J, n in zip(R7_97.Table16_I, R7_97.Table16_J, R7_97.Table16_n): + gr_tau += n * Pi**I * J * (tau - 0.5) ** (J - 1) + + return _R * T * (tau * (g0_tau + gr_tau) - Pi * (g0_pi + gr_pi)) # u2_pT @staticmethod def s2_pT(p, T): @@ -1609,168 +484,62 @@ def s2_pT(p, T): 6 Equations for Region 2, Section. 6.1 Basic Equation Table 11 and 12, Page 14 and 15 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: specific entropy in [kJ / (kg K)] """ - J0 = [0, 1, -5, -4, -3, -2, -1, 2, 3] - n0 = [ - -9.6927686500217, - 10.086655968018, - -0.005608791128302, - 0.071452738081455, - -0.40710498223928, - 1.4240819171444, - -4.383951131945, - -0.28408632460772, - 0.021268463753307, - ] - Ir = [ - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 5, - 6, - 6, - 6, - 7, - 7, - 7, - 8, - 8, - 9, - 10, - 10, - 10, - 16, - 16, - 18, - 20, - 20, - 20, - 21, - 22, - 23, - 24, - 24, - 24, - ] - Jr = [ - 0, - 1, - 2, - 3, - 6, - 1, - 2, - 4, - 7, - 36, - 0, - 1, - 3, - 6, - 35, - 1, - 2, - 3, - 7, - 3, - 16, - 35, - 0, - 11, - 25, - 8, - 36, - 13, - 4, - 10, - 14, - 29, - 50, - 57, - 20, - 35, - 48, - 21, - 53, - 39, - 26, - 40, - 58, - ] - nr = [ - -1.7731742473213e-03, - -0.017834862292358, - -0.045996013696365, - -0.057581259083432, - -0.05032527872793, - -3.3032641670203e-05, - -1.8948987516315e-04, - -3.9392777243355e-03, - -0.043797295650573, - -2.6674547914087e-05, - 2.0481737692309e-08, - 4.3870667284435e-07, - -3.227767723857e-05, - -1.5033924542148e-03, - -0.040668253562649, - -7.8847309559367e-10, - 1.2790717852285e-08, - 4.8225372718507e-07, - 2.2922076337661e-06, - -1.6714766451061e-11, - -2.1171472321355e-03, - -23.895741934104, - -5.905956432427e-18, - -1.2621808899101e-06, - -0.038946842435739, - 1.1256211360459e-11, - -8.2311340897998, - 1.9809712802088e-08, - 1.0406965210174e-19, - -1.0234747095929e-13, - -1.0018179379511e-09, - -8.0882908646985e-11, - 0.10693031879409, - -0.33662250574171, - 8.9185845355421e-25, - 3.0629316876232e-13, - -4.2002467698208e-06, - -5.9056029685639e-26, - 3.7826947613457e-06, - -1.2768608934681e-15, - 7.3087610595061e-29, - 5.5414715350778e-17, - -9.436970724121e-07, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ Pi = p tau = 540 / T + + g0 = math.log(Pi) + g0_tau = 0 + for J, n in zip(R7_97.Table10_J0, R7_97.Table10_n0_a): + g0 = g0 + n * tau**J + g0_tau = g0_tau + n * J * tau ** (J - 1) + + gr = 0 + gr_tau = 0 + for I, J, n in zip(R7_97.Table11_I, R7_97.Table11_J, R7_97.Table11_n): + gr = gr + n * Pi**I * (tau - 0.5) ** J + gr_tau = gr_tau + n * Pi**I * J * (tau - 0.5) ** (J - 1) + + return _R * (tau * (g0_tau + gr_tau) - (g0 + gr)) + + @staticmethod + def s2_pT_meta(p, T): + """ + 6 Equations for Region 2, Section. 6.2 Supplementary Equation for the Metastable-Vapor Region + + Table 16, Page 18 + + specific volume + """ + Pi = p # Eq 1 + tau = 540 / T # Eq 1 + + # table 13 - dimensionless gibbs free energy - gamma 0 g0 = math.log(Pi) + for J, n in zip(R7_97.Table10_J0, R7_97.Table10_n0_b): + g0 += n * tau**J + + # table 13 - dimensionless gibbs free energy - gamma 0 tau g0_tau = 0 - for i in range(0, 9): - g0 = g0 + n0[i] * tau ** J0[i] - g0_tau = g0_tau + n0[i] * J0[i] * tau ** (J0[i] - 1) + for J, n in zip(R7_97.Table10_J0, R7_97.Table10_n0_b): + g0_tau += n * J * tau ** (J - 1) + + # table 14 - residual dimensionless gibbs free energy - part r gr = 0 + for I, J, n in zip(R7_97.Table16_I, R7_97.Table16_J, R7_97.Table16_n): + gr += n * Pi**I * (tau - 0.5) ** J + + # table 14 - residual dimensionless gibbs free energy - part r tau gr_tau = 0 - for i in range(0, 43): - gr = gr + nr[i] * Pi ** Ir[i] * (tau - 0.5) ** Jr[i] - gr_tau = gr_tau + nr[i] * Pi ** Ir[i] * Jr[i] * (tau - 0.5) ** (Jr[i] - 1) - return R * (tau * (g0_tau + gr_tau) - (g0 + gr)) + for I, J, n in zip(R7_97.Table16_I, R7_97.Table16_J, R7_97.Table16_n): + gr_tau += n * Pi**I * J * (tau - 0.5) ** (J - 1) + + return _R * (tau * (g0_tau + gr_tau) - (g0 + gr)) # s2_pT @staticmethod def Cp2_pT(p, T): @@ -1779,166 +548,48 @@ def Cp2_pT(p, T): 6 Equations for Region 2, Section. 6.1 Basic Equation Table 11 and 12, Page 14 and 15 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: specific isobaric heat capacity in [kJ / (kg K)] """ - J0 = [0, 1, -5, -4, -3, -2, -1, 2, 3] - n0 = [ - -9.6927686500217, - 10.086655968018, - -0.005608791128302, - 0.071452738081455, - -0.40710498223928, - 1.4240819171444, - -4.383951131945, - -0.28408632460772, - 0.021268463753307, - ] - Ir = [ - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 5, - 6, - 6, - 6, - 7, - 7, - 7, - 8, - 8, - 9, - 10, - 10, - 10, - 16, - 16, - 18, - 20, - 20, - 20, - 21, - 22, - 23, - 24, - 24, - 24, - ] - Jr = [ - 0, - 1, - 2, - 3, - 6, - 1, - 2, - 4, - 7, - 36, - 0, - 1, - 3, - 6, - 35, - 1, - 2, - 3, - 7, - 3, - 16, - 35, - 0, - 11, - 25, - 8, - 36, - 13, - 4, - 10, - 14, - 29, - 50, - 57, - 20, - 35, - 48, - 21, - 53, - 39, - 26, - 40, - 58, - ] - nr = [ - -1.7731742473213e-03, - -0.017834862292358, - -0.045996013696365, - -0.057581259083432, - -0.05032527872793, - -3.3032641670203e-05, - -1.8948987516315e-04, - -3.9392777243355e-03, - -0.043797295650573, - -2.6674547914087e-05, - 2.0481737692309e-08, - 4.3870667284435e-07, - -3.227767723857e-05, - -1.5033924542148e-03, - -0.040668253562649, - -7.8847309559367e-10, - 1.2790717852285e-08, - 4.8225372718507e-07, - 2.2922076337661e-06, - -1.6714766451061e-11, - -2.1171472321355e-03, - -23.895741934104, - -5.905956432427e-18, - -1.2621808899101e-06, - -0.038946842435739, - 1.1256211360459e-11, - -8.2311340897998, - 1.9809712802088e-08, - 1.0406965210174e-19, - -1.0234747095929e-13, - -1.0018179379511e-09, - -8.0882908646985e-11, - 0.10693031879409, - -0.33662250574171, - 8.9185845355421e-25, - 3.0629316876232e-13, - -4.2002467698208e-06, - -5.9056029685639e-26, - 3.7826947613457e-06, - -1.2768608934681e-15, - 7.3087610595061e-29, - 5.5414715350778e-17, - -9.436970724121e-07, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ Pi = p tau = 540 / T + g0_tautau = 0 - for i in range(0, 9): - g0_tautau = g0_tautau + n0[i] * J0[i] * (J0[i] - 1) * tau ** (J0[i] - 2) + for J, n in zip(R7_97.Table10_J0, R7_97.Table10_n0_a): + g0_tautau = g0_tautau + n * J * (J - 1) * tau ** (J - 2) + gr_tautau = 0 - for i in range(0, 43): - gr_tautau = gr_tautau + nr[i] * Pi ** Ir[i] * Jr[i] * (Jr[i] - 1) * ( - tau - 0.5 - ) ** (Jr[i] - 2) - return -R * tau**2 * (g0_tautau + gr_tautau) + for I, J, n in zip(R7_97.Table11_I, R7_97.Table11_J, R7_97.Table11_n): + gr_tautau = gr_tautau + n * Pi**I * J * (J - 1) * (tau - 0.5) ** (J - 2) + + return -_R * tau**2 * (g0_tautau + gr_tautau) + + @staticmethod + def Cp2_pT_meta(p, T): + """ + 6 Equations for Region 2, Section. 6.2 Supplementary Equation for the Metastable-Vapor Region + + Table 16, Page 18 + + specific volume + """ + Pi = p # Eq 1 + tau = 540 / T # Eq 1 + + # table 13 - dimensionless gibbs free energy - gamma 0 tau tau + g0_tautau = 0 + for J, n in zip(R7_97.Table10_J0, R7_97.Table10_n0_b): + g0_tautau += n * J * (J - 1) * tau ** (J - 2) + + # table 14 - residual dimensionless gibbs free energy - part r tau tau + gr_tautau = 0 + for I, J, n in zip(R7_97.Table16_I, R7_97.Table16_J, R7_97.Table16_n): + gr_tautau += n * Pi**I * J * (J - 1) * (tau - 0.5) ** (J - 2) + + return -_R * tau**2 * (g0_tautau + gr_tautau) # Cp2_pT @staticmethod def Cv2_pT(p, T): @@ -1947,717 +598,173 @@ def Cv2_pT(p, T): 6 Equations for Region 2, Section. 6.1 Basic Equation Table 11 and 12, Page 14 and 15 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: specific isochoric heat capacity in [kJ / (kg K)] """ - J0 = [0, 1, -5, -4, -3, -2, -1, 2, 3] - n0 = [ - -9.6927686500217, - 10.086655968018, - -0.005608791128302, - 0.071452738081455, - -0.40710498223928, - 1.4240819171444, - -4.383951131945, - -0.28408632460772, - 0.021268463753307, - ] - Ir = [ - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 5, - 6, - 6, - 6, - 7, - 7, - 7, - 8, - 8, - 9, - 10, - 10, - 10, - 16, - 16, - 18, - 20, - 20, - 20, - 21, - 22, - 23, - 24, - 24, - 24, - ] - Jr = [ - 0, - 1, - 2, - 3, - 6, - 1, - 2, - 4, - 7, - 36, - 0, - 1, - 3, - 6, - 35, - 1, - 2, - 3, - 7, - 3, - 16, - 35, - 0, - 11, - 25, - 8, - 36, - 13, - 4, - 10, - 14, - 29, - 50, - 57, - 20, - 35, - 48, - 21, - 53, - 39, - 26, - 40, - 58, - ] - nr = [ - -1.7731742473213e-03, - -0.017834862292358, - -0.045996013696365, - -0.057581259083432, - -0.05032527872793, - -3.3032641670203e-05, - -1.8948987516315e-04, - -3.9392777243355e-03, - -0.043797295650573, - -2.6674547914087e-05, - 2.0481737692309e-08, - 4.3870667284435e-07, - -3.227767723857e-05, - -1.5033924542148e-03, - -0.040668253562649, - -7.8847309559367e-10, - 1.2790717852285e-08, - 4.8225372718507e-07, - 2.2922076337661e-06, - -1.6714766451061e-11, - -2.1171472321355e-03, - -23.895741934104, - -5.905956432427e-18, - -1.2621808899101e-06, - -0.038946842435739, - 1.1256211360459e-11, - -8.2311340897998, - 1.9809712802088e-08, - 1.0406965210174e-19, - -1.0234747095929e-13, - -1.0018179379511e-09, - -8.0882908646985e-11, - 0.10693031879409, - -0.33662250574171, - 8.9185845355421e-25, - 3.0629316876232e-13, - -4.2002467698208e-06, - -5.9056029685639e-26, - 3.7826947613457e-06, - -1.2768608934681e-15, - 7.3087610595061e-29, - 5.5414715350778e-17, - -9.436970724121e-07, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ Pi = p tau = 540 / T + g0_tautau = 0 - for i in range(0, 9): - g0_tautau = g0_tautau + n0[i] * J0[i] * (J0[i] - 1) * tau ** (J0[i] - 2) + for J, n in zip(R7_97.Table10_J0, R7_97.Table10_n0_a): + g0_tautau = g0_tautau + n * J * (J - 1) * tau ** (J - 2) + gr_pi = 0 gr_pitau = 0 gr_pipi = 0 gr_tautau = 0 - for i in range(0, 43): - gr_pi = gr_pi + nr[i] * Ir[i] * Pi ** (Ir[i] - 1) * (tau - 0.5) ** Jr[i] - gr_pipi = ( - gr_pipi - + nr[i] * Ir[i] * (Ir[i] - 1) * Pi ** (Ir[i] - 2) * (tau - 0.5) ** Jr[i] - ) - gr_pitau = gr_pitau + nr[i] * Ir[i] * Pi ** (Ir[i] - 1) * Jr[i] * ( - tau - 0.5 - ) ** (Jr[i] - 1) - gr_tautau = gr_tautau + nr[i] * Pi ** Ir[i] * Jr[i] * (Jr[i] - 1) * ( - tau - 0.5 - ) ** (Jr[i] - 2) - return R * ( - -(tau**2) * (g0_tautau + gr_tautau) - - (1 + Pi * gr_pi - tau * Pi * gr_pitau) ** 2 / (1 - Pi**2 * gr_pipi) - ) + for I, J, n in zip(R7_97.Table11_I, R7_97.Table11_J, R7_97.Table11_n): + gr_pi = gr_pi + n * I * Pi ** (I - 1) * (tau - 0.5) ** J + gr_pipi = gr_pipi + n * I * (I - 1) * Pi ** (I - 2) * (tau - 0.5) ** J + gr_pitau = gr_pitau + n * I * Pi ** (I - 1) * J * (tau - 0.5) ** (J - 1) + gr_tautau = gr_tautau + n * Pi**I * J * (J - 1) * (tau - 0.5) ** (J - 2) - @staticmethod - def w2_pT(p, T): + return _R * (-(tau**2) * (g0_tautau + gr_tautau) - (1 + Pi * gr_pi - tau * Pi * gr_pitau) ** 2 / (1 - Pi**2 * gr_pipi)) + + @classmethod + def w2_pT(cls, p: float, T: float) -> float: """function w2_pT = w2_pT(p, T) 6 Equations for Region 2, Section. 6.1 Basic Equation Table 11 and 12, Page 14 and 15 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: speed of sound in [m / s] """ - J0 = [0, 1, -5, -4, -3, -2, -1, 2, 3] - n0 = [ - -9.6927686500217, - 10.086655968018, - -0.005608791128302, - 0.071452738081455, - -0.40710498223928, - 1.4240819171444, - -4.383951131945, - -0.28408632460772, - 0.021268463753307, - ] - Ir = [ - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 5, - 6, - 6, - 6, - 7, - 7, - 7, - 8, - 8, - 9, - 10, - 10, - 10, - 16, - 16, - 18, - 20, - 20, - 20, - 21, - 22, - 23, - 24, - 24, - 24, - ] - Jr = [ - 0, - 1, - 2, - 3, - 6, - 1, - 2, - 4, - 7, - 36, - 0, - 1, - 3, - 6, - 35, - 1, - 2, - 3, - 7, - 3, - 16, - 35, - 0, - 11, - 25, - 8, - 36, - 13, - 4, - 10, - 14, - 29, - 50, - 57, - 20, - 35, - 48, - 21, - 53, - 39, - 26, - 40, - 58, - ] - nr = [ - -1.7731742473213e-03, - -0.017834862292358, - -0.045996013696365, - -0.057581259083432, - -0.05032527872793, - -3.3032641670203e-05, - -1.8948987516315e-04, - -3.9392777243355e-03, - -0.043797295650573, - -2.6674547914087e-05, - 2.0481737692309e-08, - 4.3870667284435e-07, - -3.227767723857e-05, - -1.5033924542148e-03, - -0.040668253562649, - -7.8847309559367e-10, - 1.2790717852285e-08, - 4.8225372718507e-07, - 2.2922076337661e-06, - -1.6714766451061e-11, - -2.1171472321355e-03, - -23.895741934104, - -5.905956432427e-18, - -1.2621808899101e-06, - -0.038946842435739, - 1.1256211360459e-11, - -8.2311340897998, - 1.9809712802088e-08, - 1.0406965210174e-19, - -1.0234747095929e-13, - -1.0018179379511e-09, - -8.0882908646985e-11, - 0.10693031879409, - -0.33662250574171, - 8.9185845355421e-25, - 3.0629316876232e-13, - -4.2002467698208e-06, - -5.9056029685639e-26, - 3.7826947613457e-06, - -1.2768608934681e-15, - 7.3087610595061e-29, - 5.5414715350778e-17, - -9.436970724121e-07, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ Pi = p tau = 540 / T + g0_tautau = 0 - for i in range(0, 9): - g0_tautau = g0_tautau + n0[i] * J0[i] * (J0[i] - 1) * tau ** (J0[i] - 2) + for J, n in zip(R7_97.Table10_J0, R7_97.Table10_n0_a): + g0_tautau = g0_tautau + n * J * (J - 1) * tau ** (J - 2) + gr_pi = 0 gr_pitau = 0 gr_pipi = 0 gr_tautau = 0 - for i in range(0, 43): - gr_pi = gr_pi + nr[i] * Ir[i] * Pi ** (Ir[i] - 1) * (tau - 0.5) ** Jr[i] - gr_pipi = ( - gr_pipi - + nr[i] * Ir[i] * (Ir[i] - 1) * Pi ** (Ir[i] - 2) * (tau - 0.5) ** Jr[i] - ) - gr_pitau = gr_pitau + nr[i] * Ir[i] * Pi ** (Ir[i] - 1) * Jr[i] * ( - tau - 0.5 - ) ** (Jr[i] - 1) - gr_tautau = gr_tautau + nr[i] * Pi ** Ir[i] * Jr[i] * (Jr[i] - 1) * ( - tau - 0.5 - ) ** (Jr[i] - 2) + for I, J, n in zip(R7_97.Table11_I, R7_97.Table11_J, R7_97.Table11_n): + gr_pi = gr_pi + n * I * Pi ** (I - 1) * (tau - 0.5) ** J + gr_pipi = gr_pipi + n * I * (I - 1) * Pi ** (I - 2) * (tau - 0.5) ** J + gr_pitau = gr_pitau + n * I * Pi ** (I - 1) * J * (tau - 0.5) ** (J - 1) + gr_tautau = gr_tautau + n * Pi**I * J * (J - 1) * (tau - 0.5) ** (J - 2) + return ( 1000 - * R + * _R * T * (1 + 2 * Pi * gr_pi + Pi**2 * gr_pi**2) - / ( - (1 - Pi**2 * gr_pipi) - + (1 + Pi * gr_pi - tau * Pi * gr_pitau) ** 2 - / (tau**2 * (g0_tautau + gr_tautau)) - ) + / ((1 - Pi**2 * gr_pipi) + (1 + Pi * gr_pi - tau * Pi * gr_pitau) ** 2 / (tau**2 * (g0_tautau + gr_tautau))) ) ** 0.5 + @staticmethod + def w2_pT_meta(p, T): + """ + 6 Equations for Region 2, Section. 6.2 Supplementary Equation for the Metastable-Vapor Region + + Table 16, Page 18 + + specific volume + """ + Pi = p # Eq 1 + tau = 540 / T # Eq 1 + + # table 13 - dimensionless gibbs free energy - gamma 0 tau tau + g0_tautau = 0 + for J, n in zip(R7_97.Table10_J0, R7_97.Table10_n0_b): + g0_tautau += n * J * (J - 1) * tau ** (J - 2) + + # table 14 - residual dimensionless gibbs free energy - part r pi + gr_pi = 0 + for I, J, n in zip(R7_97.Table16_I, R7_97.Table16_J, R7_97.Table16_n): + gr_pi = gr_pi + n * I * Pi ** (I - 1) * (tau - 0.5) ** J + + # table 14 - residual dimensionless gibbs free energy - part r pi pi + gr_pipi = 0 + for I, J, n in zip(R7_97.Table16_I, R7_97.Table16_J, R7_97.Table16_n): + gr_pipi += n * I * (I - 1) * Pi ** (I - 2) * (tau - 0.5) ** J + if isinstance(gr_pipi, complex): + if gr_pipi.imag != 0: + raise Exception() + gr_pipi = gr_pipi.real + + # table 14 - residual dimensionless gibbs free energy - part r tau tau + gr_tautau = 0 + for I, J, n in zip(R7_97.Table16_I, R7_97.Table16_J, R7_97.Table16_n): + gr_tautau += n * Pi**I * J * (J - 1) * (tau - 0.5) ** (J - 2) + + # table 14 - residual dimensionless gibbs free energy - part r pi tau + gr_pitau = 0 + for I, J, n in zip(R7_97.Table16_I, R7_97.Table16_J, R7_97.Table16_n): + gr_pitau += n * I * Pi ** (I - 1) * J * (tau - 0.5) ** (J - 1) + + part_1 = 1 + 2 * Pi * gr_pi + Pi**2 * gr_pi**2 + part_2_a = 1 - Pi**2 * gr_pipi + part_2_b = (1 + Pi * gr_pi - tau * Pi * gr_pitau) ** 2 + part_2_c = tau**2 * (g0_tautau + gr_tautau) + + return math.sqrt(1000 * _R * T * part_1 / (part_2_a + part_2_b / part_2_c)) + @staticmethod def T2_ph(p, h): """function T2_ph = T2_ph(p, h) - 6 Equations for Region 2, 6.3.1 The Backward Equations T(p, h) for Subregions 2a, 2b, and 2c + 6 Equations for Region 2, 6.3.1 The Backward Equations T(p, h) for + Subregions 2a, 2b, and 2c + + :param p: preasure in [MPa] + :param h: enthalpy in [kJ / kg] + + :return: temperature in [K] """ if p < 4: sub_reg = 1 else: - if p < ( - 905.84278514723 - 0.67955786399241 * h + 1.2809002730136e-04 * h**2 - ): + if p < pB2bc_h(h): # Ep20 sub_reg = 2 else: sub_reg = 3 if sub_reg == 1: - Ji = [ - 0, - 1, - 2, - 3, - 7, - 20, - 0, - 1, - 2, - 3, - 7, - 9, - 11, - 18, - 44, - 0, - 2, - 7, - 36, - 38, - 40, - 42, - 44, - 24, - 44, - 12, - 32, - 44, - 32, - 36, - 42, - 34, - 44, - 28, - ] - Ii = [ - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 4, - 4, - 4, - 5, - 5, - 5, - 6, - 6, - 7, - ] - ni = [ - 1089.8952318288, - 849.51654495535, - -107.81748091826, - 33.153654801263, - -7.4232016790248, - 11.765048724356, - 1.844574935579, - -4.1792700549624, - 6.2478196935812, - -17.344563108114, - -200.58176862096, - 271.96065473796, - -455.11318285818, - 3091.9688604755, - 252266.40357872, - -6.1707422868339e-03, - -0.31078046629583, - 11.670873077107, - 128127984.04046, - -985549096.23276, - 2822454697.3002, - -3594897141.0703, - 1722734991.3197, - -13551.334240775, - 12848734.66465, - 1.3865724283226, - 235988.32556514, - -13105236.545054, - 7399.9835474766, - -551966.9703006, - 3715408.5996233, - 19127.72923966, - -415351.64835634, - -62.459855192507, - ] Ts = 0 hs = h / 2000 - for i in range(0, 34): - Ts = Ts + ni[i] * p ** (Ii[i]) * (hs - 2.1) ** Ji[i] + for I, J, n in zip(R7_97.Table20_I, R7_97.Table20_J, R7_97.Table20_n): + Ts = Ts + n * p**I * (hs - 2.1) ** J elif sub_reg == 2: # Subregion B # Table 21, Eq 23, page 23 - Ji = [ - 0, - 1, - 2, - 12, - 18, - 24, - 28, - 40, - 0, - 2, - 6, - 12, - 18, - 24, - 28, - 40, - 2, - 8, - 18, - 40, - 1, - 2, - 12, - 24, - 2, - 12, - 18, - 24, - 28, - 40, - 18, - 24, - 40, - 28, - 2, - 28, - 1, - 40, - ] - Ii = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 4, - 4, - 4, - 5, - 5, - 5, - 6, - 7, - 7, - 9, - 9, - ] - ni = [ - 1489.5041079516, - 743.07798314034, - -97.708318797837, - 2.4742464705674, - -0.63281320016026, - 1.1385952129658, - -0.47811863648625, - 8.5208123431544e-03, - 0.93747147377932, - 3.3593118604916, - 3.3809355601454, - 0.16844539671904, - 0.73875745236695, - -0.47128737436186, - 0.15020273139707, - -0.002176411421975, - -0.021810755324761, - -0.10829784403677, - -0.046333324635812, - 7.1280351959551e-05, - 1.1032831789999e-04, - 1.8955248387902e-04, - 3.0891541160537e-03, - 1.3555504554949e-03, - 2.8640237477456e-07, - -1.0779857357512e-05, - -7.6462712454814e-05, - 1.4052392818316e-05, - -3.1083814331434e-05, - -1.0302738212103e-06, - 2.821728163504e-07, - 1.2704902271945e-06, - 7.3803353468292e-08, - -1.1030139238909e-08, - -8.1456365207833e-14, - -2.5180545682962e-11, - -1.7565233969407e-18, - 8.6934156344163e-15, - ] Ts = 0 hs = h / 2000 + # TODO check list range! # for i = 1 : 38 - for i in range(0, 38): - Ts = Ts + ni[i] * (p - 2) ** (Ii[i]) * (hs - 2.6) ** Ji[i] + for I, J, n in zip(R7_97.Table21_I, R7_97.Table21_J, R7_97.Table21_n): + # for i in range(0, 38): + Ts = Ts + n * (p - 2) ** I * (hs - 2.6) ** J else: # Subregion C # Table 22, Eq 24, page 24 - Ji = [ - 0, - 4, - 0, - 2, - 0, - 2, - 0, - 1, - 0, - 2, - 0, - 1, - 4, - 8, - 4, - 0, - 1, - 4, - 10, - 12, - 16, - 20, - 22, - ] - Ii = [ - -7, - -7, - -6, - -6, - -5, - -5, - -2, - -2, - -1, - -1, - 0, - 0, - 1, - 1, - 2, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - ] - ni = [ - -3236839855524.2, - 7326335090218.1, - 358250899454.47, - -583401318515.9, - -10783068217.47, - 20825544563.171, - 610747.83564516, - 859777.2253558, - -25745.72360417, - 31081.088422714, - 1208.2315865936, - 482.19755109255, - 3.7966001272486, - -10.842984880077, - -0.04536417267666, - 1.4559115658698e-13, - 1.126159740723e-12, - -1.7804982240686e-11, - 1.2324579690832e-07, - -1.1606921130984e-06, - 2.7846367088554e-05, - -5.9270038474176e-04, - 1.2918582991878e-03, - ] Ts = 0 hs = h / 2000 - for i in range(0, 23): - Ts = Ts + ni[i] * (p + 25) ** (Ii[i]) * (hs - 1.8) ** Ji[i] + for I, J, n in zip(R7_97.Table22_I, R7_97.Table22_J, R7_97.Table22_n): + Ts = Ts + n * (p + 25) ** I * (hs - 1.8) ** J return Ts - @staticmethod - def T2_ps(p, s): + @classmethod + def T2_ps(cls, p: float, s: float) -> float: """function T2_ps = T2_ps(p, s) - 6 Equations for Region 2,6.3.2 The Backward Equations T( p, s ) for Subregions 2a, 2b, and 2c + 6 Equations for Region 2,6.3.2 The Backward Equations T( p, s ) for + Subregions 2a, 2b, and 2c Page 26 + + :param p: preasure in [MPa] + :param s: specific entropy in [kJ / (kg K)] + + :return: temperature in [K] """ if p < 4: sub_reg = 1 @@ -2669,764 +776,107 @@ def T2_ps(p, s): if sub_reg == 1: # Subregion A # Table 25, Eq 25, page 26 - Ii = [ - -1.5, - -1.5, - -1.5, - -1.5, - -1.5, - -1.5, - -1.25, - -1.25, - -1.25, - -1, - -1, - -1, - -1, - -1, - -1, - -0.75, - -0.75, - -0.5, - -0.5, - -0.5, - -0.5, - -0.25, - -0.25, - -0.25, - -0.25, - 0.25, - 0.25, - 0.25, - 0.25, - 0.5, - 0.5, - 0.5, - 0.5, - 0.5, - 0.5, - 0.5, - 0.75, - 0.75, - 0.75, - 0.75, - 1, - 1, - 1.25, - 1.25, - 1.5, - 1.5, - ] - Ji = [ - -24, - -23, - -19, - -13, - -11, - -10, - -19, - -15, - -6, - -26, - -21, - -17, - -16, - -9, - -8, - -15, - -14, - -26, - -13, - -9, - -7, - -27, - -25, - -11, - -6, - 1, - 4, - 8, - 11, - 0, - 1, - 5, - 6, - 10, - 14, - 16, - 0, - 4, - 9, - 17, - 7, - 18, - 3, - 15, - 5, - 18, - ] - ni = [ - -392359.83861984, - 515265.7382727, - 40482.443161048, - -321.93790923902, - 96.961424218694, - -22.867846371773, - -449429.14124357, - -5011.8336020166, - 0.35684463560015, - 44235.33584819, - -13673.388811708, - 421632.60207864, - 22516.925837475, - 474.42144865646, - -149.31130797647, - -197811.26320452, - -23554.39947076, - -19070.616302076, - 55375.669883164, - 3829.3691437363, - -603.91860580567, - 1936.3102620331, - 4266.064369861, - -5978.0638872718, - -704.01463926862, - 338.36784107553, - 20.862786635187, - 0.033834172656196, - -4.3124428414893e-05, - 166.53791356412, - -139.86292055898, - -0.78849547999872, - 0.072132411753872, - -5.9754839398283e-03, - -1.2141358953904e-05, - 2.3227096733871e-07, - -10.538463566194, - 2.0718925496502, - -0.072193155260427, - 2.074988708112e-07, - -0.018340657911379, - 2.9036272348696e-07, - 0.21037527893619, - 2.5681239729999e-04, - -0.012799002933781, - -8.2198102652018e-06, - ] Pi = p Sigma = s / 2 teta = 0 + # TODO check list range! # for i = 1 : 46 - for i in range(0, 46): - teta = teta + ni[i] * Pi ** Ii[i] * (Sigma - 2) ** Ji[i] + for I, J, n in zip(R7_97.Table25_I, R7_97.Table25_J, R7_97.Table25_n): + # for i in range(0, 46): + teta = teta + n * Pi**I * (Sigma - 2) ** J elif sub_reg == 2: # Subregion B # Table 26, Eq 26, page 27 - Ii = [ - -6, - -6, - -5, - -5, - -4, - -4, - -4, - -3, - -3, - -3, - -3, - -2, - -2, - -2, - -2, - -1, - -1, - -1, - -1, - -1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 3, - 3, - 3, - 4, - 4, - 5, - 5, - 5, - ] - Ji = [ - 0, - 11, - 0, - 11, - 0, - 1, - 11, - 0, - 1, - 11, - 12, - 0, - 1, - 6, - 10, - 0, - 1, - 5, - 8, - 9, - 0, - 1, - 2, - 4, - 5, - 6, - 9, - 0, - 1, - 2, - 3, - 7, - 8, - 0, - 1, - 5, - 0, - 1, - 3, - 0, - 1, - 0, - 1, - 2, - ] - ni = [ - 316876.65083497, - 20.864175881858, - -398593.99803599, - -21.816058518877, - 223697.85194242, - -2784.1703445817, - 9.920743607148, - -75197.512299157, - 2970.8605951158, - -3.4406878548526, - 0.38815564249115, - 17511.29508575, - -1423.7112854449, - 1.0943803364167, - 0.89971619308495, - -3375.9740098958, - 471.62885818355, - -1.9188241993679, - 0.41078580492196, - -0.33465378172097, - 1387.0034777505, - -406.63326195838, - 41.72734715961, - 2.1932549434532, - -1.0320050009077, - 0.35882943516703, - 5.2511453726066e-03, - 12.838916450705, - -2.8642437219381, - 0.56912683664855, - -0.099962954584931, - -3.2632037778459e-03, - 2.3320922576723e-04, - -0.1533480985745, - 0.029072288239902, - 3.7534702741167e-04, - 1.7296691702411e-03, - -3.8556050844504e-04, - -3.5017712292608e-05, - -1.4566393631492e-05, - 5.6420857267269e-06, - 4.1286150074605e-08, - -2.0684671118824e-08, - 1.6409393674725e-09, - ] Pi = p Sigma = s / 0.7853 teta = 0 - for i in range(0, 44): - teta = teta + ni[i] * Pi ** Ii[i] * (10 - Sigma) ** Ji[i] + for I, J, n in zip(R7_97.Table26_I, R7_97.Table26_J, R7_97.Table26_n): + # for i in range(0, 44): + teta = teta + n * Pi**I * (10 - Sigma) ** J else: # Subregion C # Table 27, Eq 27, page 28 - Ii = [ - -2, - -2, - -1, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 3, - 3, - 3, - 4, - 4, - 4, - 5, - 5, - 5, - 6, - 6, - 7, - 7, - 7, - 7, - 7, - ] - Ji = [ - 0, - 1, - 0, - 0, - 1, - 2, - 3, - 0, - 1, - 3, - 4, - 0, - 1, - 2, - 0, - 1, - 5, - 0, - 1, - 4, - 0, - 1, - 2, - 0, - 1, - 0, - 1, - 3, - 4, - 5, - ] - ni = [ - 909.68501005365, - 2404.566708842, - -591.6232638713, - 541.45404128074, - -270.98308411192, - 979.76525097926, - -469.66772959435, - 14.399274604723, - -19.104204230429, - 5.3299167111971, - -21.252975375934, - -0.3114733441376, - 0.60334840894623, - -0.042764839702509, - 5.8185597255259e-03, - -0.014597008284753, - 5.6631175631027e-03, - -7.6155864584577e-05, - 2.2440342919332e-04, - -1.2561095013413e-05, - 6.3323132660934e-07, - -2.0541989675375e-06, - 3.6405370390082e-08, - -2.9759897789215e-09, - 1.0136618529763e-08, - 5.9925719692351e-12, - -2.0677870105164e-11, - -2.0874278181886e-11, - 1.0162166825089e-10, - -1.6429828281347e-10, - ] Pi = p Sigma = s / 2.9251 teta = 0 - for i in range(0, 30): - teta = teta + ni[i] * Pi ** Ii[i] * (2 - Sigma) ** Ji[i] + for I, J, n in zip(R7_97.Table27_I, R7_97.Table27_J, R7_97.Table27_n): + # for i in range(0, 30): + teta = teta + n * Pi**I * (2 - Sigma) ** J return teta - @staticmethod - def p2_hs(h, s): + @classmethod + def p2_hs(cls, h: float, s: float) -> float: """function p2_hs = p2_hs(h, s) - Supplementary Release on Backward Equations for Pressure as a function of Enthalpy and Entropy p(h,s) to the IAPWS Industrial formulation 1997 for the Thermodynamic Properties of Water and Steam + Supplementary Release on Backward Equations for Pressure as a function + of Enthalpy and Entropy p(h,s) to the IAPWS Industrial formulation 1997 + for the Thermodynamic Properties of Water and Steam Chapter 6: Backward Equations p(h,s) for Region 2 + + :param h: enthalpy in [kJ / kg] + :param s: specific entropy in [kJ / (kg K)] + + :return: preasure in [MPa] """ - if h < ( - -3498.98083432139 - + 2575.60716905876 * s - - 421.073558227969 * s**2 - + 27.6349063799944 * s**3 - ): + if h < hB2bc_s(s): sub_reg = 1 else: if s < 5.85: sub_reg = 3 else: sub_reg = 2 + if sub_reg == 1: # Subregion A # Table 6, Eq 3, page 8 - Ii = [ - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 4, - 5, - 5, - 6, - 7, - ] - Ji = [ - 1, - 3, - 6, - 16, - 20, - 22, - 0, - 1, - 2, - 3, - 5, - 6, - 10, - 16, - 20, - 22, - 3, - 16, - 20, - 0, - 2, - 3, - 6, - 16, - 16, - 3, - 16, - 3, - 1, - ] - ni = [ - -1.82575361923032e-02, - -0.125229548799536, - 0.592290437320145, - 6.04769706185122, - 238.624965444474, - -298.639090222922, - 0.051225081304075, - -0.437266515606486, - 0.413336902999504, - -5.16468254574773, - -5.57014838445711, - 12.8555037824478, - 11.414410895329, - -119.504225652714, - -2847.7798596156, - 4317.57846408006, - 1.1289404080265, - 1974.09186206319, - 1516.12444706087, - 1.41324451421235e-02, - 0.585501282219601, - -2.97258075863012, - 5.94567314847319, - -6236.56565798905, - 9659.86235133332, - 6.81500934948134, - -6332.07286824489, - -5.5891922446576, - 4.00645798472063e-02, - ] eta = h / 4200 Sigma = s / 12 + Pi = 0 - for i in range(0, 29): - Pi = Pi + ni[i] * (eta - 0.5) ** Ii[i] * (Sigma - 1.2) ** Ji[i] + for I, J, n in zip(SR2_01.Table6_I, SR2_01.Table6_J, SR2_01.Table6_n): + Pi = Pi + n * (eta - 0.5) ** I * (Sigma - 1.2) ** J + p2_hs = Pi**4 * 4 elif sub_reg == 2: # Subregion B # Table 7, Eq 4, page 9 - Ii = [ - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 4, - 4, - 5, - 5, - 6, - 6, - 6, - 7, - 7, - 8, - 8, - 8, - 8, - 12, - 14, - ] - Ji = [ - 0, - 1, - 2, - 4, - 8, - 0, - 1, - 2, - 3, - 5, - 12, - 1, - 6, - 18, - 0, - 1, - 7, - 12, - 1, - 16, - 1, - 12, - 1, - 8, - 18, - 1, - 16, - 1, - 3, - 14, - 18, - 10, - 16, - ] - ni = [ - 8.01496989929495e-02, - -0.543862807146111, - 0.337455597421283, - 8.9055545115745, - 313.840736431485, - 0.797367065977789, - -1.2161697355624, - 8.72803386937477, - -16.9769781757602, - -186.552827328416, - 95115.9274344237, - -18.9168510120494, - -4334.0703719484, - 543212633.012715, - 0.144793408386013, - 128.024559637516, - -67230.9534071268, - 33697238.0095287, - -586.63419676272, - -22140322476.9889, - 1716.06668708389, - -570817595.806302, - -3121.09693178482, - -2078413.8463301, - 3056059461577.86, - 3221.57004314333, - 326810259797.295, - -1441.04158934487, - 410.694867802691, - 109077066873.024, - -24796465425889.3, - 1888019068.65134, - -123651009018773, - ] eta = h / 4100 Sigma = s / 7.9 + Pi = 0 - for i in range(0, 33): - Pi = Pi + ni[i] * (eta - 0.6) ** Ii[i] * (Sigma - 1.01) ** Ji[i] + for I, J, n in zip(SR2_01.Table7_I, SR2_01.Table7_J, SR2_01.Table7_n): + Pi = Pi + n * (eta - 0.6) ** I * (Sigma - 1.01) ** J + p2_hs = Pi**4 * 100 else: # Subregion C # Table 8, Eq 5, page 10 - Ii = [ - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 4, - 5, - 5, - 5, - 5, - 6, - 6, - 10, - 12, - 16, - ] - Ji = [ - 0, - 1, - 2, - 3, - 4, - 8, - 0, - 2, - 5, - 8, - 14, - 2, - 3, - 7, - 10, - 18, - 0, - 5, - 8, - 16, - 18, - 18, - 1, - 4, - 6, - 14, - 8, - 18, - 7, - 7, - 10, - ] - ni = [ - 0.112225607199012, - -3.39005953606712, - -32.0503911730094, - -197.5973051049, - -407.693861553446, - 13294.3775222331, - 1.70846839774007, - 37.3694198142245, - 3581.44365815434, - 423014.446424664, - -751071025.760063, - 52.3446127607898, - -228.351290812417, - -960652.417056937, - -80705929.2526074, - 1626980172256.69, - 0.772465073604171, - 46392.9973837746, - -13731788.5134128, - 1704703926305.12, - -25110462818730.8, - 31774883083552, - 53.8685623675312, - -55308.9094625169, - -1028615.22421405, - 2042494187562.34, - 273918446.626977, - -2.63963146312685e15, - -1078908541.08088, - -29649262098.0124, - -1.11754907323424e15, - ] eta = h / 3500 Sigma = s / 5.9 + Pi = 0 - for i in range(0, 31): - Pi = Pi + ni[i] * (eta - 0.7) ** Ii[i] * (Sigma - 1.1) ** Ji[i] + for I, J, n in zip(SR2_01.Table8_I, SR2_01.Table8_J, SR2_01.Table8_n): + Pi = Pi + n * (eta - 0.7) ** I * (Sigma - 1.1) ** J + p2_hs = Pi**4 * 100 return p2_hs - @staticmethod - def T2_prho(p, rho): + @classmethod + def T2_prho(cls, p: float, rho: float) -> float: """function T2_prho=T2_prho(p,rho) Solve by iteration. Observe that of low temperatures this equation has 2 solutions. Solve with half interval method + + :param p: preasure in [MPa] + :param rho: density in [kg / m³] + + :return: temperature in [K] """ - logger = logging.getLogger("pyXSteam") + Ts = float("NaN") if p < 16.5292: Low_Bound = Region4.T4_p(p) else: - Low_Bound = RegionBorders.B23T_p(p) + Low_Bound = TB23_p(p) High_Bound = 1073.15 rhos = -1000 step_counter = 0 @@ -3438,7 +888,7 @@ def T2_prho(p, rho): rhos = 1 / Region2.v2_pT(p, Ts) if last_rhos == rhos: - logger.warning( + cls._logger.warning( "T2_prho stopped iterating after %d steps because values did not converge", step_counter, ) @@ -3453,2258 +903,426 @@ def T2_prho(p, rho): class Region3: """ - Section 2.3: IAPWS IF 97 Calling functions to calculate the properties of water in Region 3 + Section 2.3: IAPWS IF 97 Calling functions to calculate the properties + of water in Region 3 """ - @staticmethod - def p3_rhoT(rho, T): + _logger = logging.getLogger(__name__) + + @classmethod + def p3_rhoT(cls, rho: float, T: float) -> float: """function p3_rhoT = p3_rhoT(rho, T) 7 Basic Equation for Region 3, Section. 6.1 Basic Equation Table 30 and 31, Page 30 and 31 + + :param rho: density in [kg / m³] + :param T: temperature in [K] + + :return: preasure in [MPa] """ - Ii = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 4, - 5, - 5, - 5, - 6, - 6, - 6, - 7, - 8, - 9, - 9, - 10, - 10, - 11, - ] - Ji = [ - 0, - 0, - 1, - 2, - 7, - 10, - 12, - 23, - 2, - 6, - 15, - 17, - 0, - 2, - 6, - 7, - 22, - 26, - 0, - 2, - 4, - 16, - 26, - 0, - 2, - 4, - 26, - 1, - 3, - 26, - 0, - 2, - 26, - 2, - 26, - 2, - 26, - 0, - 1, - 26, - ] - ni = [ - 1.0658070028513, - -15.732845290239, - 20.944396974307, - -7.6867707878716, - 2.6185947787954, - -2.808078114862, - 1.2053369696517, - -8.4566812812502e-03, - -1.2654315477714, - -1.1524407806681, - 0.88521043984318, - -0.64207765181607, - 0.38493460186671, - -0.85214708824206, - 4.8972281541877, - -3.0502617256965, - 0.039420536879154, - 0.12558408424308, - -0.2799932969871, - 1.389979956946, - -2.018991502357, - -8.2147637173963e-03, - -0.47596035734923, - 0.0439840744735, - -0.44476435428739, - 0.90572070719733, - 0.70522450087967, - 0.10770512626332, - -0.32913623258954, - -0.50871062041158, - -0.022175400873096, - 0.094260751665092, - 0.16436278447961, - -0.013503372241348, - -0.014834345352472, - 5.7922953628084e-04, - 3.2308904703711e-03, - 8.0964802996215e-05, - -1.6557679795037e-04, - -4.4923899061815e-05, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ - tc = Constants.__CRITICAL_TEMPERATURE__ - rhoc = 322.0 # kg/m3 - delta = rho / rhoc - tau = tc / T + delta = rho / _rhoc + tau = _tc / T + fidelta = 0 - for i in range(1, 40): - fidelta = fidelta + ni[i] * Ii[i] * delta ** (Ii[i] - 1) * tau ** Ji[i] + for I, J, n in zip(R7_97.Table30_I, R7_97.Table30_J, R7_97.Table30_n): + fidelta = fidelta + n * I * delta ** (I - 1) * tau**J - fidelta = fidelta + (ni[0] / delta) - return (rho * R * T * delta * fidelta) / 1000.0 + fidelta = fidelta + (R7_97.Table30_n[0] / delta) + return (rho * _R * T * delta * fidelta) / 1000.0 - @staticmethod - def u3_rhoT(rho, T): + @classmethod + def u3_rhoT(cls, rho: float, T: float) -> float: """function u3_rhoT = u3_rhoT(rho, T) 7 Basic Equation for Region 3, Section. 6.1 Basic Equation Table 30 and 31, Page 30 and 31 + + :param rho: density in [kg / m³] + :param T: temperature in [K] + + :return: specific internal energy in [kJ / kg] """ - Ii = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 4, - 5, - 5, - 5, - 6, - 6, - 6, - 7, - 8, - 9, - 9, - 10, - 10, - 11, - ] - Ji = [ - 0, - 0, - 1, - 2, - 7, - 10, - 12, - 23, - 2, - 6, - 15, - 17, - 0, - 2, - 6, - 7, - 22, - 26, - 0, - 2, - 4, - 16, - 26, - 0, - 2, - 4, - 26, - 1, - 3, - 26, - 0, - 2, - 26, - 2, - 26, - 2, - 26, - 0, - 1, - 26, - ] - ni = [ - 1.0658070028513, - -15.732845290239, - 20.944396974307, - -7.6867707878716, - 2.6185947787954, - -2.808078114862, - 1.2053369696517, - -8.4566812812502e-03, - -1.2654315477714, - -1.1524407806681, - 0.88521043984318, - -0.64207765181607, - 0.38493460186671, - -0.85214708824206, - 4.8972281541877, - -3.0502617256965, - 0.039420536879154, - 0.12558408424308, - -0.2799932969871, - 1.389979956946, - -2.018991502357, - -8.2147637173963e-03, - -0.47596035734923, - 0.0439840744735, - -0.44476435428739, - 0.90572070719733, - 0.70522450087967, - 0.10770512626332, - -0.32913623258954, - -0.50871062041158, - -0.022175400873096, - 0.094260751665092, - 0.16436278447961, - -0.013503372241348, - -0.014834345352472, - 5.7922953628084e-04, - 3.2308904703711e-03, - 8.0964802996215e-05, - -1.6557679795037e-04, - -4.4923899061815e-05, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ - tc = Constants.__CRITICAL_TEMPERATURE__ - rhoc = 322.0 # kg/m3 - delta = rho / rhoc - tau = tc / T + delta = rho / _rhoc + tau = _tc / T + + # TODO check table range fitau = 0 - for i in range(1, 40): - fitau = fitau + ni[i] * delta ** Ii[i] * Ji[i] * tau ** (Ji[i] - 1) - return R * T * (tau * fitau) + for I, J, n in zip(R7_97.Table30_I[1:], R7_97.Table30_J[1:], R7_97.Table30_n[1:]): + fitau = fitau + n * delta**I * J * tau ** (J - 1) - @staticmethod - def h3_rhoT(rho, T): + return _R * T * (tau * fitau) + + @classmethod + def h3_rhoT(cls, rho: float, T: float) -> float: """function h3_rhoT = h3_rhoT(rho, T) 7 Basic Equation for Region 3, Section. 6.1 Basic Equation Table 30 and 31, Page 30 and 31 + + :param rho: density in [kg / m³] + :param T: temperature in [K] + + :return: enthalpy in [kJ / kg] """ - Ii = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 4, - 5, - 5, - 5, - 6, - 6, - 6, - 7, - 8, - 9, - 9, - 10, - 10, - 11, - ] - Ji = [ - 0, - 0, - 1, - 2, - 7, - 10, - 12, - 23, - 2, - 6, - 15, - 17, - 0, - 2, - 6, - 7, - 22, - 26, - 0, - 2, - 4, - 16, - 26, - 0, - 2, - 4, - 26, - 1, - 3, - 26, - 0, - 2, - 26, - 2, - 26, - 2, - 26, - 0, - 1, - 26, - ] - ni = [ - 1.0658070028513, - -15.732845290239, - 20.944396974307, - -7.6867707878716, - 2.6185947787954, - -2.808078114862, - 1.2053369696517, - -8.4566812812502e-03, - -1.2654315477714, - -1.1524407806681, - 0.88521043984318, - -0.64207765181607, - 0.38493460186671, - -0.85214708824206, - 4.8972281541877, - -3.0502617256965, - 0.039420536879154, - 0.12558408424308, - -0.2799932969871, - 1.389979956946, - -2.018991502357, - -8.2147637173963e-03, - -0.47596035734923, - 0.0439840744735, - -0.44476435428739, - 0.90572070719733, - 0.70522450087967, - 0.10770512626332, - -0.32913623258954, - -0.50871062041158, - -0.022175400873096, - 0.094260751665092, - 0.16436278447961, - -0.013503372241348, - -0.014834345352472, - 5.7922953628084e-04, - 3.2308904703711e-03, - 8.0964802996215e-05, - -1.6557679795037e-04, - -4.4923899061815e-05, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ - tc = Constants.__CRITICAL_TEMPERATURE__ - rhoc = 322.0 # kg/m3 - delta = rho / rhoc - tau = tc / T + delta = rho / _rhoc + tau = _tc / T + fidelta = 0 fitau = 0 - for i in range(1, 40): - fidelta = fidelta + ni[i] * Ii[i] * delta ** (Ii[i] - 1) * tau ** Ji[i] - fitau = fitau + ni[i] * delta ** Ii[i] * Ji[i] * tau ** (Ji[i] - 1) - fidelta = fidelta + ni[0] / delta - return R * T * (tau * fitau + delta * fidelta) + for I, J, n in zip(R7_97.Table30_I[1:], R7_97.Table30_J[1:], R7_97.Table30_n[1:]): + fidelta = fidelta + n * I * delta ** (I - 1) * tau**J + fitau = fitau + n * delta**I * J * tau ** (J - 1) - @staticmethod - def s3_rhoT(rho, T): + fidelta = fidelta + R7_97.Table30_n[0] / delta + return _R * T * (tau * fitau + delta * fidelta) + + @classmethod + def s3_rhoT(cls, rho: float, T: float) -> float: """function s3_rhoT = s3_rhoT(rho, T) 7 Basic Equation for Region 3, Section. 6.1 Basic Equation Table 30 and 31, Page 30 and 31 + + :param rho: density in [kg / m³] + :param T: temperature in [K] + + :return: specific entropy in [kJ / (kg K)] """ - Ii = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 4, - 5, - 5, - 5, - 6, - 6, - 6, - 7, - 8, - 9, - 9, - 10, - 10, - 11, - ] - Ji = [ - 0, - 0, - 1, - 2, - 7, - 10, - 12, - 23, - 2, - 6, - 15, - 17, - 0, - 2, - 6, - 7, - 22, - 26, - 0, - 2, - 4, - 16, - 26, - 0, - 2, - 4, - 26, - 1, - 3, - 26, - 0, - 2, - 26, - 2, - 26, - 2, - 26, - 0, - 1, - 26, - ] - ni = [ - 1.0658070028513, - -15.732845290239, - 20.944396974307, - -7.6867707878716, - 2.6185947787954, - -2.808078114862, - 1.2053369696517, - -8.4566812812502e-03, - -1.2654315477714, - -1.1524407806681, - 0.88521043984318, - -0.64207765181607, - 0.38493460186671, - -0.85214708824206, - 4.8972281541877, - -3.0502617256965, - 0.039420536879154, - 0.12558408424308, - -0.2799932969871, - 1.389979956946, - -2.018991502357, - -8.2147637173963e-03, - -0.47596035734923, - 0.0439840744735, - -0.44476435428739, - 0.90572070719733, - 0.70522450087967, - 0.10770512626332, - -0.32913623258954, - -0.50871062041158, - -0.022175400873096, - 0.094260751665092, - 0.16436278447961, - -0.013503372241348, - -0.014834345352472, - 5.7922953628084e-04, - 3.2308904703711e-03, - 8.0964802996215e-05, - -1.6557679795037e-04, - -4.4923899061815e-05, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ - tc = Constants.__CRITICAL_TEMPERATURE__ - rhoc = 322.0 # kg/m3 - delta = rho / rhoc - tau = tc / T + delta = rho / _rhoc + tau = _tc / T + fi = 0 fitau = 0 - for i in range(1, 40): - fi = fi + ni[i] * delta ** Ii[i] * tau ** Ji[i] - fitau = fitau + ni[i] * delta ** Ii[i] * Ji[i] * tau ** (Ji[i] - 1) - fi = fi + ni[0] * math.log(delta) - return R * (tau * fitau - fi) + for I, J, n in zip(R7_97.Table30_I[1:], R7_97.Table30_J[1:], R7_97.Table30_n[1:]): + fi = fi + n * delta**I * tau**J + fitau = fitau + n * delta**I * J * tau ** (J - 1) - @staticmethod - def Cp3_rhoT(rho, T): + fi = fi + R7_97.Table30_n[0] * math.log(delta) + return _R * (tau * fitau - fi) + + @classmethod + def Cp3_rhoT(cls, rho: float, T: float) -> float: """function Cp3_rhoT = Cp3_rhoT(rho, T) 7 Basic Equation for Region 3, Section. 6.1 Basic Equation Table 30 and 31, Page 30 and 31 + + :param rho: density in [kg / m³] + :param T: temperature in [K] + + :return: specific isobaric heat capacity in [kJ / (kg K)] """ - Ii = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 4, - 5, - 5, - 5, - 6, - 6, - 6, - 7, - 8, - 9, - 9, - 10, - 10, - 11, - ] - Ji = [ - 0, - 0, - 1, - 2, - 7, - 10, - 12, - 23, - 2, - 6, - 15, - 17, - 0, - 2, - 6, - 7, - 22, - 26, - 0, - 2, - 4, - 16, - 26, - 0, - 2, - 4, - 26, - 1, - 3, - 26, - 0, - 2, - 26, - 2, - 26, - 2, - 26, - 0, - 1, - 26, - ] - ni = [ - 1.0658070028513, - -15.732845290239, - 20.944396974307, - -7.6867707878716, - 2.6185947787954, - -2.808078114862, - 1.2053369696517, - -8.4566812812502e-03, - -1.2654315477714, - -1.1524407806681, - 0.88521043984318, - -0.64207765181607, - 0.38493460186671, - -0.85214708824206, - 4.8972281541877, - -3.0502617256965, - 0.039420536879154, - 0.12558408424308, - -0.2799932969871, - 1.389979956946, - -2.018991502357, - -8.2147637173963e-03, - -0.47596035734923, - 0.0439840744735, - -0.44476435428739, - 0.90572070719733, - 0.70522450087967, - 0.10770512626332, - -0.32913623258954, - -0.50871062041158, - -0.022175400873096, - 0.094260751665092, - 0.16436278447961, - -0.013503372241348, - -0.014834345352472, - 5.7922953628084e-04, - 3.2308904703711e-03, - 8.0964802996215e-05, - -1.6557679795037e-04, - -4.4923899061815e-05, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ - tc = Constants.__CRITICAL_TEMPERATURE__ - rhoc = 322.0 # kg/m3 - delta = rho / rhoc - tau = tc / T + delta = rho / _rhoc + tau = _tc / T + fitautau = 0 fidelta = 0 fideltatau = 0 fideltadelta = 0 - for i in range(1, 40): - fitautau = fitautau + ni[i] * delta ** Ii[i] * Ji[i] * ( - Ji[i] - 1 - ) * tau ** (Ji[i] - 2) - fidelta = fidelta + ni[i] * Ii[i] * delta ** (Ii[i] - 1) * tau ** Ji[i] - fideltatau = fideltatau + ni[i] * Ii[i] * delta ** (Ii[i] - 1) * Ji[ - i - ] * tau ** (Ji[i] - 1) - fideltadelta = ( - fideltadelta - + ni[i] * Ii[i] * (Ii[i] - 1) * delta ** (Ii[i] - 2) * tau ** Ji[i] - ) - fidelta = fidelta + ni[0] / delta - fideltadelta = fideltadelta - ni[0] / (delta**2) - return R * ( - -(tau**2) * fitautau - + (delta * fidelta - delta * tau * fideltatau) ** 2 - / (2 * delta * fidelta + delta**2 * fideltadelta) + for I, J, n in zip(R7_97.Table30_I[1:], R7_97.Table30_J[1:], R7_97.Table30_n[1:]): + fitautau = fitautau + n * delta**I * J * (J - 1) * tau ** (J - 2) + fidelta = fidelta + n * I * delta ** (I - 1) * tau**J + fideltatau = fideltatau + n * I * delta ** (I - 1) * J * tau ** (J - 1) + fideltadelta = fideltadelta + n * I * (I - 1) * delta ** (I - 2) * tau**J + + fidelta = fidelta + R7_97.Table30_n[0] / delta + fideltadelta = fideltadelta - R7_97.Table30_n[0] / (delta**2) + return _R * ( + -(tau**2) * fitautau + (delta * fidelta - delta * tau * fideltatau) ** 2 / (2 * delta * fidelta + delta**2 * fideltadelta) ) - @staticmethod - def Cv3_rhoT(rho, T): + @classmethod + def Cv3_rhoT(cls, rho: float, T: float) -> float: """function Cv3_rhoT = Cv3_rhoT(rho, T) 7 Basic Equation for Region 3, Section. 6.1 Basic Equation Table 30 and 31, Page 30 and 31 + + :param rho: density in [kg / m³] + :param T: temperature in [K] + + :return: specific isochoric heat capacity in [kJ / (kg K)] """ - Ii = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 4, - 5, - 5, - 5, - 6, - 6, - 6, - 7, - 8, - 9, - 9, - 10, - 10, - 11, - ] - Ji = [ - 0, - 0, - 1, - 2, - 7, - 10, - 12, - 23, - 2, - 6, - 15, - 17, - 0, - 2, - 6, - 7, - 22, - 26, - 0, - 2, - 4, - 16, - 26, - 0, - 2, - 4, - 26, - 1, - 3, - 26, - 0, - 2, - 26, - 2, - 26, - 2, - 26, - 0, - 1, - 26, - ] - ni = [ - 1.0658070028513, - -15.732845290239, - 20.944396974307, - -7.6867707878716, - 2.6185947787954, - -2.808078114862, - 1.2053369696517, - -8.4566812812502e-03, - -1.2654315477714, - -1.1524407806681, - 0.88521043984318, - -0.64207765181607, - 0.38493460186671, - -0.85214708824206, - 4.8972281541877, - -3.0502617256965, - 0.039420536879154, - 0.12558408424308, - -0.2799932969871, - 1.389979956946, - -2.018991502357, - -8.2147637173963e-03, - -0.47596035734923, - 0.0439840744735, - -0.44476435428739, - 0.90572070719733, - 0.70522450087967, - 0.10770512626332, - -0.32913623258954, - -0.50871062041158, - -0.022175400873096, - 0.094260751665092, - 0.16436278447961, - -0.013503372241348, - -0.014834345352472, - 5.7922953628084e-04, - 3.2308904703711e-03, - 8.0964802996215e-05, - -1.6557679795037e-04, - -4.4923899061815e-05, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ - tc = Constants.__CRITICAL_TEMPERATURE__ - rhoc = 322.0 # kg/m3 - delta = rho / rhoc - tau = tc / T + delta = rho / _rhoc + tau = _tc / T + fitautau = 0 # TODO:vvvv Check for mistake vvvvv # for i = 1 : 40 # IAWPS says i=2..40 - for i in range(1, 40): - fitautau = fitautau + ni[i] * delta ** Ii[i] * Ji[i] * ( - Ji[i] - 1 - ) * tau ** (Ji[i] - 2) - return R * -(tau * tau * fitautau) + for I, J, n in zip(R7_97.Table30_I[1:], R7_97.Table30_J[1:], R7_97.Table30_n[1:]): + # for i in range(1, 40): + fitautau = fitautau + n * delta**I * J * (J - 1) * tau ** (J - 2) - @staticmethod - def w3_rhoT(rho, T): + return _R * -(tau * tau * fitautau) + + @classmethod + def w3_rhoT(cls, rho: float, T: float) -> float: """function w3_rhoT = w3_rhoT(rho, T) 7 Basic Equation for Region 3, Section. 6.1 Basic Equation Table 30 and 31, Page 30 and 31 + + :param rho: density in [kg / m³] + :param T: temperature in [K] + + :return: speed of sound in [m / s] """ - Ii = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 4, - 5, - 5, - 5, - 6, - 6, - 6, - 7, - 8, - 9, - 9, - 10, - 10, - 11, - ] - Ji = [ - 0, - 0, - 1, - 2, - 7, - 10, - 12, - 23, - 2, - 6, - 15, - 17, - 0, - 2, - 6, - 7, - 22, - 26, - 0, - 2, - 4, - 16, - 26, - 0, - 2, - 4, - 26, - 1, - 3, - 26, - 0, - 2, - 26, - 2, - 26, - 2, - 26, - 0, - 1, - 26, - ] - ni = [ - 1.0658070028513, - -15.732845290239, - 20.944396974307, - -7.6867707878716, - 2.6185947787954, - -2.808078114862, - 1.2053369696517, - -8.4566812812502e-03, - -1.2654315477714, - -1.1524407806681, - 0.88521043984318, - -0.64207765181607, - 0.38493460186671, - -0.85214708824206, - 4.8972281541877, - -3.0502617256965, - 0.039420536879154, - 0.12558408424308, - -0.2799932969871, - 1.389979956946, - -2.018991502357, - -8.2147637173963e-03, - -0.47596035734923, - 0.0439840744735, - -0.44476435428739, - 0.90572070719733, - 0.70522450087967, - 0.10770512626332, - -0.32913623258954, - -0.50871062041158, - -0.022175400873096, - 0.094260751665092, - 0.16436278447961, - -0.013503372241348, - -0.014834345352472, - 5.7922953628084e-04, - 3.2308904703711e-03, - 8.0964802996215e-05, - -1.6557679795037e-04, - -4.4923899061815e-05, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ - tc = Constants.__CRITICAL_TEMPERATURE__ - rhoc = 322.0 # kg/m3 - delta = rho / rhoc - tau = tc / T + delta = rho / _rhoc + tau = _tc / T + fitautau = 0 fidelta = 0 fideltatau = 0 fideltadelta = 0 - for i in range(1, 40): - fitautau = fitautau + ni[i] * delta ** Ii[i] * Ji[i] * ( - Ji[i] - 1 - ) * tau ** (Ji[i] - 2) - fidelta = fidelta + ni[i] * Ii[i] * delta ** (Ii[i] - 1) * tau ** Ji[i] - fideltatau = fideltatau + ni[i] * Ii[i] * delta ** (Ii[i] - 1) * Ji[ - i - ] * tau ** (Ji[i] - 1) - fideltadelta = ( - fideltadelta - + ni[i] * Ii[i] * (Ii[i] - 1) * delta ** (Ii[i] - 2) * tau ** Ji[i] - ) - fidelta = fidelta + ni[0] / delta - fideltadelta = fideltadelta - ni[0] / (delta**2) + for I, J, n in zip(R7_97.Table30_I[1:], R7_97.Table30_J[1:], R7_97.Table30_n[1:]): + fitautau = fitautau + n * delta**I * J * (J - 1) * tau ** (J - 2) + fidelta = fidelta + n * I * delta ** (I - 1) * tau**J + fideltatau = fideltatau + n * I * delta ** (I - 1) * J * tau ** (J - 1) + fideltadelta = fideltadelta + n * I * (I - 1) * delta ** (I - 2) * tau**J + + fidelta = fidelta + R7_97.Table30_n[0] / delta + fideltadelta = fideltadelta - R7_97.Table30_n[0] / (delta**2) return ( 1000 - * R + * _R * T - * ( - 2 * delta * fidelta - + delta**2 * fideltadelta - - (delta * fidelta - delta * tau * fideltatau) ** 2 - / (tau**2 * fitautau) - ) + * (2 * delta * fidelta + delta**2 * fideltadelta - (delta * fidelta - delta * tau * fideltatau) ** 2 / (tau**2 * fitautau)) ) ** 0.5 - @staticmethod - def T3_ph(p, h): + @classmethod + def T3_ph(cls, p: float, h: float) -> float: """function T3_ph = T3_ph(p, h) - Revised Supplementary Release on Backward Equations for the functions T(p,h), v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS Industrial formulation 1997 for the Thermodynamic Properties of Water and Steam 2004 + Revised Supplementary Release on Backward Equations for the functions T(p,h), + v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS Industrial formulation + 1997 for the Thermodynamic Properties of Water and Steam 2004 Section 3.3 Backward Equations T(p,h) and v(p,h) for Subregions 3a and 3b Boundary equation, Eq 1 Page 5 + + :param p: preasure in [MPa] + :param h: enthalpy in [kJ / kg] + + :return: temperature in [K] """ - h3ab = ( - 2014.64004206875 - + 3.74696550136983 * p - - 2.19921901054187e-02 * p**2 - + 8.7513168600995e-05 * p**3 - ) - if h < h3ab: + if h < hB3ab_p(p): # Subregion 3a # Eq 2, Table 3, Page 7 - Ii = [ - -12, - -12, - -12, - -12, - -12, - -12, - -12, - -12, - -10, - -10, - -10, - -8, - -8, - -8, - -8, - -5, - -3, - -2, - -2, - -2, - -1, - -1, - 0, - 0, - 1, - 3, - 3, - 4, - 4, - 10, - 12, - ] - Ji = [ - 0, - 1, - 2, - 6, - 14, - 16, - 20, - 22, - 1, - 5, - 12, - 0, - 2, - 4, - 10, - 2, - 0, - 1, - 3, - 4, - 0, - 2, - 0, - 1, - 1, - 0, - 1, - 0, - 3, - 4, - 5, - ] - ni = [ - -1.33645667811215e-07, - 4.55912656802978e-06, - -1.46294640700979e-05, - 6.3934131297008e-03, - 372.783927268847, - -7186.54377460447, - 573494.7521034, - -2675693.29111439, - -3.34066283302614e-05, - -2.45479214069597e-02, - 47.8087847764996, - 7.64664131818904e-06, - 1.28350627676972e-03, - 1.71219081377331e-02, - -8.51007304583213, - -1.36513461629781e-02, - -3.84460997596657e-06, - 3.37423807911655e-03, - -0.551624873066791, - 0.72920227710747, - -9.92522757376041e-03, - -0.119308831407288, - 0.793929190615421, - 0.454270731799386, - 0.20999859125991, - -6.42109823904738e-03, - -0.023515586860454, - 2.52233108341612e-03, - -7.64885133368119e-03, - 1.36176427574291e-02, - -1.33027883575669e-02, - ] ps = p / 100 hs = h / 2300 + Ts = 0 - for i in range(0, 31): - Ts = Ts + ni[i] * (ps + 0.24) ** Ii[i] * (hs - 0.615) ** Ji[i] + for I, J, n in zip(SR3_03.Table3_I, SR3_03.Table3_J, SR3_03.Table3_n): + Ts = Ts + n * (ps + 0.24) ** I * (hs - 0.615) ** J + T3_ph = Ts * 760 else: # Subregion 3b # Eq 3, Table 4, Page 7,8 - Ii = [ - -12, - -12, - -10, - -10, - -10, - -10, - -10, - -8, - -8, - -8, - -8, - -8, - -6, - -6, - -6, - -4, - -4, - -3, - -2, - -2, - -1, - -1, - -1, - -1, - -1, - -1, - 0, - 0, - 1, - 3, - 5, - 6, - 8, - ] - Ji = [ - 0, - 1, - 0, - 1, - 5, - 10, - 12, - 0, - 1, - 2, - 4, - 10, - 0, - 1, - 2, - 0, - 1, - 5, - 0, - 4, - 2, - 4, - 6, - 10, - 14, - 16, - 0, - 2, - 1, - 1, - 1, - 1, - 1, - ] - ni = [ - 3.2325457364492e-05, - -1.27575556587181e-04, - -4.75851877356068e-04, - 1.56183014181602e-03, - 0.105724860113781, - -85.8514221132534, - 724.140095480911, - 2.96475810273257e-03, - -5.92721983365988e-03, - -1.26305422818666e-02, - -0.115716196364853, - 84.9000969739595, - -1.08602260086615e-02, - 1.54304475328851e-02, - 7.50455441524466e-02, - 2.52520973612982e-02, - -6.02507901232996e-02, - -3.07622221350501, - -5.74011959864879e-02, - 5.03471360939849, - -0.925081888584834, - 3.91733882917546, - -77.314600713019, - 9493.08762098587, - -1410437.19679409, - 8491662.30819026, - 0.861095729446704, - 0.32334644281172, - 0.873281936020439, - -0.436653048526683, - 0.286596714529479, - -0.131778331276228, - 6.76682064330275e-03, - ] hs = h / 2800 ps = p / 100 + Ts = 0 - for i in range(0, 33): - Ts = Ts + ni[i] * (ps + 0.298) ** Ii[i] * (hs - 0.72) ** Ji[i] + for I, J, n in zip(SR3_03.Table4_I, SR3_03.Table4_J, SR3_03.Table4_n): + Ts = Ts + n * (ps + 0.298) ** I * (hs - 0.72) ** J + T3_ph = Ts * 860 return T3_ph - @staticmethod - def v3_ph(p, h): + @classmethod + def v3_ph(cls, p: float, h: float) -> float: """function v3_ph = v3_ph(p, h) - Revised Supplementary Release on Backward Equations for the functions T(p, h), v(p, h) and T(p, s), v(p, s) for Region 3 of the IAPWS Industrial formulation 1997 for the Thermodynamic Properties of Water and Steam 2004 + Revised Supplementary Release on Backward Equations for the functions T(p, h), v(p, h) and T(p, s), v(p, s) for Region 3 + of the IAPWS Industrial formulation 1997 for the Thermodynamic Properties of Water and Steam 2004 Section 3.3 Backward Equations T(p, h) and v(p, h) for Subregions 3a and 3b Boundary equation, Eq 1 Page 5 + + :param p: preasure in [MPa] + :param h: enthalpy in [kJ / kg] + + :return: specific volume in [m³ / kg] """ - h3ab = ( - 2014.64004206875 - + 3.74696550136983 * p - - 2.19921901054187e-02 * p**2 - + 8.7513168600995e-05 * p**3 - ) - if h < h3ab: + if h < hB3ab_p(p): # Subregion 3a # Eq 4, Table 6, Page 9 - Ii = [ - -12, - -12, - -12, - -12, - -10, - -10, - -10, - -8, - -8, - -6, - -6, - -6, - -4, - -4, - -3, - -2, - -2, - -1, - -1, - -1, - -1, - 0, - 0, - 1, - 1, - 1, - 2, - 2, - 3, - 4, - 5, - 8, - ] - Ji = [ - 6, - 8, - 12, - 18, - 4, - 7, - 10, - 5, - 12, - 3, - 4, - 22, - 2, - 3, - 7, - 3, - 16, - 0, - 1, - 2, - 3, - 0, - 1, - 0, - 1, - 2, - 0, - 2, - 0, - 2, - 2, - 2, - ] - ni = [ - 5.29944062966028e-03, - -0.170099690234461, - 11.1323814312927, - -2178.98123145125, - -5.06061827980875e-04, - 0.556495239685324, - -9.43672726094016, - -0.297856807561527, - 93.9353943717186, - 1.92944939465981e-02, - 0.421740664704763, - -3689141.2628233, - -7.37566847600639e-03, - -0.354753242424366, - -1.99768169338727, - 1.15456297059049, - 5683.6687581596, - 8.08169540124668e-03, - 0.172416341519307, - 1.04270175292927, - -0.297691372792847, - 0.560394465163593, - 0.275234661176914, - -0.148347894866012, - -6.51142513478515e-02, - -2.92468715386302, - 6.64876096952665e-02, - 3.52335014263844, - -1.46340792313332e-02, - -2.24503486668184, - 1.10533464706142, - -4.08757344495612e-02, - ] ps = p / 100 hs = h / 2100 + vs = 0 - for i in range(0, 32): - vs = vs + ni[i] * (ps + 0.128) ** Ii[i] * (hs - 0.727) ** Ji[i] + for I, J, n in zip(SR3_03.Table6_I, SR3_03.Table6_J, SR3_03.Table6_n): + vs = vs + n * (ps + 0.128) ** I * (hs - 0.727) ** J + v3_ph = vs * 0.0028 else: # Subregion 3b # Eq 5, Table 7, Page 9 - Ii = [ - -12, - -12, - -8, - -8, - -8, - -8, - -8, - -8, - -6, - -6, - -6, - -6, - -6, - -6, - -4, - -4, - -4, - -3, - -3, - -2, - -2, - -1, - -1, - -1, - -1, - 0, - 1, - 1, - 2, - 2, - ] - Ji = [ - 0, - 1, - 0, - 1, - 3, - 6, - 7, - 8, - 0, - 1, - 2, - 5, - 6, - 10, - 3, - 6, - 10, - 0, - 2, - 1, - 2, - 0, - 1, - 4, - 5, - 0, - 0, - 1, - 2, - 6, - ] - ni = [ - -2.25196934336318e-09, - 1.40674363313486e-08, - 2.3378408528056e-06, - -3.31833715229001e-05, - 1.07956778514318e-03, - -0.271382067378863, - 1.07202262490333, - -0.853821329075382, - -2.15214194340526e-05, - 7.6965608822273e-04, - -4.31136580433864e-03, - 0.453342167309331, - -0.507749535873652, - -100.475154528389, - -0.219201924648793, - -3.21087965668917, - 607.567815637771, - 5.57686450685932e-04, - 0.18749904002955, - 9.05368030448107e-03, - 0.285417173048685, - 3.29924030996098e-02, - 0.239897419685483, - 4.82754995951394, - -11.8035753702231, - 0.169490044091791, - -1.79967222507787e-02, - 3.71810116332674e-02, - -5.36288335065096e-02, - 1.6069710109252, - ] ps = p / 100 hs = h / 2800 + vs = 0 - for i in range(0, 30): - vs = vs + ni[i] * (ps + 0.0661) ** Ii[i] * (hs - 0.72) ** Ji[i] + for I, J, n in zip(SR3_03.Table7_I, SR3_03.Table7_J, SR3_03.Table7_n): + vs = vs + n * (ps + 0.0661) ** I * (hs - 0.720) ** J + v3_ph = vs * 0.0088 return v3_ph - @staticmethod - def T3_ps(p, s): + @classmethod + def T3_ps(cls, p: float, s: float) -> float: """function T3_ps = T3_ps(p, s) - Revised Supplementary Release on Backward Equations for the functions T(p,h), v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS Industrial formulation 1997 for the Thermodynamic Properties of Water and Steam 2004 + Revised Supplementary Release on Backward Equations for the functions T(p,h), + v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS Industrial formulation + 1997 for the Thermodynamic Properties of Water and Steam 2004 3.4 Backward Equations T(p,s) and v(p,s) for Subregions 3a and 3b Boundary equation, Eq 6 Page 11 + + :param p: preasure in [MPa] + :param s: specific entropy in [kJ / (kg K)] + + :return: temperature in [K] """ - if s <= 4.41202148223476: + if s <= SR3_03.s_c: # Subregion 3a # Eq 6, Table 10, Page 11 - Ii = [ - -12, - -12, - -10, - -10, - -10, - -10, - -8, - -8, - -8, - -8, - -6, - -6, - -6, - -5, - -5, - -5, - -4, - -4, - -4, - -2, - -2, - -1, - -1, - 0, - 0, - 0, - 1, - 2, - 2, - 3, - 8, - 8, - 10, - ] - Ji = [ - 28, - 32, - 4, - 10, - 12, - 14, - 5, - 7, - 8, - 28, - 2, - 6, - 32, - 0, - 14, - 32, - 6, - 10, - 36, - 1, - 4, - 1, - 6, - 0, - 1, - 4, - 0, - 0, - 3, - 2, - 0, - 1, - 2, - ] - ni = [ - 1500420082.63875, - -159397258480.424, - 5.02181140217975e-04, - -67.2057767855466, - 1450.58545404456, - -8238.8953488889, - -0.154852214233853, - 11.2305046746695, - -29.7000213482822, - 43856513263.5495, - 1.37837838635464e-03, - -2.97478527157462, - 9717779473494.13, - -5.71527767052398e-05, - 28830.794977842, - -74442828926270.3, - 12.8017324848921, - -368.275545889071, - 6.64768904779177e15, - 0.044935925195888, - -4.22897836099655, - -0.240614376434179, - -4.74341365254924, - 0.72409399912611, - 0.923874349695897, - 3.99043655281015, - 3.84066651868009e-02, - -3.59344365571848e-03, - -0.735196448821653, - 0.188367048396131, - 1.41064266818704e-04, - -2.57418501496337e-03, - 1.23220024851555e-03, - ] Sigma = s / 4.4 Pi = p / 100 + teta = 0 - for i in range(0, 33): - teta = teta + ni[i] * (Pi + 0.24) ** Ii[i] * (Sigma - 0.703) ** Ji[i] + for I, J, n in zip(SR3_03.Table10_I, SR3_03.Table10_J, SR3_03.Table10_n): + teta = teta + n * (Pi + 0.24) ** I * (Sigma - 0.703) ** J + T3_ps = teta * 760 else: # Subregion 3b # Eq 7, Table 11, Page 11 - Ii = [ - -12, - -12, - -12, - -12, - -8, - -8, - -8, - -6, - -6, - -6, - -5, - -5, - -5, - -5, - -5, - -4, - -3, - -3, - -2, - 0, - 2, - 3, - 4, - 5, - 6, - 8, - 12, - 14, - ] - Ji = [ - 1, - 3, - 4, - 7, - 0, - 1, - 3, - 0, - 2, - 4, - 0, - 1, - 2, - 4, - 6, - 12, - 1, - 6, - 2, - 0, - 1, - 1, - 0, - 24, - 0, - 3, - 1, - 2, - ] - ni = [ - 0.52711170160166, - -40.1317830052742, - 153.020073134484, - -2247.99398218827, - -0.193993484669048, - -1.40467557893768, - 42.6799878114024, - 0.752810643416743, - 22.6657238616417, - -622.873556909932, - -0.660823667935396, - 0.841267087271658, - -25.3717501764397, - 485.708963532948, - 880.531517490555, - 2650155.92794626, - -0.359287150025783, - -656.991567673753, - 2.41768149185367, - 0.856873461222588, - 0.655143675313458, - -0.213535213206406, - 5.62974957606348e-03, - -316955725450471, - -6.99997000152457e-04, - 1.19845803210767e-02, - 1.93848122022095e-05, - -2.15095749182309e-05, - ] Sigma = s / 5.3 Pi = p / 100 + teta = 0 - for i in range(0, 28): - teta = teta + ni[i] * (Pi + 0.76) ** Ii[i] * (Sigma - 0.818) ** Ji[i] + for I, J, n in zip(SR3_03.Table11_I, SR3_03.Table11_J, SR3_03.Table11_n): + teta = teta + n * (Pi + 0.76) ** I * (Sigma - 0.818) ** J + T3_ps = teta * 860 return T3_ps - @staticmethod - def v3_ps(p, s): + @classmethod + def v3_ps(cls, p: float, s: float) -> float: """function v3_ps = v3_ps(p, s) - Revised Supplementary Release on Backward Equations for the functions T(p, h), v(p, h) and T(p, s), v(p, s) for Region 3 of the IAPWS Industrial formulation 1997 for the Thermodynamic Properties of Water and Steam 2004 + Revised Supplementary Release on Backward Equations for the functions T(p, h), + v(p, h) and T(p, s), v(p, s) for Region 3 of the IAPWS Industrial formulation + 1997 for the Thermodynamic Properties of Water and Steam 2004 3.4 Backward Equations T(p, s) and v(p, s) for Subregions 3a and 3b Boundary equation, Eq 6 Page 11 + + :param p: preasure in [MPa] + :param s: specific entropy in [kJ / (kg K)] + + :return: specific volume in [m³ / kg] """ - if s <= 4.41202148223476: + if s <= SR3_03.s_c: # Subregion 3a # Eq 8, Table 13, Page 14 - Ii = [ - -12, - -12, - -12, - -10, - -10, - -10, - -10, - -8, - -8, - -8, - -8, - -6, - -5, - -4, - -3, - -3, - -2, - -2, - -1, - -1, - 0, - 0, - 0, - 1, - 2, - 4, - 5, - 6, - ] - Ji = [ - 10, - 12, - 14, - 4, - 8, - 10, - 20, - 5, - 6, - 14, - 16, - 28, - 1, - 5, - 2, - 4, - 3, - 8, - 1, - 2, - 0, - 1, - 3, - 0, - 0, - 2, - 2, - 0, - ] - ni = [ - 79.5544074093975, - -2382.6124298459, - 17681.3100617787, - -1.10524727080379e-03, - -15.3213833655326, - 297.544599376982, - -35031520.6871242, - 0.277513761062119, - -0.523964271036888, - -148011.182995403, - 1600148.99374266, - 1708023226634.27, - 2.46866996006494e-04, - 1.6532608479798, - -0.118008384666987, - 2.537986423559, - 0.965127704669424, - -28.2172420532826, - 0.203224612353823, - 1.10648186063513, - 0.52612794845128, - 0.277000018736321, - 1.08153340501132, - -7.44127885357893e-02, - 1.64094443541384e-02, - -6.80468275301065e-02, - 0.025798857610164, - -1.45749861944416e-04, - ] Pi = p / 100 Sigma = s / 4.4 + omega = 0 - for i in range(0, 28): - omega = omega + ni[i] * (Pi + 0.187) ** Ii[i] * (Sigma - 0.755) ** Ji[i] + for I, J, n in zip(SR3_03.Table13_I, SR3_03.Table13_J, SR3_03.Table13_n): + omega = omega + n * (Pi + 0.187) ** I * (Sigma - 0.755) ** J + v3_ps = omega * 0.0028 else: # Subregion 3b # Eq 9, Table 14, Page 14 - Ii = [ - -12, - -12, - -12, - -12, - -12, - -12, - -10, - -10, - -10, - -10, - -8, - -5, - -5, - -5, - -4, - -4, - -4, - -4, - -3, - -2, - -2, - -2, - -2, - -2, - -2, - 0, - 0, - 0, - 1, - 1, - 2, - ] - Ji = [ - 0, - 1, - 2, - 3, - 5, - 6, - 0, - 1, - 2, - 4, - 0, - 1, - 2, - 3, - 0, - 1, - 2, - 3, - 1, - 0, - 1, - 2, - 3, - 4, - 12, - 0, - 1, - 2, - 0, - 2, - 2, - ] - ni = [ - 5.91599780322238e-05, - -1.85465997137856e-03, - 1.04190510480013e-02, - 5.9864730203859e-03, - -0.771391189901699, - 1.72549765557036, - -4.67076079846526e-04, - 1.34533823384439e-02, - -8.08094336805495e-02, - 0.508139374365767, - 1.28584643361683e-03, - -1.63899353915435, - 5.86938199318063, - -2.92466667918613, - -6.14076301499537e-03, - 5.76199014049172, - -12.1613320606788, - 1.67637540957944, - -7.44135838773463, - 3.78168091437659e-02, - 4.01432203027688, - 16.0279837479185, - 3.17848779347728, - -3.58362310304853, - -1159952.60446827, - 0.199256573577909, - -0.122270624794624, - -19.1449143716586, - -1.50448002905284e-02, - 14.6407900162154, - -3.2747778718823, - ] Pi = p / 100 Sigma = s / 5.3 + omega = 0 - for i in range(0, 31): - omega = omega + ni[i] * (Pi + 0.298) ** Ii[i] * (Sigma - 0.816) ** Ji[i] + for I, J, n in zip(SR3_03.Table14_I, SR3_03.Table14_J, SR3_03.Table14_n): + omega = omega + n * (Pi + 0.298) ** I * (Sigma - 0.816) ** J + v3_ps = omega * 0.0088 return v3_ps - @staticmethod - def p3_hs(h, s): + @classmethod + def p3_hs(cls, h: float, s: float) -> float: """function p3_hs = p3_hs(h, s) - Supplementary Release on Backward Equations () , p h s for Region 3, Equations as a function of h and s for the Region Boundaries, and an Equation sat , T hs for Region 4 of the IAPWS Industrial formulation 1997 for the Thermodynamic Properties of Water and Steam 2004 + Supplementary Release on Backward Equations () , p h s for Region 3, + Equations as a function of h and s for the Region Boundaries, and an + Equation sat, T hs for Region 4 of the IAPWS Industrial formulation 1997 + for the Thermodynamic Properties of Water and Steam 2004 Section 3 Backward functions p(h, s), T(h, s), and v(h, s) for Region 3 + + :param h: enthalpy in [kJ / kg] + :param s: specific entropy in [kJ / (kg K)] + + :return: preasure in [MPa] """ - if s < 4.41202148223476: + if s < SR3_03.s_c: # Subregion 3a # Eq 1, Table 3, Page 8 - Ii = [ - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 3, - 3, - 3, - 4, - 4, - 4, - 4, - 5, - 6, - 7, - 8, - 10, - 10, - 14, - 18, - 20, - 22, - 22, - 24, - 28, - 28, - 32, - 32, - ] - Ji = [ - 0, - 1, - 5, - 0, - 3, - 4, - 8, - 14, - 6, - 16, - 0, - 2, - 3, - 0, - 1, - 4, - 5, - 28, - 28, - 24, - 1, - 32, - 36, - 22, - 28, - 36, - 16, - 28, - 36, - 16, - 36, - 10, - 28, - ] - ni = [ - 7.70889828326934, - -26.0835009128688, - 267.416218930389, - 17.2221089496844, - -293.54233214597, - 614.135601882478, - -61056.2757725674, - -65127225.1118219, - 73591.9313521937, - -11664650591.4191, - 35.5267086434461, - -596.144543825955, - -475.842430145708, - 69.6781965359503, - 335.674250377312, - 25052.6809130882, - 146997.380630766, - 5.38069315091534e19, - 1.43619827291346e21, - 3.64985866165994e19, - -2547.41561156775, - 2.40120197096563e27, - -3.93847464679496e29, - 1.47073407024852e24, - -4.26391250432059e31, - 1.94509340621077e38, - 6.66212132114896e23, - 7.06777016552858e33, - 1.75563621975576e41, - 1.08408607429124e28, - 7.30872705175151e43, - 1.5914584739887e24, - 3.77121605943324e40, - ] Sigma = s / 4.4 eta = h / 2300 Pi = 0 - for i in range(0, 33): - Pi = Pi + ni[i] * (eta - 1.01) ** Ii[i] * (Sigma - 0.75) ** Ji[i] + for I, J, n in zip(SR4_04.Table3_I, SR4_04.Table3_J, SR4_04.Table3_n): + Pi = Pi + n * (eta - 1.01) ** I * (Sigma - 0.75) ** J p3_hs = Pi * 99 else: # Subregion 3b # Eq 2, Table 4, Page 8 - Ii = [ - -12, - -12, - -12, - -12, - -12, - -10, - -10, - -10, - -10, - -8, - -8, - -6, - -6, - -6, - -6, - -5, - -4, - -4, - -4, - -3, - -3, - -3, - -3, - -2, - -2, - -1, - 0, - 2, - 2, - 5, - 6, - 8, - 10, - 14, - 14, - ] - Ji = [ - 2, - 10, - 12, - 14, - 20, - 2, - 10, - 14, - 18, - 2, - 8, - 2, - 6, - 7, - 8, - 10, - 4, - 5, - 8, - 1, - 3, - 5, - 6, - 0, - 1, - 0, - 3, - 0, - 1, - 0, - 1, - 1, - 1, - 3, - 7, - ] - ni = [ - 1.25244360717979e-13, - -1.26599322553713e-02, - 5.06878030140626, - 31.7847171154202, - -391041.161399932, - -9.75733406392044e-11, - -18.6312419488279, - 510.973543414101, - 373847.005822362, - 2.99804024666572e-08, - 20.0544393820342, - -4.98030487662829e-06, - -10.230180636003, - 55.2819126990325, - -206.211367510878, - -7940.12232324823, - 7.82248472028153, - -58.6544326902468, - 3550.73647696481, - -1.15303107290162e-04, - -1.75092403171802, - 257.98168774816, - -727.048374179467, - 1.21644822609198e-04, - 3.93137871762692e-02, - 7.04181005909296e-03, - -82.910820069811, - -0.26517881813125, - 13.7531682453991, - -52.2394090753046, - 2405.56298941048, - -22736.1631268929, - 89074.6343932567, - -23923456.5822486, - 5687958081.29714, - ] Sigma = s / 5.3 eta = h / 2800 Pi = 0 + # TODO check table range # for i = 1 : 35 - for i in range(0, 35): - Pi = Pi + ni[i] * (eta - 0.681) ** Ii[i] * (Sigma - 0.792) ** Ji[i] + for I, J, n in zip(SR4_04.Table4_I, SR4_04.Table4_J, SR4_04.Table4_n): + Pi = Pi + n * (eta - 0.681) ** I * (Sigma - 0.792) ** J p3_hs = 16.6 / Pi return p3_hs - @staticmethod - def h3_pT(p, T): + @classmethod + def h3_pT(cls, p: float, T: float) -> float: """function h3_pT = h3_pT(p, T) Not available with if 97 Solve function T3_ph - T = 0 with half interval method. - ver2.6 Start corrected bug + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: enthalpy in [kJ / kg] """ - logger = logging.getLogger("pyXSteam") - if p < 22.06395: # Below triple point + hs = float("NaN") + if p < _pc: # Below triple point Ts = Region4.T4_p(p) # Saturation temperature if T <= Ts: # Liquid side High_Bound = Region4.h4L_p(p) # Max h ???r liauid h. Low_Bound = Region1.h1_pT(p, 623.15) else: Low_Bound = Region4.h4V_p(p) # Min h ???r Vapour h. - High_Bound = Region2.h2_pT(p, RegionBorders.B23T_p(p)) - else: # Above triple point. R3 from R2 till R3. + High_Bound = Region2.h2_pT(p, TB23_p(p)) + else: # Above triple point. R3 from R2 till R1. Low_Bound = Region1.h1_pT(p, 623.15) - High_Bound = Region2.h2_pT(p, RegionBorders.B23T_p(p)) + High_Bound = Region2.h2_pT(p, TB23_p(p)) Ts = T + 1 step_counter = 0 @@ -5716,7 +1334,7 @@ def h3_pT(p, T): Ts = Region3.T3_ph(p, hs) if last_Ts == Ts: - logger.warning( + cls._logger.warning( "h3_pT stopped iterating after %d steps because values did not converge", step_counter, ) @@ -5728,13 +1346,19 @@ def h3_pT(p, T): Low_Bound = hs return hs - @staticmethod - def T3_prho(p, rho): + @classmethod + def T3_prho(cls, p: float, rho: float) -> float: """function T3_prho = T3_prho(p, rho) - Solve by iteration. Observe that of low temperatures this equation has 2 solutions. Solve with half interval method + Solve by iteration. Observe that of low temperatures this equation has + 2 solutions. Solve with half interval method + + :param p: preasure in [MPa] + :param rho: density in [kg / m³] + + :return: temperature in [K] """ - logger = logging.getLogger("pyXSteam") + Ts = float("NaN") Low_Bound = 623.15 High_Bound = 1073.15 ps = -1000 @@ -5747,7 +1371,7 @@ def T3_prho(p, rho): ps = Region3.p3_rhoT(rho, Ts) if last_ps == ps: - logger.warning( + cls._logger.warning( "T3_prho stopped iterating after %d steps because values did not converge", step_counter, ) @@ -5759,350 +1383,180 @@ def T3_prho(p, rho): Low_Bound = Ts return Ts + @staticmethod + def psat3_h(h: float) -> float: + """ + calculate saturation preasure from preasure for region 3 + + Section 4.2 Region 3. pSat_h & pSat_s + + Revised Supplementary Release on Backward Equations for the functions T(p,h), v(p,h) s& T(p,s), v(p,s) for Region 3 + of the IAPWS Industrial formulation 1997 for the Thermodynamic Properties of Water & Steam 2004 Section 4 Boundary + Equations psat(h) & psat(s) for the Saturation Lines of Region 3 + + See pictures Page 17, Eq 10, Table 17, Page 18 + + :param h: enthalpy in [kJ / kg] + + :return: saturation preasure in [MPa] + """ + hs = h / 2600 + ps = 0 + for I, J, n in zip(SR3_03.Table17_I, SR3_03.Table17_J, SR3_03.Table17_n): + ps = ps + n * (hs - 1.02) ** I * (hs - 0.608) ** J # SR3-03 Eq 10 + return ps * 22 + + @staticmethod + def psat3_s(s: float) -> float: + """ + calculate saturation preasure from Specific entropy for region 3 + + Section 4.2 Region 3. pSat_h & pSat_s + + :param s: Specific entropy in [kJ / (kg K)] + + :return: saturation preasure in [MPa] + """ + sigma = s / 5.2 + pi = 0 + for I, J, n in zip(SR3_03.Table19_I, SR3_03.Table19_J, SR3_03.Table19_n): + pi += n * (sigma - 1.03) ** I * (sigma - 0.699) ** J # SR3-03 Eq 11 + return pi * 22 + class Region4: """ - Section 2.4: IAPWS IF 97 Calling functions to calculate the properties of water in Region 4 + Section 2.4: IAPWS IF 97 Calling functions to calculate the properties of + water in Region 4 """ - @staticmethod - def p4_T(T): + _logger = logging.getLogger(__name__) + + @classmethod + def p4_T(cls, T: float) -> float: """function p4_T = p4_T(T) Section 8.1 The Saturation-Pressure Equation Eq 30, Page 33 - """ - teta = T - 0.23855557567849 / (T - 650.17534844798) - a = teta**2 + 1167.0521452767 * teta - 724213.16703206 - B = -17.073846940092 * teta**2 + 12020.82470247 * teta - 3232555.0322333 - C = 14.91510861353 * teta**2 - 4823.2657361591 * teta + 405113.40542057 - return (2 * C / (-B + (B**2 - 4 * a * C) ** 0.5)) ** 4 - @staticmethod - def T4_p(p): + :param T: temperature in [K] + + :return: preasure in [MPa] + """ + teta = T + R7_97.Table34_n[8] / (T - R7_97.Table34_n[9]) + A = teta**2 + R7_97.Table34_n[0] * teta + R7_97.Table34_n[1] + B = R7_97.Table34_n[2] * teta**2 + R7_97.Table34_n[3] * teta + R7_97.Table34_n[4] + C = R7_97.Table34_n[5] * teta**2 + R7_97.Table34_n[6] * teta + R7_97.Table34_n[7] + return (2 * C / (-B + (B**2 - 4 * A * C) ** 0.5)) ** 4 + + @classmethod + def T4_p(cls, p: float) -> float: """function T4_p = T4_p(p) Section 8.2 The Saturation-Temperature Equation Eq 31, Page 34 + + :param p: preasure in [MPa] + + :return: temperature in [K] """ + # TODO: replace values with table ref (at least table 34 if not more) beta = p**0.25 - E = beta**2 - 17.073846940092 * beta + 14.91510861353 - f = 1167.0521452767 * beta**2 + 12020.82470247 * beta - 4823.2657361591 - G = -724213.16703206 * beta**2 - 3232555.0322333 * beta + 405113.40542057 - D = 2 * G / (-f - (f**2 - 4 * E * G) ** 0.5) - return ( - 650.17534844798 - + D - - ( - (650.17534844798 + D) ** 2 - - 4 * (-0.23855557567849 + 650.17534844798 * D) - ) - ** 0.5 - ) / 2 - - @staticmethod - def h4_s(s): + E = beta**2 + R7_97.Table34_n[2] * beta + R7_97.Table34_n[5] + F = R7_97.Table34_n[0] * beta**2 + R7_97.Table34_n[3] * beta + R7_97.Table34_n[6] + G = R7_97.Table34_n[1] * beta**2 + R7_97.Table34_n[4] * beta + R7_97.Table34_n[7] + D = 2 * G / (-F - (F**2 - 4 * E * G) ** 0.5) + return (R7_97.Table34_n[9] + D - ((R7_97.Table34_n[9] + D) ** 2 - 4 * (R7_97.Table34_n[8] + R7_97.Table34_n[9] * D)) ** 0.5) / 2 + + @classmethod + def h4_s(cls, s: float) -> float: """function h4_s = h4_s(s) - Supplementary Release on Backward Equations () , p h s for Region 3, Equations as a function of h and s for the Region Boundaries, and an Equation() sat , T hs for Region 4 of the IAPWS Industrial formulation 1997 for the Thermodynamic Properties of Water and Steam 4 Equations for Region Boundaries Given Enthalpy and Entropy + Supplementary Release on Backward Equations () , p h s for Region 3, Equations + as a function of h and s for the Region Boundaries, and an Equation() sat, + T hs for Region 4 of the IAPWS Industrial formulation 1997 for the + Thermodynamic Properties of Water and Steam 4 Equations for Region Boundaries + Given Enthalpy and Entropy See picture page 14 + + :param s: specific entropy in [kJ / (kg K)] + + :return: enthalpy in [kJ / kg] """ - if (s > -0.0001545495919) and (s <= 3.77828134): + if SR4_04.s_dash_low < s <= SR4_04.s_dash_heigh: # hL1_s # Eq 3, Table 9, Page 16 - Ii = [ - 0, - 0, - 1, - 1, - 2, - 2, - 3, - 3, - 4, - 4, - 4, - 5, - 5, - 7, - 8, - 12, - 12, - 14, - 14, - 16, - 20, - 20, - 22, - 24, - 28, - 32, - 32, - ] - Ji = [ - 14, - 36, - 3, - 16, - 0, - 5, - 4, - 36, - 4, - 16, - 24, - 18, - 24, - 1, - 4, - 2, - 4, - 1, - 22, - 10, - 12, - 28, - 8, - 3, - 0, - 6, - 8, - ] - ni = [ - 0.332171191705237, - 6.11217706323496e-04, - -8.82092478906822, - -0.45562819254325, - -2.63483840850452e-05, - -22.3949661148062, - -4.28398660164013, - -0.616679338856916, - -14.682303110404, - 284.523138727299, - -113.398503195444, - 1156.71380760859, - 395.551267359325, - -1.54891257229285, - 19.4486637751291, - -3.57915139457043, - -3.35369414148819, - -0.66442679633246, - 32332.1885383934, - 3317.66744667084, - -22350.1257931087, - 5739538.75852936, - 173.226193407919, - -3.63968822121321e-02, - 8.34596332878346e-07, - 5.03611916682674, - 65.5444787064505, - ] Sigma = s / 3.8 eta = 0 - for i in range(0, 27): - eta = ( - eta + ni[i] * (Sigma - 1.09) ** Ii[i] * (Sigma + 0.0000366) ** Ji[i] - ) + for I, J, n in zip(SR4_04.Table9_I, SR4_04.Table9_J, SR4_04.Table9_n): + eta = eta + n * (Sigma - 1.09) ** I * (Sigma + 0.366e-4) ** J # SR4-04 Eq 3 h4_s = eta * 1700 - elif (s > 3.77828134) and (s <= 4.41202148223476): + elif SR4_04.s_dash_heigh < s <= SR3_03.s_c: # hL3_s # Eq 4, Table 10, Page 16 - Ii = [0, 0, 0, 0, 2, 3, 4, 4, 5, 5, 6, 7, 7, 7, 10, 10, 10, 32, 32] - Ji = [1, 4, 10, 16, 1, 36, 3, 16, 20, 36, 4, 2, 28, 32, 14, 32, 36, 0, 6] - ni = [ - 0.822673364673336, - 0.181977213534479, - -0.011200026031362, - -7.46778287048033e-04, - -0.179046263257381, - 4.24220110836657e-02, - -0.341355823438768, - -2.09881740853565, - -8.22477343323596, - -4.99684082076008, - 0.191413958471069, - 5.81062241093136e-02, - -1655.05498701029, - 1588.70443421201, - -85.0623535172818, - -31771.4386511207, - -94589.0406632871, - -1.3927384708869e-06, - 0.63105253224098, - ] Sigma = s / 3.8 eta = 0 - for i in range(0, 19): - eta = ( - eta + ni[i] * (Sigma - 1.09) ** Ii[i] * (Sigma + 0.0000366) ** Ji[i] - ) + for I, J, n in zip(SR4_04.Table10_I, SR4_04.Table10_J, SR4_04.Table10_n): + eta = eta + n * (Sigma - 1.09) ** I * (Sigma + 0.366e-4) ** J # SR4-04 Eq 4 h4_s = eta * 1700 - elif (s > 4.41202148223476) and (s <= 5.85): - # Section 4.4 Equations () 2ab " h s and ( ) 2c3b "h s for the Saturated Vapor Line + elif SR3_03.s_c < s <= 5.85: + # Section 4.4 Equations () 2ab " h s and ( ) 2c3b "h s for the + # Saturated Vapor Line # Page 19, Eq 5 # hV2c3b_s(s) - Ii = [0, 0, 0, 1, 1, 5, 6, 7, 8, 8, 12, 16, 22, 22, 24, 36] - Ji = [0, 3, 4, 0, 12, 36, 12, 16, 2, 20, 32, 36, 2, 32, 7, 20] - ni = [ - 1.04351280732769, - -2.27807912708513, - 1.80535256723202, - 0.420440834792042, - -105721.24483466, - 4.36911607493884e24, - -328032702839.753, - -6.7868676080427e15, - 7439.57464645363, - -3.56896445355761e19, - 1.67590585186801e31, - -3.55028625419105e37, - 396611982166.538, - -4.14716268484468e40, - 3.59080103867382e18, - -1.16994334851995e40, - ] Sigma = s / 5.9 eta = 0 - for i in range(0, 16): - eta = eta + ni[i] * (Sigma - 1.02) ** Ii[i] * (Sigma - 0.726) ** Ji[i] + for I, J, n in zip(SR4_04.Table17_I, SR4_04.Table17_J, SR4_04.Table17_n): + eta = eta + n * (Sigma - 1.02) ** I * (Sigma - 0.726) ** J # SR3-03 Eq 10 h4_s = eta**4 * 2800 - elif (s > 5.85) and (s < 9.155759395): - # Section 4.4 Equations () 2ab " h s and ( ) 2c3b "h s for the Saturated Vapor Line + elif 5.85 < s < SR4_04.s_doubledash: + # Section 4.4 Equations () 2ab " h s and ( ) 2c3b "h s for the + # Saturated Vapor Line # Page 20, Eq 6 - Ii = [ - 1, - 1, - 2, - 2, - 4, - 4, - 7, - 8, - 8, - 10, - 12, - 12, - 18, - 20, - 24, - 28, - 28, - 28, - 28, - 28, - 32, - 32, - 32, - 32, - 32, - 36, - 36, - 36, - 36, - 36, - ] - Ji = [ - 8, - 24, - 4, - 32, - 1, - 2, - 7, - 5, - 12, - 1, - 0, - 7, - 10, - 12, - 32, - 8, - 12, - 20, - 22, - 24, - 2, - 7, - 12, - 14, - 24, - 10, - 12, - 20, - 22, - 28, - ] - ni = [ - -524.581170928788, - -9269472.18142218, - -237.385107491666, - 21077015581.2776, - -23.9494562010986, - 221.802480294197, - -5104725.33393438, - 1249813.96109147, - 2000084369.96201, - -815.158509791035, - -157.612685637523, - -11420042233.2791, - 6.62364680776872e15, - -2.27622818296144e18, - -1.71048081348406e31, - 6.60788766938091e15, - 1.66320055886021e22, - -2.18003784381501e29, - -7.87276140295618e29, - 1.51062329700346e31, - 7957321.70300541, - 1.31957647355347e15, - -3.2509706829914e23, - -4.18600611419248e25, - 2.97478906557467e34, - -9.53588761745473e19, - 1.66957699620939e24, - -1.75407764869978e32, - 3.47581490626396e34, - -7.10971318427851e38, - ] Sigma1 = s / 5.21 Sigma2 = s / 9.2 eta = 0 - for i in range(0, 30): - eta = ( - eta - + ni[i] * (1 / Sigma1 - 0.513) ** Ii[i] * (Sigma2 - 0.524) ** Ji[i] - ) + for I, J, n in zip(SR4_04.Table16_I, SR4_04.Table16_J, SR4_04.Table16_n): + eta = eta + n * (1 / Sigma1 - 0.513) ** I * (Sigma2 - 0.524) ** J h4_s = math.exp(eta) * 2800 else: h4_s = -99999 return h4_s - @staticmethod - def p4_s(s): + @classmethod + def p4_s(cls, s: float) -> float: """function p4_s = p4_s(s) Uses h4_s and p_hs for the different regions to determine p4_s + + :param s: specific entropy in [kJ / (kg K)] + + :return: preasure in [MPa] """ h_sat = Region4.h4_s(s) - if s > -0.0001545495919 and s <= 3.77828134: + if SR4_04.s_dash_low < s <= SR4_04.s_dash_heigh: p4_s = Region1.p1_hs(h_sat, s) - elif s > 3.77828134 and s <= 5.210887663: + elif SR4_04.s_dash_heigh < s <= 5.210887663: p4_s = Region3.p3_hs(h_sat, s) - elif s > 5.210887663 and s < 9.155759395: + elif 5.210887663 < s < SR4_04.s_doubledash: p4_s = Region2.p2_hs(h_sat, s) else: p4_s = -99999 return p4_s - @staticmethod - def h4L_p(p): - """function h4L_p = h4L_p(p)""" - logger = logging.getLogger("pyXSteam") - if (p > 0.000611657) and (p < 22.06395): + @classmethod + def h4L_p(cls, p: float) -> float: + """function h4L_p = h4L_p(p) + + :param p: preasure in [MPa] + + :return: enthalpy in [kJ / kg] + """ + hs = float("NaN") + if TRIPLE_POINT_PRESSURE < p < _pc: Ts = Region4.T4_p(p) if p < 16.529: h4L_p = Region1.h1_pT(p, Ts) @@ -6117,10 +1571,10 @@ def h4L_p(p): last_ps = ps hs = (Low_Bound + High_Bound) / 2 - ps = RegionBorders.p3sat_h(hs) + ps = Region3.psat3_h(hs) if last_ps == ps: - logger.warning( + cls._logger.warning( "h4L_p stopped iterating after %d steps because values did not converge", step_counter, ) @@ -6135,18 +1589,23 @@ def h4L_p(p): h4L_p = -99999 return h4L_p - @staticmethod - def h4V_p(p): - """function h4V_p = h4V_p(p)""" - logger = logging.getLogger("pyXSteam") - if (p > 0.000611657) and (p < 22.06395): + @classmethod + def h4V_p(cls, p: float) -> float: + """function h4V_p = h4V_p(p) + + :param p: preasure in [MPa] + + :return: enthalpy in [kJ / kg] + """ + hs = float("NaN") + if TRIPLE_POINT_PRESSURE < p < _pc: Ts = Region4.T4_p(p) if p < 16.529: h4V_p = Region2.h2_pT(p, Ts) else: # Iterate to find the the backward solution of p3sat_h Low_Bound = 2087.23500164864 - High_Bound = 2563.592004 + 5 + High_Bound = SR3_03.h_doubledash + 5 ps = -1000 step_counter = 0 while math.fabs(p - ps) > 0.000001: @@ -6154,10 +1613,10 @@ def h4V_p(p): last_ps = ps hs = (Low_Bound + High_Bound) / 2 - ps = RegionBorders.p3sat_h(hs) + ps = Region3.psat3_h(hs) if last_ps == ps: - logger.warning( + cls._logger.warning( "h4V_p stopped iterating after %d steps because values did not converge", step_counter, ) @@ -6172,11 +1631,16 @@ def h4V_p(p): h4V_p = -99999 return h4V_p - @staticmethod - def x4_ph(p, h): + @classmethod + def x4_ph(cls, p: float, h: float) -> float: """function x4_ph = x4_ph(p, h) Calculate vapour fraction from hL and hV for given p + + :param p: preasure in [MPa] + :param h: enthalpy in [kJ / kg] + + :return: vapor fraction """ h4v = Region4.h4V_p(p) h4L = Region4.h4L_p(p) @@ -6188,19 +1652,21 @@ def x4_ph(p, h): x4_ph = (h - h4L) / (h4v - h4L) return x4_ph - @staticmethod - def x4_ps(p, s): - """function x4_ps = x4_ps(p, s)""" + @classmethod + def x4_ps(cls, p: float, s: float) -> float: + """function x4_ps = x4_ps(p, s) + + :param p: preasure in [MPa] + :param s: specific entropy in [kJ / (kg K)] + + :return: vapor fraction + """ if p < 16.529: ssv = Region2.s2_pT(p, Region4.T4_p(p)) ssL = Region1.s1_pT(p, Region4.T4_p(p)) else: - ssv = Region3.s3_rhoT( - 1 / (Region3.v3_ph(p, Region4.h4V_p(p))), Region4.T4_p(p) - ) - ssL = Region3.s3_rhoT( - 1 / (Region3.v3_ph(p, Region4.h4L_p(p))), Region4.T4_p(p) - ) + ssv = Region3.s3_rhoT(1 / (Region3.v3_ph(p, Region4.h4V_p(p))), Region4.T4_p(p)) + ssL = Region3.s3_rhoT(1 / (Region3.v3_ph(p, Region4.h4L_p(p))), Region4.T4_p(p)) if s < ssL: x4_ps = 0 elif s > ssv: @@ -6209,146 +1675,36 @@ def x4_ps(p, s): x4_ps = (s - ssL) / (ssv - ssL) return x4_ps - @staticmethod - def T4_hs(h, s): + @classmethod + def T4_hs(cls, h: float, s: float) -> float: """function T4_hs = T4_hs(h, s) Supplementary Release on Backward Equations ( ) , p h s for Region 3, Chapter 5.3 page 30. - The if 97 function is only valid for part of region4. Use iteration outside. + :param h: enthalpy in [kJ / kg] + :param s: specific entropy in [kJ / (kg K)] + + :return: temperature in [K] """ - Ii = [ - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 4, - 4, - 5, - 5, - 5, - 5, - 6, - 6, - 6, - 8, - 10, - 10, - 12, - 14, - 14, - 16, - 16, - 18, - 18, - 18, - 20, - 28, - ] - Ji = [ - 0, - 3, - 12, - 0, - 1, - 2, - 5, - 0, - 5, - 8, - 0, - 2, - 3, - 4, - 0, - 1, - 1, - 2, - 4, - 16, - 6, - 8, - 22, - 1, - 20, - 36, - 24, - 1, - 28, - 12, - 32, - 14, - 22, - 36, - 24, - 36, - ] - ni = [ - 0.179882673606601, - -0.267507455199603, - 1.162767226126, - 0.147545428713616, - -0.512871635973248, - 0.421333567697984, - 0.56374952218987, - 0.429274443819153, - -3.3570455214214, - 10.8890916499278, - -0.248483390456012, - 0.30415322190639, - -0.494819763939905, - 1.07551674933261, - 7.33888415457688e-02, - 1.40170545411085e-02, - -0.106110975998808, - 1.68324361811875e-02, - 1.25028363714877, - 1013.16840309509, - -1.51791558000712, - 52.4277865990866, - 23049.5545563912, - 2.49459806365456e-02, - 2107964.67412137, - 366836848.613065, - -144814105.365163, - -1.7927637300359e-03, - 4899556021.00459, - 471.262212070518, - -82929439019.8652, - -1715.45662263191, - 3557776.82973575, - 586062760258.436, - -12988763.5078195, - 31724744937.1057, - ] - if (s > 5.210887825) and (s < 9.15546555571324): + PL = float("NaN") + p = float("NaN") + + if 5.210887825 < s < 9.15546555571324: Sigma = s / 9.2 eta = h / 2800 teta = 0 - for i in range(0, 36): - teta = teta + ni[i] * (eta - 0.119) ** Ii[i] * (Sigma - 1.07) ** Ji[i] + for I, J, n in zip(SR4_04.Table28_I, SR4_04.Table28_J, SR4_04.Table28_n): + teta = teta + n * (eta - 0.119) ** I * (Sigma - 1.07) ** J # SR4-04 Eq 9 T4_hs = teta * 550 else: # function psat_h - if (s > -0.0001545495919) and (s <= 3.77828134): + if SR4_04.s_dash_low < s <= SR4_04.s_dash_heigh: Low_Bound = 0.000611 High_Bound = 165.291642526045 hL = -1000 - while (math.fabs(hL - h) > 0.00001) and ( - math.fabs(High_Bound - Low_Bound) > 0.0001 - ): + while (math.fabs(hL - h) > 0.00001) and (math.fabs(High_Bound - Low_Bound) > 0.0001): PL = (Low_Bound + High_Bound) / 2 Ts = Region4.T4_p(PL) hL = Region1.h1_pT(PL, Ts) @@ -6356,16 +1712,14 @@ def T4_hs(h, s): High_Bound = PL else: Low_Bound = PL - elif (s > 3.77828134) and (s <= 4.41202148223476): - PL = RegionBorders.p3sat_h(h) - elif (s > 4.41202148223476) and (s <= 5.210887663): - PL = RegionBorders.p3sat_h(h) + elif SR4_04.s_dash_heigh < s <= SR3_03.s_c: + PL = Region3.psat3_h(h) + elif SR3_03.s_c < s <= 5.210887663: + PL = Region3.psat3_h(h) Low_Bound = 0.000611 High_Bound = PL sss = -1000 - while (math.fabs(s - sss) > 0.000001) and ( - math.fabs(High_Bound - Low_Bound) > 0.0000001 - ): + while (math.fabs(s - sss) > 0.000001) and (math.fabs(High_Bound - Low_Bound) > 0.0000001): p = (Low_Bound + High_Bound) / 2 # Calculate s4_ph Ts = Region4.T4_p(p) @@ -6389,325 +1743,232 @@ def T4_hs(h, s): class Region5: """ - Section 2.5: IAPWS IF 97 Calling functions to calculate the properties of water in Region 5 + Section 2.5: IAPWS IF 97 Calling functions to calculate the properties + of water in Region 5 """ - @staticmethod - def h5_pT(p, T): + _logger = logging.getLogger(__name__) + + @classmethod + def h5_pT(cls, p: float, T: float) -> float: """function h5_pT = h5_pT(p, T) Basic Equation for Region 5 Eq 32,33, Page 36, Tables 37-41 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: enthalpy in [kJ / kg] """ - Ji0 = [0, 1, -3, -2, -1, 2] - ni0 = [ - -13.179983674201, - 6.8540841634434, - -0.024805148933466, - 0.36901534980333, - -3.1161318213925, - -0.32961626538917, - ] - Iir = [1, 1, 1, 2, 3] - Jir = [0, 1, 3, 9, 3] - nir = [ - -1.2563183589592e-04, - 2.1774678714571e-03, - -0.004594282089991, - -3.9724828359569e-06, - 1.2919228289784e-07, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ tau = 1000 / T Pi = p + gamma0_tau = 0 - for i in range(0, 6): - gamma0_tau = gamma0_tau + ni0[i] * Ji0[i] * tau ** (Ji0[i] - 1) + for J, n in zip(R7_97.Table37_J, R7_97.Table37_n): + gamma0_tau = gamma0_tau + n * J * tau ** (J - 1) + gammar_tau = 0 - for i in range(0, 5): - gammar_tau = gammar_tau + nir[i] * Pi ** Iir[i] * Jir[i] * tau ** ( - Jir[i] - 1 - ) - return R * T * tau * (gamma0_tau + gammar_tau) + for I, J, n in zip(R7_97.Tablexx_I, R7_97.Tablexx_J, R7_97.Tablexx_n): + gammar_tau = gammar_tau + n * Pi**I * J * tau ** (J - 1) - @staticmethod - def v5_pT(p, T): + return _R * T * tau * (gamma0_tau + gammar_tau) + + @classmethod + def v5_pT(cls, p: float, T: float) -> float: """function v5_pT = v5_pT(p, T) Basic Equation for Region 5 Eq 32,33, Page 36, Tables 37-41 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: specific volume in [m³ / kg] """ - Iir = [1, 1, 1, 2, 3] - Jir = [0, 1, 3, 9, 3] - nir = [ - -1.2563183589592e-04, - 2.1774678714571e-03, - -0.004594282089991, - -3.9724828359569e-06, - 1.2919228289784e-07, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ - tau = 1000 / T # - Pi = p # - gamma0_pi = 1 / Pi # - gammar_pi = 0 # - for i in range(0, 5): - gammar_pi = gammar_pi + nir[i] * Iir[i] * Pi ** (Iir[i] - 1) * tau ** Jir[i] - return R * T / p * Pi * (gamma0_pi + gammar_pi) / 1000 + tau = 1000 / T + Pi = p - @staticmethod - def u5_pT(p, T): + gamma0_pi = 1 / Pi + + gammar_pi = 0 + for I, J, n in zip(R7_97.Tablexx_I, R7_97.Tablexx_J, R7_97.Tablexx_n): + gammar_pi = gammar_pi + n * I * Pi ** (I - 1) * tau**J + + return _R * T / p * Pi * (gamma0_pi + gammar_pi) / 1000 + + @classmethod + def u5_pT(cls, p: float, T: float) -> float: """function u5_pT = u5_pT(p, T) Basic Equation for Region 5 Eq 32,33, Page 36, Tables 37-41 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: specific internal energy in [kJ / kg] """ - Ji0 = [0, 1, -3, -2, -1, 2] - ni0 = [ - -13.179983674201, - 6.8540841634434, - -0.024805148933466, - 0.36901534980333, - -3.1161318213925, - -0.32961626538917, - ] - Iir = [1, 1, 1, 2, 3] - Jir = [0, 1, 3, 9, 3] - nir = [ - -1.2563183589592e-04, - 2.1774678714571e-03, - -0.004594282089991, - -3.9724828359569e-06, - 1.2919228289784e-07, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ tau = 1000 / T Pi = p + gamma0_pi = 1 / Pi + gamma0_tau = 0 - for i in range(0, 6): - gamma0_tau = gamma0_tau + ni0[i] * Ji0[i] * tau ** (Ji0[i] - 1) + for J, n in zip(R7_97.Table37_J, R7_97.Table37_n): + gamma0_tau = gamma0_tau + n * J * tau ** (J - 1) + gammar_pi = 0 gammar_tau = 0 - for i in range(0, 5): - gammar_pi = gammar_pi + nir[i] * Iir[i] * Pi ** (Iir[i] - 1) * tau ** Jir[i] - gammar_tau = gammar_tau + nir[i] * Pi ** Iir[i] * Jir[i] * tau ** ( - Jir[i] - 1 - ) - return R * T * (tau * (gamma0_tau + gammar_tau) - Pi * (gamma0_pi + gammar_pi)) + for I, J, n in zip(R7_97.Tablexx_I, R7_97.Tablexx_J, R7_97.Tablexx_n): + gammar_pi = gammar_pi + n * I * Pi ** (I - 1) * tau**J + gammar_tau = gammar_tau + n * Pi**I * J * tau ** (J - 1) - @staticmethod - def Cp5_pT(p, T): + return _R * T * (tau * (gamma0_tau + gammar_tau) - Pi * (gamma0_pi + gammar_pi)) + + @classmethod + def Cp5_pT(cls, p: float, T: float) -> float: """function Cp5_pT = Cp5_pT(p, T) Basic Equation for Region 5 Eq 32,33, Page 36, Tables 37-41 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: specific isobaric heat capacity in [kJ / (kg K)] """ - Ji0 = [0, 1, -3, -2, -1, 2] - ni0 = [ - -13.179983674201, - 6.8540841634434, - -0.024805148933466, - 0.36901534980333, - -3.1161318213925, - -0.32961626538917, - ] - Iir = [1, 1, 1, 2, 3] - Jir = [0, 1, 3, 9, 3] - nir = [ - -1.2563183589592e-04, - 2.1774678714571e-03, - -0.004594282089991, - -3.9724828359569e-06, - 1.2919228289784e-07, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ tau = 1000 / T Pi = p + gamma0_tautau = 0 - for i in range(0, 6): - gamma0_tautau = gamma0_tautau + ni0[i] * Ji0[i] * (Ji0[i] - 1) * tau ** ( - Ji0[i] - 2 - ) + for J, n in zip(R7_97.Table37_J, R7_97.Table37_n): + gamma0_tautau = gamma0_tautau + n * J * (J - 1) * tau ** (J - 2) + gammar_tautau = 0 - for i in range(0, 5): - gammar_tautau = gammar_tautau + nir[i] * Pi ** Iir[i] * Jir[i] * ( - Jir[i] - 1 - ) * tau ** (Jir[i] - 2) - return -R * tau**2 * (gamma0_tautau + gammar_tautau) + for I, J, n in zip(R7_97.Tablexx_I, R7_97.Tablexx_J, R7_97.Tablexx_n): + gammar_tautau = gammar_tautau + n * Pi**I * J * (J - 1) * tau ** (J - 2) - @staticmethod - def s5_pT(p, T): + return -_R * tau**2 * (gamma0_tautau + gammar_tautau) + + @classmethod + def s5_pT(cls, p: float, T: float) -> float: """function s5_pT = s5_pT(p, T) Basic Equation for Region 5 Eq 32, 33, Page 36, Tables 37 - 41 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: specific entropy in [kJ / (kg K)] """ - Ji0 = [0, 1, -3, -2, -1, 2] - ni0 = [ - -13.179983674201, - 6.8540841634434, - -0.024805148933466, - 0.36901534980333, - -3.1161318213925, - -0.32961626538917, - ] - Iir = [1, 1, 1, 2, 3] - Jir = [0, 1, 3, 9, 3] - nir = [ - -1.2563183589592e-04, - 2.1774678714571e-03, - -0.004594282089991, - -3.9724828359569e-06, - 1.2919228289784e-07, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ tau = 1000 / T Pi = p + gamma0 = math.log(Pi) gamma0_tau = 0 - for i in range(0, 6): - gamma0_tau = gamma0_tau + ni0[i] * Ji0[i] * tau ** (Ji0[i] - 1) - gamma0 = gamma0 + ni0[i] * tau ** Ji0[i] + for J, n in zip(R7_97.Table37_J, R7_97.Table37_n): + gamma0 = gamma0 + n * tau**J + gamma0_tau = gamma0_tau + n * J * tau ** (J - 1) + gammar = 0 gammar_tau = 0 - for i in range(0, 5): - gammar = gammar + nir[i] * Pi ** Iir[i] * tau ** Jir[i] - gammar_tau = gammar_tau + nir[i] * Pi ** Iir[i] * Jir[i] * tau ** ( - Jir[i] - 1 - ) - return R * (tau * (gamma0_tau + gammar_tau) - (gamma0 + gammar)) + for I, J, n in zip(R7_97.Tablexx_I, R7_97.Tablexx_J, R7_97.Tablexx_n): + gammar = gammar + n * Pi**I * tau**J + gammar_tau = gammar_tau + n * Pi**I * J * tau ** (J - 1) - @staticmethod - def Cv5_pT(p, T): + return _R * (tau * (gamma0_tau + gammar_tau) - (gamma0 + gammar)) + + @classmethod + def Cv5_pT(cls, p: float, T: float) -> float: """function Cv5_pT = Cv5_pT(p, T) Basic Equation for Region 5 Eq 32, 33, Page 36, Tables 37 - 41 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: specific isochoric heat capacity in [kJ / (kg K)] """ - Ji0 = [0, 1, -3, -2, -1, 2] - ni0 = [ - -13.179983674201, - 6.8540841634434, - -0.024805148933466, - 0.36901534980333, - -3.1161318213925, - -0.32961626538917, - ] - Iir = [1, 1, 1, 2, 3] - Jir = [0, 1, 3, 9, 3] - nir = [ - -1.2563183589592e-04, - 2.1774678714571e-03, - -0.004594282089991, - -3.9724828359569e-06, - 1.2919228289784e-07, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ tau = 1000 / T Pi = p + gamma0_tautau = 0 - for i in range(0, 6): - gamma0_tautau = gamma0_tautau + ni0[i] * (Ji0[i] - 1) * Ji0[i] * tau ** ( - Ji0[i] - 2 - ) + for J, n in zip(R7_97.Table37_J, R7_97.Table37_n): + gamma0_tautau = gamma0_tautau + n * (J - 1) * J * tau ** (J - 2) + gammar_pi = 0 gammar_pitau = 0 gammar_pipi = 0 gammar_tautau = 0 - for i in range(0, 5): - gammar_pi = gammar_pi + nir[i] * Iir[i] * Pi ** (Iir[i] - 1) * tau ** Jir[i] - gammar_pitau = gammar_pitau + nir[i] * Iir[i] * Pi ** (Iir[i] - 1) * Jir[ - i - ] * tau ** (Jir[i] - 1) - gammar_pipi = ( - gammar_pipi - + nir[i] * Iir[i] * (Iir[i] - 1) * Pi ** (Iir[i] - 2) * tau ** Jir[i] - ) - gammar_tautau = gammar_tautau + nir[i] * Pi ** Iir[i] * Jir[i] * ( - Jir[i] - 1 - ) * tau ** (Jir[i] - 2) - return R * ( - -(tau**2 * (gamma0_tautau + gammar_tautau)) - - (1 + Pi * gammar_pi - tau * Pi * gammar_pitau) ** 2 - / (1 - Pi**2 * gammar_pipi) + for I, J, n in zip(R7_97.Tablexx_I, R7_97.Tablexx_J, R7_97.Tablexx_n): + gammar_pi = gammar_pi + n * I * Pi ** (I - 1) * tau**J + gammar_pitau = gammar_pitau + n * I * Pi ** (I - 1) * J * tau ** (J - 1) + gammar_pipi = gammar_pipi + n * I * (I - 1) * Pi ** (I - 2) * tau**J + gammar_tautau = gammar_tautau + n * Pi**I * J * (J - 1) * tau ** (J - 2) + + return _R * ( + -(tau**2 * (gamma0_tautau + gammar_tautau)) - (1 + Pi * gammar_pi - tau * Pi * gammar_pitau) ** 2 / (1 - Pi**2 * gammar_pipi) ) - @staticmethod - def w5_pT(p, T): + @classmethod + def w5_pT(cls, p: float, T: float) -> float: """function w5_pT = w5_pT(p, T) Basic Equation for Region 5 Eq 32, 33, Page 36, Tables 37 - 41 + + :param p: preasure in [MPa] + :param T: temperature in [K] + + :return: speed of sound in [m / s] """ - Ji0 = [0, 1, -3, -2, -1, 2] - ni0 = [ - -13.179983674201, - 6.8540841634434, - -0.024805148933466, - 0.36901534980333, - -3.1161318213925, - -0.32961626538917, - ] - Iir = [1, 1, 1, 2, 3] - Jir = [0, 1, 3, 9, 3] - nir = [ - -1.2563183589592e-04, - 2.1774678714571e-03, - -0.004594282089991, - -3.9724828359569e-06, - 1.2919228289784e-07, - ] - R = Constants.__SPECIFIC_GAS_CONSTANT__ tau = 1000 / T Pi = p + gamma0_tautau = 0 - for i in range(0, 6): - gamma0_tautau = gamma0_tautau + ni0[i] * (Ji0[i] - 1) * Ji0[i] * tau ** ( - Ji0[i] - 2 - ) + for J, n in zip(R7_97.Table37_J, R7_97.Table37_n): + gamma0_tautau = gamma0_tautau + n * (J - 1) * J * tau ** (J - 2) + gammar_pi = 0 gammar_pitau = 0 gammar_pipi = 0 gammar_tautau = 0 - for i in range(0, 5): - gammar_pi = gammar_pi + nir[i] * Iir[i] * Pi ** (Iir[i] - 1) * tau ** Jir[i] - gammar_pitau = gammar_pitau + nir[i] * Iir[i] * Pi ** (Iir[i] - 1) * Jir[ - i - ] * tau ** (Jir[i] - 1) - gammar_pipi = ( - gammar_pipi - + nir[i] * Iir[i] * (Iir[i] - 1) * Pi ** (Iir[i] - 2) * tau ** Jir[i] - ) - gammar_tautau = gammar_tautau + nir[i] * Pi ** Iir[i] * Jir[i] * ( - Jir[i] - 1 - ) * tau ** (Jir[i] - 2) + for I, J, n in zip(R7_97.Tablexx_I, R7_97.Tablexx_J, R7_97.Tablexx_n): + gammar_pi = gammar_pi + n * I * Pi ** (I - 1) * tau**J + gammar_pitau = gammar_pitau + n * I * Pi ** (I - 1) * J * tau ** (J - 1) + gammar_pipi = gammar_pipi + n * I * (I - 1) * Pi ** (I - 2) * tau**J + gammar_tautau = gammar_tautau + n * Pi**I * J * (J - 1) * tau ** (J - 2) + return ( 1000 - * R + * _R * T * (1 + 2 * Pi * gammar_pi + Pi**2 * gammar_pi**2) - / ( - (1 - Pi**2 * gammar_pipi) - + (1 + Pi * gammar_pi - tau * Pi * gammar_pitau) ** 2 - / (tau**2 * (gamma0_tautau + gammar_tautau)) - ) + / ((1 - Pi**2 * gammar_pipi) + (1 + Pi * gammar_pi - tau * Pi * gammar_pitau) ** 2 / (tau**2 * (gamma0_tautau + gammar_tautau))) ) ** 0.5 - @staticmethod - def T5_ph(p, h): + @classmethod + def T5_ph(cls, p: float, h: float) -> float: """function T5_ph = T5_ph(p, h) Solve with half interval method + + :param p: preasure in [MPa] + :param h: enthalpy in [kJ / kg] + + :return: temperature in [K] """ - logger = logging.getLogger("pyXSteam") + Ts = float("NaN") Low_Bound = 1073.15 High_Bound = 2273.15 hs = h - 1 @@ -6720,7 +1981,7 @@ def T5_ph(p, h): hs = Region5.h5_pT(p, Ts) if last_hs == hs: - logger.warning( + cls._logger.warning( "T5_ph stopped iterating after %d steps because values did not converge", step_counter, ) @@ -6732,13 +1993,18 @@ def T5_ph(p, h): Low_Bound = Ts return Ts - @staticmethod - def T5_ps(p, s): + @classmethod + def T5_ps(cls, p: float, s: float) -> float: """function T5_ps = T5_ps(p, s) Solve with half interval method + + :param p: preasure in [MPa] + :param s: specific entropy in [kJ / (kg K)] + + :return: temperature in [K] """ - logger = logging.getLogger("pyXSteam") + Ts = float("NaN") Low_Bound = 1073.15 High_Bound = 2273.15 ss = s - 1 @@ -6751,7 +2017,7 @@ def T5_ps(p, s): ss = Region5.s5_pT(p, Ts) if last_ss == ss: - logger.warning( + cls._logger.warning( "T5_ps stopped iterating after %d steps because values did not converge", step_counter, ) @@ -6763,13 +2029,19 @@ def T5_ps(p, s): Low_Bound = Ts return Ts - @staticmethod - def T5_prho(p, rho): + @classmethod + def T5_prho(cls, p: float, rho: float) -> float: """function T5_prho = T5_prho(p, rho) - Solve by iteration. Observe that for low temperatures this equation has 2 solutions. Solve with half interval method + Solve by iteration. Observe that for low temperatures this equation has + 2 solutions. Solve with half interval method + + :param p: preasure in [MPa] + :param rho: density in [kg / m³] + + :return: temperature in [K] """ - logger = logging.getLogger("pyXSteam") + Ts = float("NaN") Low_Bound = 1073.15 High_Bound = 2073.15 rhos = -1000 @@ -6782,7 +2054,7 @@ def T5_prho(p, rho): rhos = 1 / Region2.v2_pT(p, Ts) if last_rhos == rhos: - logger.warning( + cls._logger.warning( "T5_prho stopped iterating after %d steps because values did not converge", step_counter, ) diff --git a/pyXSteam/Tables.py b/pyXSteam/Tables.py new file mode 100644 index 0000000..a5e8c73 --- /dev/null +++ b/pyXSteam/Tables.py @@ -0,0 +1,2396 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Content of the Tables from related documents + +Sources: + +* IAPWS R7-97(2012) IAPWS Industrial formulation 1997 for the Thermodynamic +Properties of Water and Steam, September 1997 + +* IAPWS SR1-86(1992) Revised Supplementary Release on Satutation Properties of +Ordinary Water Substances + +* IAPWS SR2-01(2014) Revised Supplementary Release on Backward Equations for +Pressure as a Function of Enthalpy and Entropy p(h,s) for Regions 1 and 2 of +the IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of +Water and Steam + +* IAPWS SR3-03(2014) Revised Supplementary Release on Backward Equations for +the Functions T(p,h), v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS Industrial +Formulation 1997 for the Thermodynamic Properties of Water and Steam + +* IAPWS SR4-04(2014) Revised Supplementary Release on Backward Equations p(h,s) +for Region 3, Equations as a Function of h and s for the Region Boundaries, and +an Equation Tsat(h,s) for Region 4 of the IAPWS Industrial Formulation 1997 for +the Thermodynamic Properties of Water and Steam + + +""" + + +# Region 1 +class R7_97: + """class with table data from IAPWS R7-97(2012)""" + + # Table 1: Numerical values of the coefficients of the B23-equation, Eqs. (5) and (6), for defining the boundary between regions 2 and 3 + Table1_n = [0.34805185628969e3, -0.11671859879975e1, 0.10192970039326e-2, 0.57254459862746e3, 0.13918839778870e2] + + # Table 2: Numerical values of the coefficients and exponents of the dimensionless Gibbs free energy for region 1, Eq. (7) + Table2_I = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 8, 8, 21, 23, 29, 30, 31, 32] + Table2_J = [ + -2, + -1, + 0, + 1, + 2, + 3, + 4, + 5, + -9, + -7, + -1, + 0, + 1, + 3, + -3, + 0, + 1, + 3, + 17, + -4, + 0, + 6, + -5, + -2, + 10, + -8, + -11, + -6, + -29, + -31, + -38, + -39, + -40, + -41, + ] + Table2_n = [ + +0.14632971213167, + -0.84548187169114, + -0.37563603672040e1, + +0.33855169168385e1, + -0.95791963387872, + +0.15772038513228, + -0.16616417199501e-1, + +0.81214629983568e-3, + +0.28319080123804e-3, + -0.60706301565874e-3, + -0.18990068218419e-1, + -0.32529748770505e-1, + -0.21841717175414e-1, + -0.52838357969930e-4, + -0.47184321073267e-3, + -0.30001780793026e-3, + +0.47661393906987e-4, + -0.44141845330846e-5, + -0.72694996297594e-15, + -0.31679644845054e-4, + -0.28270797985312e-5, + -0.85205128120103e-9, + -0.22425281908000e-5, + -0.65171222895601e-6, + -0.14341729937924e-12, + -0.40516996860117e-6, + -0.12734301741641e-8, + -0.17424871230634e-9, + -0.68762131295531e-18, + +0.14478307828521e-19, + +0.26335781662795e-22, + -0.11947622640071e-22, + +0.18228094581404e-23, + -0.93537087292458e-25, + ] + + # Table 6: Numerical values of the coefficients and exponents of the backward equation T ( p,h ) for region 1, Eq. (11) + Table6_I = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5, 6] + Table6_J = [0, 1, 2, 6, 22, 32, 0, 1, 2, 3, 4, 10, 32, 10, 32, 10, 32, 32, 32, 32] + Table6_n = [ + -0.23872489924521e3, + +0.40421188637945e3, + +0.11349746881718e3, + -0.58457616048039e1, + -0.15285482413140e-3, + -0.10866707695377e-5, + -0.13391744872602e2, + +0.43211039183559e2, + -0.54010067170506e2, + +0.30535892203916e2, + -0.65964749423638e1, + +0.93965400878363e-2, + +0.11573647505340e-6, + -0.25858641282073e-4, + -0.40644363084799e-8, + +0.66456186191635e-7, + +0.80670734103027e-10, + -0.93477771213947e-12, + +0.58265442020601e-14, + -0.15020185953503e-16, + ] + + # Table 8: Numerical values of the coefficients and exponents of the backward equation T ( p,s ) for region 1, Eq. (13) + Table8_I = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 4] + Table8_J = [0, 1, 2, 3, 11, 31, 0, 1, 2, 3, 12, 31, 0, 1, 2, 9, 31, 10, 32, 32] + Table8_n = [ + +0.17478268058307e3, + +0.34806930892873e2, + +0.65292584978455e1, + +0.33039981775489, + -0.19281382923196e-6, + -0.24909197244573e-22, + -0.26107636489332, + +0.22592965981586, + -0.64256463395226e-1, + +0.78876289270526e-2, + +0.35672110607366e-9, + +0.17332496994895e-23, + +0.56608900654837e-3, + -0.32635483139717e-3, + +0.44778286690632e-4, + -0.51322156908507e-9, + -0.42522657042207e-25, + +0.26400441360689e-12, + +0.78124600459723e-28, + -0.30732199903668e-30, + ] + + # Region2 + # Table 10. Numerical values of the coefficients and exponents of the ideal-gas part gamma o of the dimensionless Gibbs free energy for region 2, Eq. (16)a + Table10_J0 = [0, 1, -5, -4, -3, -2, -1, 2, 3] + Table10_n0_a = [ + -0.96927686500217e1, # 1a + +0.10086655968018e2, # 2a + -0.56087911283020e-2, + +0.71452738081455e-1, + -0.40710498223928, + +0.14240819171444e1, + -0.43839511319450e1, + -0.28408632460772, + +0.21268463753307e-1, + ] + # Numerical values of the coefficients and exponents of the ideal-gas part gamma o of the dimensionless Gibbs free energy for metastable region 2, Eq. (18) + Table10_n0_b = [ + -0.96937268393049e1, # 1b + +0.10087275970006e2, # 2b + -0.56087911283020e-2, + +0.71452738081455e-1, + -0.40710498223928, + +0.14240819171444e1, + -0.43839511319450e1, + -0.28408632460772, + +0.21268463753307e-1, + ] + + # Table 11: Numerical values of the coefficients and exponents of the residual part gamma r of + # the dimensionless Gibbs free energy for region 2, Eq. (17) + Table11_I = [ + 1, + 1, + 1, + 1, + 1, + 2, + 2, + 2, + 2, + 2, + 3, + 3, + 3, + 3, + 3, + 4, + 4, + 4, + 5, + 6, + 6, + 6, + 7, + 7, + 7, + 8, + 8, + 9, + 10, + 10, + 10, + 16, + 16, + 18, + 20, + 20, + 20, + 21, + 22, + 23, + 24, + 24, + 24, + ] + Table11_J = [ + 0, + 1, + 2, + 3, + 6, + 1, + 2, + 4, + 7, + 36, + 0, + 1, + 3, + 6, + 35, + 1, + 2, + 3, + 7, + 3, + 16, + 35, + 0, + 11, + 25, + 8, + 36, + 13, + 4, + 10, + 14, + 29, + 50, + 57, + 20, + 35, + 48, + 21, + 53, + 39, + 26, + 40, + 58, + ] + Table11_n = [ + -0.17731742473213e-2, + -0.17834862292358e-1, + -0.45996013696365e-1, + -0.57581259083432e-1, + -0.50325278727930e-1, + -0.33032641670203e-4, + -0.18948987516315e-3, + -0.39392777243355e-2, + -0.43797295650573e-1, + -0.26674547914087e-4, + +0.20481737692309e-7, + +0.43870667284435e-6, + -0.32277677238570e-4, + -0.15033924542148e-2, + -0.40668253562649e-1, + -0.78847309559367e-9, + +0.12790717852285e-7, + +0.48225372718507e-6, + +0.22922076337661e-5, + -0.16714766451061e-10, + -0.21171472321355e-2, + -0.23895741934104e2, + -0.59059564324270e-17, + -0.12621808899101e-5, + -0.38946842435739e-1, + +0.11256211360459e-10, + -0.82311340897998e1, + +0.19809712802088e-7, + +0.10406965210174e-18, + -0.10234747095929e-12, + -0.10018179379511e-8, + -0.80882908646985e-10, + +0.10693031879409, + -0.33662250574171, + +0.89185845355421e-24, + +0.30629316876232e-12, + -0.42002467698208e-5, + -0.59056029685639e-25, + +0.37826947613457e-5, + -0.12768608934681e-14, + +0.73087610595061e-28, + +0.55414715350778e-16, + -0.94369707241210e-6, + ] + + # Table 16: Numerical values of the coefficients and exponents of the residual part gamma r of + # the dimensionless Gibbs free energy for the metastable-vapor region, Eq. (19) + Table16_I = [1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5] + Table16_J = [0, 2, 5, 11, 1, 7, 16, 4, 16, 7, 10, 9, 10] + Table16_n = [ + -0.73362260186506e-2, + -0.88223831943146e-1, + -0.72334555213245e-1, + -0.40813178534455e-2, + +0.20097803380207e-2, + -0.53045921898642e-1, + -0.76190409086970e-2, + -0.63498037657313e-2, + -0.86043093028588e-1, + +0.75321581522770e-2, + -0.79238375446139e-2, + -0.22888160778447e-3, + -0.26456501482810e-2, + ] + + # Table 19: Numerical values of the coefficients of the B2bc-equation, Eqs. (20) and (21), for + # defining the boundary between subregions 2b and 2c with respect to T( p,h ) calculations + Table19_n = [ + +0.90584278514723e3, + -0.67955786399241, + +0.12809002730136e-3, + +0.26526571908428e4, + +0.45257578905948e1, + ] + + # Table 20: Numerical values of the coefficients and exponents of the backward + # equation T ( p,h ) for subregion 2a, Eq. (22) + Table20_I = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7] + Table20_J = [0, 1, 2, 3, 7, 20, 0, 1, 2, 3, 7, 9, 11, 18, 44, 0, 2, 7, 36, 38, 40, 42, 44, 24, 44, 12, 32, 44, 32, 36, 42, 34, 44, 28] + Table20_n = [ + +0.10898952318288e4, + +0.84951654495535e3, + -0.10781748091826e3, + +0.33153654801263e2, + -0.74232016790248e1, + +0.11765048724356e2, + +0.18445749355790e1, + -0.41792700549624e1, + +0.62478196935812e1, + -0.17344563108114e2, + -0.20058176862096e3, + +0.27196065473796e3, + -0.45511318285818e3, + +0.30919688604755e4, + +0.25226640357872e6, + -0.61707422868339e-2, + -0.31078046629583, + +0.11670873077107e2, + +0.12812798404046e9, + -0.98554909623276e9, + +0.28224546973002e10, + -0.35948971410703e10, + +0.17227349913197e10, + -0.13551334240775e5, + +0.12848734664650e8, + +0.13865724283226e1, + +0.23598832556514e6, + -0.13105236545054e8, + +0.73999835474766e4, + -0.55196697030060e6, + +0.37154085996233e7, + +0.19127729239660e5, + -0.41535164835634e6, + -0.62459855192507e2, + ] + + # Table 21: Numerical values of the coefficients and exponents of the backward equation T ( p,h ) for subregion 2b, Eq. (23) + Table21_I = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 6, 7, 7, 9, 9] + Table21_J = [ + 0, + 1, + 2, + 12, + 18, + 24, + 28, + 40, + 0, + 2, + 6, + 12, + 18, + 24, + 28, + 40, + 2, + 8, + 18, + 40, + 1, + 2, + 12, + 24, + 2, + 12, + 18, + 24, + 28, + 40, + 18, + 24, + 40, + 28, + 2, + 28, + 1, + 40, + ] + Table21_n = [ + +0.14895041079516e4, + +0.74307798314034e3, + -0.97708318797837e2, + +0.24742464705674e1, + -0.63281320016026, + +0.11385952129658e1, + -0.47811863648625, + +0.85208123431544e-2, + +0.93747147377932, + +0.33593118604916e1, + +0.33809355601454e1, + +0.16844539671904, + +0.73875745236695, + -0.47128737436186, + +0.15020273139707, + -0.21764114219750e-2, + -0.21810755324761e-1, + -0.10829784403677, + -0.46333324635812e-1, + +0.71280351959551e-4, + +0.11032831789999e-3, + +0.18955248387902e-3, + +0.30891541160537e-2, + +0.13555504554949e-2, + +0.28640237477456e-6, + -0.10779857357512e-4, + -0.76462712454814e-4, + +0.14052392818316e-4, + -0.31083814331434e-4, + -0.10302738212103e-5, + +0.28217281635040e-6, + +0.12704902271945e-5, + +0.73803353468292e-7, + -0.11030139238909e-7, + -0.81456365207833e-13, + -0.25180545682962e-10, + -0.17565233969407e-17, + +0.86934156344163e-14, + ] + + # Table 22: Numerical values of the coefficients and exponents of the backward equation T ( p,h ) for subregion 2c, Eq. (24) + Table22_I = [-7, -7, -6, -6, -5, -5, -2, -2, -1, -1, 0, 0, 1, 1, 2, 6, 6, 6, 6, 6, 6, 6, 6] + Table22_J = [0, 4, 0, 2, 0, 2, 0, 1, 0, 2, 0, 1, 4, 8, 4, 0, 1, 4, 10, 12, 16, 20, 22] + Table22_n = [ + -0.32368398555242e13, + +0.73263350902181e13, + +0.35825089945447e12, + -0.58340131851590e12, + -0.10783068217470e11, + +0.20825544563171e11, + +0.61074783564516e6, + +0.85977722535580e6, + -0.25745723604170e5, + +0.31081088422714e5, + +0.12082315865936e4, + +0.48219755109255e3, + +0.37966001272486e1, + -0.10842984880077e2, + -0.45364172676660e-1, + +0.14559115658698e-12, + +0.11261597407230e-11, + -0.17804982240686e-10, + +0.12324579690832e-6, + -0.11606921130984e-5, + +0.27846367088554e-4, + -0.59270038474176e-3, + +0.12918582991878e-2, + ] + + # Table 25: Numerical values of the coefficients and exponents of the backward equation T( p,s ) for subregion 2a, Eq. (25) + Table25_I = [ + -1.5, + -1.5, + -1.5, + -1.5, + -1.5, + -1.5, + -1.25, + -1.25, + -1.25, + -1, + -1, + -1, + -1, + -1, + -1, + -0.75, + -0.75, + -0.5, + -0.5, + -0.5, + -0.5, + -0.25, + -0.25, + -0.25, + -0.25, + 0.25, + 0.25, + 0.25, + 0.25, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.75, + 0.75, + 0.75, + 0.75, + 1, + 1, + 1.25, + 1.25, + 1.5, + 1.5, + ] + Table25_J = [ + -24, + -23, + -19, + -13, + -11, + -10, + -19, + -15, + -6, + -26, + -21, + -17, + -16, + -9, + -8, + -15, + -14, + -26, + -13, + -9, + -7, + -27, + -25, + -11, + -6, + 1, + 4, + 8, + 11, + 0, + 1, + 5, + 6, + 10, + 14, + 16, + 0, + 4, + 9, + 17, + 7, + 18, + 3, + 15, + 5, + 18, + ] + Table25_n = [ + -0.39235983861984e6, + +0.51526573827270e6, + +0.40482443161048e5, + -0.32193790923902e3, + +0.96961424218694e2, + -0.22867846371773e2, + -0.44942914124357e6, + -0.50118336020166e4, + +0.35684463560015, + +0.44235335848190e5, + -0.13673388811708e5, + +0.42163260207864e6, + +0.22516925837475e5, + +0.47442144865646e3, + -0.14931130797647e3, + -0.19781126320452e6, + -0.23554399470760e5, + -0.19070616302076e5, + +0.55375669883164e5, + +0.38293691437363e4, + -0.60391860580567e3, + +0.19363102620331e4, + +0.42660643698610e4, + -0.59780638872718e4, + -0.70401463926862e3, + +0.33836784107553e3, + +0.20862786635187e2, + +0.33834172656196e-1, + -0.43124428414893e-4, + +0.16653791356412e3, + -0.13986292055898e3, + -0.78849547999872, + +0.72132411753872e-1, + -0.59754839398283e-2, + -0.12141358953904e-4, + +0.23227096733871e-6, + -0.10538463566194e2, + +0.20718925496502e1, + -0.72193155260427e-1, + +0.20749887081120e-6, + -0.18340657911379e-1, + +0.29036272348696e-6, + +0.21037527893619, + +0.25681239729999e-3, + -0.12799002933781e-1, + -0.82198102652018e-5, + ] + + # Table 26: Numerical values of the coefficients and exponents of the backward equation T( p,s ) for subregion 2b, Eq. (26) + Table26_I = [ + -6, + -6, + -5, + -5, + -4, + -4, + -4, + -3, + -3, + -3, + -3, + -2, + -2, + -2, + -2, + -1, + -1, + -1, + -1, + -1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 2, + 2, + 2, + 3, + 3, + 3, + 4, + 4, + 5, + 5, + 5, + ] + Table26_J = [ + 0, + 11, + 0, + 11, + 0, + 1, + 11, + 0, + 1, + 11, + 12, + 0, + 1, + 6, + 10, + 0, + 1, + 5, + 8, + 9, + 0, + 1, + 2, + 4, + 5, + 6, + 9, + 0, + 1, + 2, + 3, + 7, + 8, + 0, + 1, + 5, + 0, + 1, + 3, + 0, + 1, + 0, + 1, + 2, + ] + Table26_n = [ + +0.31687665083497e6, + +0.20864175881858e2, + -0.39859399803599e6, + -0.21816058518877e2, + +0.22369785194242e6, + -0.27841703445817e4, + +0.99207436071480e1, + -0.75197512299157e5, + +0.29708605951158e4, + -0.34406878548526e1, + +0.38815564249115, + +0.17511295085750e5, + -0.14237112854449e4, + +0.10943803364167e1, + +0.89971619308495, + -0.33759740098958e4, + +0.47162885818355e3, + -0.19188241993679e1, + +0.41078580492196, + -0.33465378172097, + +0.13870034777505e4, + -0.40663326195838e3, + +0.41727347159610e2, + +0.21932549434532e1, + -0.10320050009077e1, + +0.35882943516703, + +0.52511453726066e-2, + +0.12838916450705e2, + -0.28642437219381e1, + +0.56912683664855, + -0.99962954584931e-1, + -0.32632037778459e-2, + +0.23320922576723e-3, + -0.15334809857450, + +0.29072288239902e-1, + +0.37534702741167e-3, + +0.17296691702411e-2, + -0.38556050844504e-3, + -0.35017712292608e-4, + -0.14566393631492e-4, + +0.56420857267269e-5, + +0.41286150074605e-7, + -0.20684671118824e-7, + +0.16409393674725e-8, + ] + + # Table 27: Numerical values of the coefficient s and exponents of the backward equation T( p,s ) for subregion 2c, Eq. (27) + Table27_I = [-2, -2, -1, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 7, 7] + Table27_J = [0, 1, 0, 0, 1, 2, 3, 0, 1, 3, 4, 0, 1, 2, 0, 1, 5, 0, 1, 4, 0, 1, 2, 0, 1, 0, 1, 3, 4, 5] + Table27_n = [ + +0.90968501005365e3, + +0.24045667088420e4, + -0.59162326387130e3, + +0.54145404128074e3, + -0.27098308411192e3, + +0.97976525097926e3, + -0.46966772959435e3, + +0.14399274604723e2, + -0.19104204230429e2, + +0.53299167111971e1, + -0.21252975375934e2, + -0.31147334413760, + +0.60334840894623, + -0.42764839702509e-1, + +0.58185597255259e-2, + -0.14597008284753e-1, + +0.56631175631027e-2, + -0.76155864584577e-4, + +0.22440342919332e-3, + -0.12561095013413e-4, + +0.63323132660934e-6, + -0.20541989675375e-5, + +0.36405370390082e-7, + -0.29759897789215e-8, + +0.10136618529763e-7, + +0.59925719692351e-11, + -0.20677870105164e-10, + -0.20874278181886e-10, + +0.10162166825089e-9, + -0.16429828281347e-9, + ] + + # Region3 + + # Table 30: Numerical values of the coefficients and exponents of the dimensionless Helmholtz free energy for region 3, Eq. (28) + # TODO: check calculations for skip on index 0 + Table30_I = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 8, 9, 9, 10, 10, 11] + Table30_J = [ + 0, + 0, + 1, + 2, + 7, + 10, + 12, + 23, + 2, + 6, + 15, + 17, + 0, + 2, + 6, + 7, + 22, + 26, + 0, + 2, + 4, + 16, + 26, + 0, + 2, + 4, + 26, + 1, + 3, + 26, + 0, + 2, + 26, + 2, + 26, + 2, + 26, + 0, + 1, + 26, + ] + Table30_n = [ + +0.10658070028513e1, + -0.15732845290239e2, + +0.20944396974307e2, + -0.76867707878716e1, + +0.26185947787954e1, + -0.28080781148620e1, + +0.12053369696517e1, + -0.84566812812502e-2, + -0.12654315477714e1, + -0.11524407806681e1, + +0.88521043984318, + -0.64207765181607, + +0.38493460186671, + -0.85214708824206, + +0.48972281541877e1, + -0.30502617256965e1, + +0.39420536879154e-1, + +0.12558408424308, + -0.27999329698710, + +0.13899799569460e1, + -0.20189915023570e1, + -0.82147637173963e-2, + -0.47596035734923, + +0.43984074473500e-1, + -0.44476435428739, + +0.90572070719733, + +0.70522450087967, + +0.10770512626332, + -0.32913623258954, + -0.50871062041158, + -0.22175400873096e-1, + +0.94260751665092e-1, + +0.16436278447961, + -0.13503372241348e-1, + -0.14834345352472e-1, + +0.57922953628084e-3, + +0.32308904703711e-2, + +0.80964802996215e-4, + -0.16557679795037e-3, + -0.44923899061815e-4, + ] + + # Region4 + + # Table 34: Numerical values of the coefficients of the dimensionless saturation equations, Eqs. (29) to (31) + Table34_n = [ + +0.11670521452767e4, + -0.72421316703206e6, + -0.17073846940092e2, + +0.12020824702470e5, + -0.32325550322333e7, + +0.14915108613530e2, + -0.48232657361591e4, + +0.40511340542057e6, + -0.23855557567849, + +0.65017534844798e3, + ] + + # Region5 + + # Table 37: Numerical values of the coefficients and exponents of the ideal-gas part gamma o of the dimensionless Gibbs free energy for region 5, Eq. (33) + Table37_J = [0, 1, -3, -2, -1, 2] + Table37_J = [0, 1, -3, -2, -1, 2] + Table37_n = [-0.13179983674201e2, +0.68540841634434e1, -0.24805148933466e-1, +0.36901534980333, -0.31161318213925e1, -0.329616265389177] + + # Table 38: Numerical values of the coefficients and exponents of the residual part gamma r of the dimensionless Gibbs free energy for region 5, Eq. (34) + Table38_I = [1, 1, 1, 2, 2, 3] + Table38_J = [1, 2, 3, 3, 9, 8] + Table38_n = [ + +0.15736404855259e-2, + +0.90153761673944e-3, + -0.50270077677648e-3, + +0.22440037409485e-5, + -0.41163275453471e-5, + +0.37919454822955e-7, + ] + + # ????????? + # TODO find source + Tablexx_I = [1, 1, 1, 2, 3] + Tablexx_J = [0, 1, 3, 9, 3] + Tablexx_n = [ + -1.2563183589592e-04, + 2.1774678714571e-03, + -0.004594282089991, + -3.9724828359569e-06, + 1.2919228289784e-07, + ] + + +class SR1_86: + """class with table data from IAPWS SR1-86(1992)""" + + # coefficients for Eq 1: Vapour pressure + a = [-7.85951783, 1.84408259, -11.7866497, 22.6807411, -15.9618719, 1.80122502] + + # coefficients for Eq 2: density of saturated liquid + b = [1.99274064, 1.09965342, -0.510839303, -1.75493479, -45.5170352, -6.74694450e5] + + # coefficients for Eq 3: density of saturated vapour + c = [-2.03150240, -2.68302940, -5.38626492, -17.2991605, -44.7586581, -63.9201063] + + # coefficients for Eq 4 and 5: auxiliary equations + d = [-5.65134998e-8, 2690.66631, 127.287297, -135.003439, 0.981825814] + d_alpha = -1135.905627715 + d_phi = 2319.5246 + + h_dash_t = 0.611786 # specific enthalpy of the liquid at the triple point in J / kg + + +class SR2_01: + """class with table data from IAPWS SR2-01(2014)""" + + # Table 2: Coefficients and exponents of the backward equation p_1(h,s) for region 1 in its dimensionless form, Eq. (1) + Table2_I = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 4, 4, 5] + Table2_J = [0, 1, 2, 4, 5, 6, 8, 14, 0, 1, 4, 6, 0, 1, 10, 4, 1, 4, 0] + Table2_n = [ + -0.691997014660582, + -0.183612548787560e2, + -0.928332409297335e1, + +0.659639569909906e2, + -0.162060388912024e2, + +0.450620017338667e3, + +0.854680678224170e3, + +0.607523214001162e4, + +0.326487682621856e2, + -0.269408844582931e2, + -0.319947848334300e3, + -0.928354307043320e3, + +0.303634537455249e2, + -0.650540422444146e2, + -0.430991316516130e4, + -0.747512324096068e3, + +0.730000345529245e3, + +0.114284032569021e4, + -0.436407041874559e3, + ] + + # Table 5: Numerical values of the coefficients of the equation h2ab(s) in its dimensionless form, Eq. (2), for defining the boundary between subregions 2a and 2b + Table5_n = [-0.349898083432139e4, +0.257560716905876e4, -0.421073558227969e3, +0.276349063799944e2] + + # Table 6: Coefficients and exponents of the backward equation p_2a(h,s) for subregion 2a in its dimensionless form, Eq. (3) + Table6_I = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 5, 5, 6, 7] + Table6_J = [1, 3, 6, 16, 20, 22, 0, 1, 2, 3, 5, 6, 10, 16, 20, 22, 3, 16, 20, 0, 2, 3, 6, 16, 16, 3, 16, 3, 1] + Table6_n = [ + -0.182575361923032e-1, + -0.125229548799536, + +0.592290437320145, + +0.604769706185122e1, + +0.238624965444474e3, + -0.298639090222922e3, + +0.512250813040750e-1, + -0.437266515606486, + +0.413336902999504, + -0.516468254574773e1, + -0.557014838445711e1, + +0.128555037824478e2, + +0.114144108953290e2, + -0.119504225652714e3, + -0.284777985961560e4, + +0.431757846408006e4, + +0.112894040802650e1, + +0.197409186206319e4, + +0.151612444706087e4, + +0.141324451421235e-1, + +0.585501282219601, + -0.297258075863012e1, + +0.594567314847319e1, + -0.623656565798905e4, + +0.965986235133332e4, + +0.681500934948134e1, + -0.633207286824489e4, + -0.558919224465760e1, + +0.400645798472063e-1, + ] + + # Table 7: Coefficients and exponents of the backward equation p_2b(h,s) for subregion 2b in its dimensionless form, Eq. (4) + Table7_I = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 8, 8, 12, 14] + Table7_J = [0, 1, 2, 4, 8, 0, 1, 2, 3, 5, 12, 1, 6, 18, 0, 1, 7, 12, 1, 16, 1, 12, 1, 8, 18, 1, 16, 1, 3, 14, 18, 10, 16] + Table7_n = [ + +0.801496989929495e-1, + -0.543862807146111, + +0.337455597421283, + +0.890555451157450e1, + +0.313840736431485e3, + +0.797367065977789, + -0.121616973556240e1, + +0.872803386937477e1, + -0.169769781757602e2, + -0.186552827328416e3, + +0.951159274344237e5, + -0.189168510120494e2, + -0.433407037194840e4, + +0.543212633012715e9, + +0.144793408386013, + +0.128024559637516e3, + -0.672309534071268e5, + +0.336972380095287e8, + -0.586634196762720e3, + -0.221403224769889e11, + +0.171606668708389e4, + -0.570817595806302e9, + -0.312109693178482e4, + -0.207841384633010e7, + +0.305605946157786e13, + +0.322157004314333e4, + +0.326810259797295e12, + -0.144104158934487e4, + +0.410694867802691e3, + +0.109077066873024e12, + -0.247964654258893e14, + +0.188801906865134e10, + -0.123651009018773e15, + ] + + # Table 8. Coefficients and exponents of the backward equation p_2c(h,s) for subregion 2c in its dimensionless form, Eq. (5) + Table8_I = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 6, 6, 10, 12, 16] + Table8_J = [0, 1, 2, 3, 4, 8, 0, 2, 5, 8, 14, 2, 3, 7, 10, 18, 0, 5, 8, 16, 18, 18, 1, 4, 6, 14, 8, 18, 7, 7, 10] + Table8_n = [ + +0.112225607199012, + -0.339005953606712e1, + -0.320503911730094e2, + -0.197597305104900e3, + -0.407693861553446e3, + +0.132943775222331e5, + +0.170846839774007e1, + +0.373694198142245e2, + +0.358144365815434e4, + +0.423014446424664e6, + -0.751071025760063e9, + +0.523446127607898e2, + -0.228351290812417e3, + -0.960652417056937e6, + -0.807059292526074e8, + +0.162698017225669e13, + +0.772465073604171, + +0.463929973837746e5, + -0.137317885134128e8, + +0.170470392630512e13, + -0.251104628187308e14, + +0.317748830835520e14, + +0.538685623675312e2, + -0.553089094625169e5, + -0.102861522421405e7, + +0.204249418756234e13, + +0.273918446626977e9, + -0.263963146312685e16, + -0.107890854108088e10, + -0.296492620980124e11, + -0.111754907323424e16, + ] + + +class SR3_03: + """class with table data from IAPWS SR3-03(2014)""" + + s_c = 4.41202148223476 # kJ / kg K + h_dash = 1.670858218e3 # kJ / kg @ 623,15K + h_doubledash = 2.563592004e3 # kJ / kg @ 623,15K + s_dash = 3.778281340 # kJ / kg K @ 623,15K + s_doubledash = 5.210887825 # kJ / kg K @ 623,15K + + # Table 2: Numerical values of the coefficients of the equation h_3ab(p) in its dimensionless form, Eq. (1), for defining the boundary between subregions 3a and 3b + Table2_n = [ + +0.201464004206875e4, + +0.374696550136983e1, + -0.219921901054187e-1, + +0.875131686009950e-4, + ] + + # Table 3: Coefficients and exponents of the backward equation T_3a(p,h) for subregion 3a in its dimensionless form, Eq. (2) + Table3_I = [ + -12, + -12, + -12, + -12, + -12, + -12, + -12, + -12, + -10, + -10, + -10, + -8, + -8, + -8, + -8, + -5, + -3, + -2, + -2, + -2, + -1, + -1, + 0, + 0, + 1, + 3, + 3, + 4, + 4, + 10, + 12, + ] + Table3_J = [ + 0, + 1, + 2, + 6, + 14, + 16, + 20, + 22, + 1, + 5, + 12, + 0, + 2, + 4, + 10, + 2, + 0, + 1, + 3, + 4, + 0, + 2, + 0, + 1, + 1, + 0, + 1, + 0, + 3, + 4, + 5, + ] + Table3_n = [ + -0.133645667811215e-6, + +0.455912656802978e-5, + -0.146294640700979e-4, + +0.639341312970080e-2, + +0.372783927268847e3, + -0.718654377460447e4, + +0.573494752103400e6, + -0.267569329111439e7, + -0.334066283302614e-4, + -0.245479214069597e-1, + +0.478087847764996e2, + +0.764664131818904e-5, + +0.128350627676972e-2, + +0.171219081377331e-1, + -0.851007304583213e1, + -0.136513461629781e-1, + -0.384460997596657e-5, + +0.337423807911655e-2, + -0.551624873066791, + +0.729202277107470, + -0.992522757376041e-2, + -0.119308831407288, + +0.793929190615421, + +0.454270731799386, + +0.209998591259910, + -0.642109823904738e-2, + -0.235155868604540e-1, + +0.252233108341612e-2, + -0.764885133368119e-2, + +0.136176427574291e-1, + -0.133027883575669e-1, + ] + + # Table 4: Coefficients and exponents of the backward equation T_3b(p,h) for subregion 3b in its dimensionless form, Eq. (3) + Table4_I = [ + -12, + -12, + -10, + -10, + -10, + -10, + -10, + -8, + -8, + -8, + -8, + -8, + -6, + -6, + -6, + -4, + -4, + -3, + -2, + -2, + -1, + -1, + -1, + -1, + -1, + -1, + 0, + 0, + 1, + 3, + 5, + 6, + 8, + ] + Table4_J = [ + 0, + 1, + 0, + 1, + 5, + 10, + 12, + 0, + 1, + 2, + 4, + 10, + 0, + 1, + 2, + 0, + 1, + 5, + 0, + 4, + 2, + 4, + 6, + 10, + 14, + 16, + 0, + 2, + 1, + 1, + 1, + 1, + 1, + ] + Table4_n = [ + +0.323254573644920e-4, + -0.127575556587181e-3, + -0.475851877356068e-3, + +0.156183014181602e-2, + +0.105724860113781, + -0.858514221132534e2, + +0.724140095480911e3, + +0.296475810273257e-2, + -0.592721983365988e-2, + -0.126305422818666e-1, + -0.115716196364853, + +0.849000969739595e2, + -0.108602260086615e-1, + +0.154304475328851e-1, + +0.750455441524466e-1, + +0.252520973612982e-1, + -0.602507901232996e-1, + -0.307622221350501e1, + -0.574011959864879e-1, + +0.503471360939849e1, + -0.925081888584834, + +0.391733882917546e1, + -0.773146007130190e2, + +0.949308762098587e4, + -0.141043719679409e7, + +0.849166230819026e7, + +0.861095729446704, + +0.323346442811720, + +0.873281936020439, + -0.436653048526683, + +0.286596714529479, + -0.131778331276228, + +0.676682064330275e-2, + ] + + # Table 6: Coefficients and exponents of the backward equation v_3a(p,h) for subregion 3a in its dimensionless form, Eq. (4) + Table6_I = [ + -12, + -12, + -12, + -12, + -10, + -10, + -10, + -8, + -8, + -6, + -6, + -6, + -4, + -4, + -3, + -2, + -2, + -1, + -1, + -1, + -1, + 0, + 0, + 1, + 1, + 1, + 2, + 2, + 3, + 4, + 5, + 8, + ] + Table6_J = [ + 6, + 8, + 12, + 18, + 4, + 7, + 10, + 5, + 12, + 3, + 4, + 22, + 2, + 3, + 7, + 3, + 16, + 0, + 1, + 2, + 3, + 0, + 1, + 0, + 1, + 2, + 0, + 2, + 0, + 2, + 2, + 2, + ] + Table6_n = [ + +0.529944062966028e-2, + -0.170099690234461, + +0.111323814312927e2, + -0.217898123145125e4, + -0.506061827980875e-3, + +0.556495239685324, + -0.943672726094016e1, + -0.297856807561527, + +0.939353943717186e2, + +0.192944939465981e-1, + +0.421740664704763, + -0.368914126282330e7, + -0.737566847600639e-2, + -0.354753242424366, + -0.199768169338727e1, + +0.115456297059049e1, + +0.568366875815960e4, + +0.808169540124668e-2, + +0.172416341519307, + +0.104270175292927e1, + -0.297691372792847, + +0.560394465163593, + +0.275234661176914, + -0.148347894866012, + -0.651142513478515e-1, + -0.292468715386302e1, + +0.664876096952665e-1, + +0.352335014263844e1, + -0.146340792313332e-1, + -0.224503486668184e1, + +0.110533464706142e1, + -0.408757344495612e-1, + ] + + # Table 7: Coefficients and exponents of the backward equation v_3b(p,h) for subregion 3b in its dimensionless form, Eq. (5) + Table7_I = [ + -12, + -12, + -8, + -8, + -8, + -8, + -8, + -8, + -6, + -6, + -6, + -6, + -6, + -6, + -4, + -4, + -4, + -3, + -3, + -2, + -2, + -1, + -1, + -1, + -1, + 0, + 1, + 1, + 2, + 2, + ] + Table7_J = [ + 0, + 1, + 0, + 1, + 3, + 6, + 7, + 8, + 0, + 1, + 2, + 5, + 6, + 10, + 3, + 6, + 10, + 0, + 2, + 1, + 2, + 0, + 1, + 4, + 5, + 0, + 0, + 1, + 2, + 6, + ] + Table7_n = [ + -0.225196934336318e-8, + +0.140674363313486e-7, + +0.233784085280560e-5, + -0.331833715229001e-4, + +0.107956778514318e-2, + -0.271382067378863, + +0.107202262490333e1, + -0.853821329075382, + -0.215214194340526e-4, + +0.769656088222730e-3, + -0.431136580433864e-2, + +0.453342167309331, + -0.507749535873652, + -0.100475154528389e3, + -0.219201924648793, + -0.321087965668917e1, + +0.607567815637771e3, + +0.557686450685932e-3, + +0.187499040029550, + +0.905368030448107e-2, + +0.285417173048685, + +0.329924030996098e-1, + +0.239897419685483, + +0.482754995951394e1, + -0.118035753702231e2, + +0.169490044091791, + -0.179967222507787e-1, + +0.371810116332674e-1, + -0.536288335065096e-1, + +0.160697101092520e1, + ] + + # Table 10: Coefficients and exponents of the backward equation T_3a(p,s) for subregion 3a in its dimensionless form, Eq. (6) + Table10_I = [ + -12, + -12, + -10, + -10, + -10, + -10, + -8, + -8, + -8, + -8, + -6, + -6, + -6, + -5, + -5, + -5, + -4, + -4, + -4, + -2, + -2, + -1, + -1, + 0, + 0, + 0, + 1, + 2, + 2, + 3, + 8, + 8, + 10, + ] + Table10_J = [ + 28, + 32, + 4, + 10, + 12, + 14, + 5, + 7, + 8, + 28, + 2, + 6, + 32, + 0, + 14, + 32, + 6, + 10, + 36, + 1, + 4, + 1, + 6, + 0, + 1, + 4, + 0, + 0, + 3, + 2, + 0, + 1, + 2, + ] + Table10_n = [ + +0.150042008263875e10, + -0.159397258480424e12, + +0.502181140217975e-3, + -0.672057767855466e2, + +0.145058545404456e4, + -0.823889534888890e4, + -0.154852214233853, + +0.112305046746695e2, + -0.297000213482822e2, + +0.438565132635495e11, + +0.137837838635464e-2, + -0.297478527157462e1, + +0.971777947349413e13, + -0.571527767052398e-4, + +0.288307949778420e5, + -0.744428289262703e14, + +0.128017324848921e2, + -0.368275545889071e3, + +0.664768904779177e16, + +0.449359251958880e-1, + -0.422897836099655e1, + -0.240614376434179, + -0.474341365254924e1, + +0.724093999126110, + +0.923874349695897, + +0.399043655281015e1, + +0.384066651868009e-1, + -0.359344365571848e-2, + -0.735196448821653, + +0.188367048396131, + +0.141064266818704e-3, + -0.257418501496337e-2, + +0.123220024851555e-2, + ] + + # Table 11: Coefficients and exponents of the backward equation T_3b(p,s) for subregion 3b in its dimensionless form, Eq. (7) + Table11_I = [ + -12, + -12, + -12, + -12, + -8, + -8, + -8, + -6, + -6, + -6, + -5, + -5, + -5, + -5, + -5, + -4, + -3, + -3, + -2, + 0, + 2, + 3, + 4, + 5, + 6, + 8, + 12, + 14, + ] + Table11_J = [ + 1, + 3, + 4, + 7, + 0, + 1, + 3, + 0, + 2, + 4, + 0, + 1, + 2, + 4, + 6, + 12, + 1, + 6, + 2, + 0, + 1, + 1, + 0, + 24, + 0, + 3, + 1, + 2, + ] + Table11_n = [ + +0.527111701601660, + -0.401317830052742e2, + +0.153020073134484e3, + -0.224799398218827e4, + -0.193993484669048, + -0.140467557893768e1, + +0.426799878114024e2, + +0.752810643416743, + +0.226657238616417e2, + -0.622873556909932e3, + -0.660823667935396, + +0.841267087271658, + -0.253717501764397e2, + +0.485708963532948e3, + +0.880531517490555e3, + +0.265015592794626e7, + -0.359287150025783, + -0.656991567673753e3, + +0.241768149185367e1, + +0.856873461222588, + +0.655143675313458, + -0.213535213206406, + +0.562974957606348e-2, + -0.316955725450471e15, + -0.699997000152457e-3, + +0.119845803210767e-1, + +0.193848122022095e-4, + -0.215095749182309e-4, + ] + + # Table 13: Coefficients and exponents of the backward equation v_3a(p,s) for subregion 3a in its dimensionless form, Eq. (8). + Table13_I = [ + -12, + -12, + -12, + -10, + -10, + -10, + -10, + -8, + -8, + -8, + -8, + -6, + -5, + -4, + -3, + -3, + -2, + -2, + -1, + -1, + 0, + 0, + 0, + 1, + 2, + 4, + 5, + 6, + ] + Table13_J = [ + 10, + 12, + 14, + 4, + 8, + 10, + 20, + 5, + 6, + 14, + 16, + 28, + 1, + 5, + 2, + 4, + 3, + 8, + 1, + 2, + 0, + 1, + 3, + 0, + 0, + 2, + 2, + 0, + ] + Table13_n = [ + +0.795544074093975e2, + -0.238261242984590e4, + +0.176813100617787e5, + -0.110524727080379e-2, + -0.153213833655326e2, + +0.297544599376982e3, + -0.350315206871242e8, + +0.277513761062119, + -0.523964271036888, + -0.148011182995403e6, + +0.160014899374266e7, + +0.170802322663427e13, + +0.246866996006494e-3, + +0.165326084797980e1, + -0.118008384666987, + +0.253798642355900e1, + +0.965127704669424, + -0.282172420532826e2, + +0.203224612353823, + +0.110648186063513e1, + +0.526127948451280, + +0.277000018736321, + +0.108153340501132e1, + -0.744127885357893e-1, + +0.164094443541384e-1, + -0.680468275301065e-1, + +0.257988576101640e-1, + -0.145749861944416e-3, + ] + + # Table 14: Coefficients and exponents of the backward equation v_3b(p,s) for subregion 3b in its dimensionless form, Eq. (9) + Table14_I = [ + -12, + -12, + -12, + -12, + -12, + -12, + -10, + -10, + -10, + -10, + -8, + -5, + -5, + -5, + -4, + -4, + -4, + -4, + -3, + -2, + -2, + -2, + -2, + -2, + -2, + 0, + 0, + 0, + 1, + 1, + 2, + ] + Table14_J = [ + 0, + 1, + 2, + 3, + 5, + 6, + 0, + 1, + 2, + 4, + 0, + 1, + 2, + 3, + 0, + 1, + 2, + 3, + 1, + 0, + 1, + 2, + 3, + 4, + 12, + 0, + 1, + 2, + 0, + 2, + 2, + ] + Table14_n = [ + +0.591599780322238e-4, + -0.185465997137856e-2, + +0.104190510480013e-1, + +0.598647302038590e-2, + -0.771391189901699, + +0.172549765557036e1, + -0.467076079846526e-3, + +0.134533823384439e-1, + -0.808094336805495e-1, + +0.508139374365767, + +0.128584643361683e-2, + -0.163899353915435e1, + +0.586938199318063e1, + -0.292466667918613e1, + -0.614076301499537e-2, + +0.576199014049172e1, + -0.121613320606788e2, + +0.167637540957944e1, + -0.744135838773463e1, + +0.378168091437659e-1, + +0.401432203027688e1, + +0.160279837479185e2, + +0.317848779347728e1, + -0.358362310304853e1, + -0.115995260446827e7, + +0.199256573577909, + -0.122270624794624, + -0.191449143716586e2, + -0.150448002905284e-1, + +0.146407900162154e2, + -0.327477787188230e1, + ] + + # Table 17: Coefficients and exponents of the boundary equation p_3sat(h) in its dimensionless form, Eq. (10) + Table17_I = [0, 1, 1, 1, 1, 5, 7, 8, 14, 20, 22, 24, 28, 36] + Table17_J = [0, 1, 3, 4, 36, 3, 0, 24, 16, 16, 3, 18, 8, 24] + Table17_n = [ + +0.600073641753024, + -0.936203654849857e1, + +0.246590798594147e2, + -0.107014222858224e3, + -0.915821315805768e14, + -0.862332011700662e4, + -0.235837344740032e2, + +0.252304969384128e18, + -0.389718771997719e19, + -0.333775713645296e23, + +0.356499469636328e11, + -0.148547544720641e27, + +0.330611514838798e19, + +0.813641294467829e38, + ] + + # Table 19: Coefficients and exponents of the boundary equation p_3sat(s) in its dimensionless form, Eq. (11) + Table19_I = [0, 1, 1, 4, 12, 12, 16, 24, 28, 32] + Table19_J = [0, 1, 32, 7, 4, 14, 36, 10, 0, 18] + Table19_n = [ + +0.639767553612785, + -0.129727445396014e2, + -0.224595125848403e16, + +0.177466741801846e7, + +0.717079349571538e10, + -0.378829107169011e18, + -0.955586736431328e35, + +0.187269814676188e24, + +0.119254746466473e12, + +0.110649277244882e37, + ] + + +class SR4_04: + """class with table data from IAPWS SR4-04(2014)""" + + s_dash_low = -1.545495919e-4 # kJ / kg K @ 273.15K + s_dash_heigh = 3.778281340 # kJ / kg K @ 623.15K + s_c = SR3_03.s_c # 4.41202148223476 # kJ / kg K @ 623.15K + s_doubledash = 9.155759395 # kJ / kg K @ 273.15K + s_heigh_mpa = 3.397782955 # kJ / kg K @ 100MPA, 673.15K + s_min_B23 = 5.048096828 # kJ / kg K + s_max_B23 = 5.260578707 # kJ / kg K + + h_min_B23 = SR3_03.h_doubledash # kJ / kg + h_max_B23 = 2.812942061e2 # kJ / kg + + # Table 3: Coefficients and exponents of the backward equation p_3a (h,s) for subregion 3a in its dimensionless form, Eq. (1) + Table3_I = [0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 6, 7, 8, 10, 10, 14, 18, 20, 22, 22, 24, 28, 28, 32, 32] + Table3_J = [0, 1, 5, 0, 3, 4, 8, 14, 6, 16, 0, 2, 3, 0, 1, 4, 5, 28, 28, 24, 1, 32, 36, 22, 28, 36, 16, 28, 36, 16, 36, 10, 28] + Table3_n = [ + +0.770889828326934e1, + -0.260835009128688e2, + +0.267416218930389e3, + +0.172221089496844e2, + -0.293542332145970e3, + +0.614135601882478e3, + -0.610562757725674e5, + -0.651272251118219e8, + +0.735919313521937e5, + -0.116646505914191e11, + +0.355267086434461e2, + -0.596144543825955e3, + -0.475842430145708e3, + +0.696781965359503e2, + +0.335674250377312e3, + +0.250526809130882e5, + +0.146997380630766e6, + +0.538069315091534e20, + +0.143619827291346e22, + +0.364985866165994e20, + -0.254741561156775e4, + +0.240120197096563e28, + -0.393847464679496e30, + +0.147073407024852e25, + -0.426391250432059e32, + +0.194509340621077e39, + +0.666212132114896e24, + +0.706777016552858e34, + +0.175563621975576e42, + +0.108408607429124e29, + +0.730872705175151e44, + +0.159145847398870e25, + +0.377121605943324e41, + ] + + # Table 4: Coefficients and exponents of the backward equation p_3b (h,s) for subregion 3b in its dimensionless form, Eq. (2) + Table4_I = [ + -12, + -12, + -12, + -12, + -12, + -10, + -10, + -10, + -10, + -8, + -8, + -6, + -6, + -6, + -6, + -5, + -4, + -4, + -4, + -3, + -3, + -3, + -3, + -2, + -2, + -1, + 0, + 2, + 2, + 5, + 6, + 8, + 10, + 14, + 14, + ] + Table4_J = [2, 10, 12, 14, 20, 2, 10, 14, 18, 2, 8, 2, 6, 7, 8, 10, 4, 5, 8, 1, 3, 5, 6, 0, 1, 0, 3, 0, 1, 0, 1, 1, 1, 3, 7] + Table4_n = [ + +0.125244360717979e-12, + -0.126599322553713e-1, + +0.506878030140626e1, + +0.317847171154202e2, + -0.391041161399932e6, + -0.975733406392044e-10, + -0.186312419488279e2, + +0.510973543414101e3, + +0.373847005822362e6, + +0.299804024666572e-7, + +0.200544393820342e2, + -0.498030487662829e-5, + -0.102301806360030e2, + +0.552819126990325e2, + -0.206211367510878e3, + -0.794012232324823e4, + +0.782248472028153e1, + -0.586544326902468e2, + +0.355073647696481e4, + -0.115303107290162e-3, + -0.175092403171802e1, + +0.257981687748160e3, + -0.727048374179467e3, + +0.121644822609198e-3, + +0.393137871762692e-1, + +0.704181005909296e-2, + -0.829108200698110e2, + -0.265178818131250, + +0.137531682453991e2, + -0.522394090753046e2, + +0.240556298941048e4, + -0.227361631268929e5, + +0.890746343932567e5, + -0.239234565822486e8, + +0.568795808129714e10, + ] + + # Table 9: Coefficients and exponents of the boundary equation h'_1 (s) in its dimensionless form, Eq. (3) + Table9_I = [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 7, 8, 12, 12, 14, 14, 16, 20, 20, 22, 24, 28, 32, 32] + Table9_J = [14, 36, 3, 16, 0, 5, 4, 36, 4, 16, 24, 18, 24, 1, 4, 2, 4, 1, 22, 10, 12, 28, 8, 3, 0, 6, 8] + Table9_n = [ + +0.332171191705237, + +0.611217706323496e-3, + -0.882092478906822e1, + -0.455628192543250, + -0.263483840850452e-4, + -0.223949661148062e2, + -0.428398660164013e1, + -0.616679338856916, + -0.146823031104040e2, + +0.284523138727299e3, + -0.113398503195444e3, + +0.115671380760859e4, + +0.395551267359325e3, + -0.154891257229285e1, + +0.194486637751291e2, + -0.357915139457043e1, + -0.335369414148819e1, + -0.664426796332460, + +0.323321885383934e5, + +0.331766744667084e4, + -0.223501257931087e5, + +0.573953875852936e7, + +0.173226193407919e3, + -0.363968822121321e-1, + +0.834596332878346e-6, + +0.503611916682674e1, + +0.655444787064505e2, + ] + + # Table 10: Coefficients and exponents of the boundary equation h'_3a(s) in its dimensionless form, Eq. (4) + Table10_I = [0, 0, 0, 0, 2, 3, 4, 4, 5, 5, 6, 7, 7, 7, 10, 10, 10, 32, 32] + Table10_J = [1, 4, 10, 16, 1, 36, 3, 16, 20, 36, 4, 2, 28, 32, 14, 32, 36, 0, 6] + Table10_n = [ + +0.822673364673336, + +0.181977213534479, + -0.112000260313624e-1, + -0.746778287048033e-3, + -0.179046263257381, + +0.424220110836657e-1, + -0.341355823438768, + -0.209881740853565e1, + -0.822477343323596e1, + -0.499684082076008e1, + +0.191413958471069, + +0.581062241093136e-1, + -0.165505498701029e4, + +0.158870443421201e4, + -0.850623535172818e2, + -0.317714386511207e5, + -0.945890406632871e5, + -0.13927384708869e-5, + +0.63105253224098, + ] + + # Table 16: Coefficients and exponents of the boundary equation h''_2ab(s) in its dimensionless form, Eq. (5) + Table16_I = [1, 1, 2, 2, 4, 4, 7, 8, 8, 10, 12, 12, 18, 20, 24, 28, 28, 28, 28, 28, 32, 32, 32, 32, 32, 36, 36, 36, 36, 36] + Table16_J = [8, 24, 4, 32, 1, 2, 7, 5, 12, 1, 0, 7, 10, 12, 32, 8, 12, 20, 22, 24, 2, 7, 12, 14, 24, 10, 12, 20, 22, 28] + Table16_n = [ + -0.524581170928788e3, + -0.926947218142218e7, + -0.237385107491666e3, + +0.210770155812776e11, + -0.239494562010986e2, + +0.221802480294197e3, + -0.510472533393438e7, + +0.124981396109147e7, + +0.200008436996201e10, + -0.815158509791035e3, + -0.157612685637523e3, + -0.114200422332791e11, + +0.662364680776872e16, + -0.227622818296144e19, + -0.171048081348406e32, + +0.660788766938091e16, + +0.166320055886021e23, + -0.218003784381501e30, + -0.787276140295618e30, + +0.151062329700346e32, + +0.795732170300541e7, + +0.131957647355347e16, + -0.325097068299140e24, + -0.418600611419248e26, + +0.297478906557467e35, + -0.953588761745473e20, + +0.166957699620939e25, + -0.175407764869978e33, + +0.347581490626396e35, + -0.710971318427851e39, + ] + + # Table 17: Coefficients and exponents of the boundary equation h''_2c3b(s) in its dimensionless form, Eq. (6) + Table17_I = [0, 0, 0, 1, 1, 5, 6, 7, 8, 8, 12, 16, 22, 22, 24, 36] + Table17_J = [0, 3, 4, 0, 12, 36, 12, 16, 2, 20, 32, 36, 2, 32, 7, 20] + Table17_n = [ + +0.104351280732769e1, + -0.227807912708513e1, + +0.180535256723202e1, + +0.420440834792042, + -0.105721244834660e6, + +0.436911607493884e25, + -0.328032702839753e12, + -0.678686760804270e16, + +0.743957464645363e4, + -0.356896445355761e20, + +0.167590585186801e32, + -0.355028625419105e38, + +0.396611982166538e12, + -0.414716268484468e41, + +0.359080103867382e19, + -0.116994334851995e41, + ] + + # Table 23. Coefficients and exponents of the equation h_B13(s) in its dimensionless form, Eq. (7) + Table23_I = [0, 1, 1, 3, 5, 6] + Table23_J = [0, -2, 2, -12, -4, -3] + Table23_n = [ + +0.913965547600543, + -0.430944856041991e-4, + +0.603235694765419e2, + +0.117518273082168e-17, + +0.220000904781292, + -0.690815545851641e2, + ] + + # Table 25: Coefficients and exponents of the boundary equation T_B23(h,s) in its dimensionless form, Eq. (8) + Table25_I = [-12, -10, -8, -4, -3, -2, -2, -2, -2, 0, 1, 1, 1, 3, 3, 5, 6, 6, 8, 8, 8, 12, 12, 14, 14] + Table25_J = [10, 8, 3, 4, 3, -6, 2, 3, 4, 0, -3, -2, 10, -2, -1, -5, -6, -3, -8, -2, -1, -12, -1, -12, 1] + Table25_n = [ + +0.629096260829810e-3, + -0.823453502583165e-3, + +0.515446951519474e-7, + -0.117565945784945e1, + +0.348519684726192e1, + -0.507837382408313e-11, + -0.284637670005479e1, + -0.236092263939673e1, + +0.601492324973779e1, + +0.148039650824546e1, + +0.360075182221907e-3, + -0.126700045009952e-1, + -0.122184332521413e7, + +0.149276502463272, + +0.698733471798484, + -0.252207040114321e-1, + +0.147151930985213e-1, + -0.108618917681849e1, + -0.936875039816322e-3, + +0.819877897570217e2, + -0.182041861521835e3, + +0.261907376402688e-5, + -0.291626417025961e5, + +0.140660774926165e-4, + +0.783237062349385e7, + ] + + # Table 28: Coefficients and exponents of the equation T_sat(h,s) in its dimensionless form, Eq. (9) + Table28_I = [ + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 2, + 2, + 2, + 3, + 3, + 3, + 3, + 4, + 4, + 5, + 5, + 5, + 5, + 6, + 6, + 6, + 8, + 10, + 10, + 12, + 14, + 14, + 16, + 16, + 18, + 18, + 18, + 20, + 28, + ] + Table28_J = [ + 0, + 3, + 12, + 0, + 1, + 2, + 5, + 0, + 5, + 8, + 0, + 2, + 3, + 4, + 0, + 1, + 1, + 2, + 4, + 16, + 6, + 8, + 22, + 1, + 20, + 36, + 24, + 1, + 28, + 12, + 32, + 14, + 22, + 36, + 24, + 36, + ] + Table28_n = [ + +0.179882673606601, + -0.267507455199603, + +0.116276722612600e1, + +0.147545428713616, + -0.512871635973248, + +0.421333567697984, + +0.563749522189870, + +0.429274443819153, + -0.335704552142140e1, + +0.108890916499278e2, + -0.248483390456012, + +0.304153221906390, + -0.494819763939905, + +0.107551674933261e1, + +0.733888415457688e-1, + +0.140170545411085e-1, + -0.106110975998808, + +0.168324361811875e-1, + +0.125028363714877e1, + +0.101316840309509e4, + -0.151791558000712e1, + +0.524277865990866e2, + +0.230495545563912e5, + +0.249459806365456e-1, + +0.210796467412137e7, + +0.366836848613065e9, + -0.144814105365163e9, + -0.179276373003590e-2, + +0.489955602100459e10, + +0.471262212070518e3, + -0.829294390198652e11, + -0.171545662263191e4, + +0.355777682973575e7, + +0.586062760258436e12, + -0.129887635078195e8, + +0.317247449371057e11, + ] diff --git a/pyXSteam/TransportProperties.py b/pyXSteam/TransportProperties.py index 0c6da9a..55162c8 100755 --- a/pyXSteam/TransportProperties.py +++ b/pyXSteam/TransportProperties.py @@ -5,14 +5,17 @@ """ import math import logging -from . import RegionSelection +from .RegionSelection import ( + select_region_pT, + select_region_ph, +) from .Regions import Region1, Region2, Region3, Region4, Region5 -from . import Constants +from .Constants import TRIPLE_POINT_TEMPERATURE, CRITICAL_TEMPERATURE, FREEZING_TEMPERATURE_H2O logger = logging.getLogger(__name__) -def my_AllRegions_pT(p, T): +def my_AllRegions_pT(p: float, T: float) -> float: """function my_AllRegions_pT = my_AllRegions_pT(p, T) Section 5.1 Viscosity (IAPWS formulation 1985, Revised 2003) @@ -26,17 +29,17 @@ def my_AllRegions_pT(p, T): h6 = [0, 0, 0, -0.003629481, 0, 0] # Calculate density. - if RegionSelection.region_pT(p, T) == 1: + if select_region_pT(p, T) == 1: rho = 1 / Region1.v1_pT(p, T) - elif RegionSelection.region_pT(p, T) == 2: + elif select_region_pT(p, T) == 2: rho = 1 / Region2.v2_pT(p, T) - elif RegionSelection.region_pT(p, T) == 3: + elif select_region_pT(p, T) == 3: hs = Region3.h3_pT(p, T) rho = 1 / Region3.v3_ph(p, hs) - elif RegionSelection.region_pT(p, T) == 4: + elif select_region_pT(p, T) == 4: logger.warning("function my_AllRegions_pT is not available in region 4") return float("NaN") - elif RegionSelection.region_pT(p, T) == 5: + elif select_region_pT(p, T) == 5: rho = 1 / Region5.v5_pT(p, T) else: logger.warning("Region switch returned unknown value") @@ -48,9 +51,9 @@ def my_AllRegions_pT(p, T): # Check valid area if ( - (T > (900 + 273.15)) - or ((T > (600 + 273.15)) and (p > 300)) - or ((T > (150 + 273.15)) and (p > 350)) + (T > (900 + FREEZING_TEMPERATURE_H2O)) + or (T > (600 + FREEZING_TEMPERATURE_H2O) and (p > 300)) + or (T > (150 + FREEZING_TEMPERATURE_H2O) and (p > 350)) or (p > 500) ): logger.warning("Temperature and/or Preasure out of range of validity") @@ -74,7 +77,7 @@ def my_AllRegions_pT(p, T): return mys * 0.000055071 -def my_AllRegions_ph(p, h): +def my_AllRegions_ph(p: float, h: float) -> float: """function my_AllRegions_ph = my_AllRegions_ph(p, h) Section 5.1 Viscosity (IAPWS formulation 1985, Revised 2003) @@ -88,18 +91,18 @@ def my_AllRegions_ph(p, h): h6 = [0, 0, 0, -0.003629481, 0, 0] # Calculate density. - if RegionSelection.region_ph(p, h) == 1: + if select_region_ph(p, h) == 1: Ts = Region1.T1_ph(p, h) T = Ts rho = 1 / Region1.v1_pT(p, Ts) - elif RegionSelection.region_ph(p, h) == 2: + elif select_region_ph(p, h) == 2: Ts = Region2.T2_ph(p, h) T = Ts rho = 1 / Region2.v2_pT(p, Ts) - elif RegionSelection.region_ph(p, h) == 3: + elif select_region_ph(p, h) == 3: rho = 1 / Region3.v3_ph(p, h) T = Region3.T3_ph(p, h) - elif RegionSelection.region_ph(p, h) == 4: + elif select_region_ph(p, h) == 4: xs = Region4.x4_ph(p, h) if p < 16.529: v4v = Region2.v2_pT(p, Region4.T4_p(p)) @@ -109,7 +112,7 @@ def my_AllRegions_ph(p, h): v4L = Region3.v3_ph(p, Region4.h4L_p(p)) rho = 1 / (xs * v4v + (1 - xs) * v4L) T = Region4.T4_p(p) - elif RegionSelection.region_ph(p, h) == 5: + elif select_region_ph(p, h) == 5: Ts = Region5.T5_ph(p, h) T = Ts rho = 1 / Region5.v5_pT(p, Ts) @@ -122,9 +125,9 @@ def my_AllRegions_ph(p, h): # Check valid area if ( - (T > (900 + 273.15)) - or (T > (600 + 273.15) and (p > 300)) - or (T > (150 + 273.15) and (p > 350)) + (T > (900 + FREEZING_TEMPERATURE_H2O)) + or (T > (600 + FREEZING_TEMPERATURE_H2O) and (p > 300)) + or (T > (150 + FREEZING_TEMPERATURE_H2O) and (p > 350)) or (p > 500) ): logger.warning("Temperature and/or Preasure out of range of validity") @@ -150,7 +153,7 @@ def my_AllRegions_ph(p, h): return mys * 0.000055071 -def tc_ptrho(p, T, rho): +def tc_ptrho(p: float, T: float, rho: float) -> float: """function tc_ptrho = tc_ptrho(p, T, rho) Section 5.2 Thermal Conductivity (IAPWS formulation 1985) @@ -161,18 +164,18 @@ def tc_ptrho(p, T, rho): """ # ver2.6 Start corrected bug - if T < 273.15: + if T < FREEZING_TEMPERATURE_H2O: logger.warning("Temperature out of range of validity") return float("NaN") - elif T < 500 + 273.15: + if T < 500 + FREEZING_TEMPERATURE_H2O: if p > 100: logger.warning("Preasure out of range of validity") return float("NaN") - elif T <= 650 + 273.15: + if T <= 650 + FREEZING_TEMPERATURE_H2O: if p > 70: logger.warning("Preasure out of range of validity") return float("NaN") - else: # T <= 800 + 273.15: + else: # T <= 800 + __FREEZING_POINT_H2O__: if p > 40: logger.warning("Preasure out of range of validity") return float("NaN") @@ -181,15 +184,9 @@ def tc_ptrho(p, T, rho): T = T / 647.26 # Page 8, Eq 4 rho = rho / 317.7 # Page 8, Eq 5 - tc0 = T**0.5 * ( - 0.0102811 + 0.0299621 * T + 0.0156146 * (T**2) - 0.00422464 * (T**3) - ) # Page 9, Eq 9 + tc0 = T**0.5 * (0.0102811 + 0.0299621 * T + 0.0156146 * (T**2) - 0.00422464 * (T**3)) # Page 9, Eq 9 - tc1 = ( - -0.397070 - + 0.400302 * rho - + 1.06 * math.exp(-0.171587 * ((rho + 2.392190) ** 2)) - ) # Page 9, Eq 10 + tc1 = -0.397070 + 0.400302 * rho + 1.06 * math.exp(-0.171587 * ((rho + 2.392190) ** 2)) # Page 9, Eq 10 dT = abs(T - 1) + 0.00308976 # Page 9, Eq 12 Q = 2 + 0.0822994 / (dT ** (3 / 5)) # Page 10, Eq 13 @@ -199,33 +196,31 @@ def tc_ptrho(p, T, rho): s = 10.0932 / (dT ** (3 / 5)) tc2 = ( - (0.0701309 / (T**10) + 0.0118520) - * (rho ** (9 / 5)) - * math.exp(0.642857 * (1 - rho ** (14 / 5))) + (0.0701309 / (T**10) + 0.0118520) * (rho ** (9 / 5)) * math.exp(0.642857 * (1 - rho ** (14 / 5))) + 0.00169937 * s * (rho**Q) * math.exp((Q / (1 + Q)) * (1 - rho ** (1 + Q))) - 1.02 * math.exp(-4.11717 * (T ** (3 / 2)) - 6.17937 / (rho**5)) ) # Page 9, Eq 11 return tc0 + tc1 + tc2 # Page 9, Eq 8 -def Surface_Tension_T(T): - """function Surface_Tension_T = Surface_Tension_T(T) +def surface_tension_T(T: float) -> float: + """R1-76(2014) calculate surface tension as a function of temperature - Section 5.3 Surface Tension - - IAPWS Release on Surface Tension of Ordinary Water Substance, September 1994 + IAPWS Revised Release on Surface Tension of Ordinary Water Substance, June 2014 R1-76(2014) + http://www.iapws.org/relguide/Surf-H2O-2014.pdf - also + :param T: temperature in Kelvin - IAPWS Revised Release on Surface Tension of Ordinary Water Substance, June 2014 R1-76(2014) + :return: surface tension in mN/m """ - tc = Constants.__CRITICAL_TEMPERATURE__ - B = 0.2358 # N/m - bb = -0.625 # - my = 1.256 # - if (T < 0.01) or (T > tc): - logger.warning("Temperature out of range of validity") - return float("NaN") + B = 235.8 # N/m + bb = -0.625 + my = 1.256 + + if TRIPLE_POINT_TEMPERATURE <= T <= CRITICAL_TEMPERATURE: + tau = 1 - T / CRITICAL_TEMPERATURE + sigma = B * tau**my * (1 + bb * tau) + return sigma - tau = 1 - T / tc - return B * tau**my * (1 + bb * tau) + logger.warning("Temperature out of range of validity") + return float("NaN") diff --git a/pyXSteam/TransportProperties_HW.py b/pyXSteam/TransportProperties_HW.py new file mode 100644 index 0000000..51915e2 --- /dev/null +++ b/pyXSteam/TransportProperties_HW.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""functions for transport properties of heavy water""" + +import logging + +from .Constants import TRIPLE_POINT_TEMPERATURE, CRITICAL_TEMPERATURE_D20_1992 +from .Constants import __REFERENCE_TEMPERATURE_D20_R17_R18__ as T_STAR +from .Constants import __REFERENCE_PREASSURE_D20_R17_R18__ as P_STAR +from .Constants import __REFERENCE_DENSITY_D20_R17_R18__ as RHO_STAR +from .Constants import __REFERENCE_VISCOSITY_D20_R17_R18__ as MY_STAR +from .Constants import __REFERENCE_THERMAL_CONDUCTIVITY_D20_R18__ as LAMBDA_STAR +from .Constants import __SPECIFIC_GAS_CONSTANT_D20_R17_R18__ as R +from .Constants import __TRIPLE_POINT_TEMPERATURE_D2O_RESHW_2018__ as P_t +from .Constants import __TRIPLE_POINT_PRESSURE_D20_RESHW_2018__ as T_t + +logger = logging.getLogger(__name__) + + +def my_AllRegions_pT() -> float: + """R17-20 calculate viscosity of all liquide states for heavy water, replaces IAPWS R4-84(2007)""" + # 0 < p ≤ pt pt ≤ p ≤ 100 MPa 100 MPa < p ≤ 200 MPa 200 MPa < p ≤ 960 MPa and and and and Tt ≤ T ≤ 775 K + # Tm(p) ≤ T ≤ 775 K + # Tm(p) ≤ T ≤ 473 K Tm(p) ≤ T ≤ 373 K + pass + + +def tc_() -> float: + """R18-21 calculate thermal conductivity of heavy water, replaces IAPWS R4-84(2007)""" + pass + + +def surface_tension_T(T: float) -> float: + """R5-85(1994) calculate surface tension as a function of temperature for heavy water + + IAPWS Release on Surface Tension of Heavy Water Substance + http://www.iapws.org/relguide/surfd2o.pdf + + :param T: temperature in Kelvin + + :return: surface tension in mN/m + """ + B = 238.0 # N/m + bb = -0.639 + my = 1.25 + + if TRIPLE_POINT_TEMPERATURE <= T <= CRITICAL_TEMPERATURE_D20_1992: + tau = 1 - T / CRITICAL_TEMPERATURE_D20_1992 + sigma = B * tau**my * (1 + bb * tau) + return sigma + + logger.warning("Temperature out of range of validity") + return float("NaN") diff --git a/pyXSteam/UnitConverter.py b/pyXSteam/UnitConverter.py index fd317ba..4862ed6 100755 --- a/pyXSteam/UnitConverter.py +++ b/pyXSteam/UnitConverter.py @@ -5,224 +5,355 @@ a enduser might use. """ import logging -from . import Constants +from .Constants import ABSOLUTE_ZERO_CELSIUS, UnitSystem -class UnitConverter(object): - """Helper class to convert user units to SI-units and back""" +class UnitConverter: + """ + Helper class to convert user units to SI-units and back - __UNIT_SYSTEM_BARE__ = 0 # m/kg/sec/K/MPa/W - __UNIT_SYSTEM_MKS__ = 1 # m/kg/sec/°C/bar/W - __UNIT_SYSTEM_FLS__ = 2 # ft/lb/sec/°F/psi/btu + :param unitSystem: unit system used for input and output values. For + supported values see the enum UnitSystem. + """ - def __init__(self, unitSystem=__UNIT_SYSTEM_BARE__): - """Initialise the unit converter. Parameter is the unit system used by the application""" - self.logger = logging.getLogger("pyXSteam-UnitConverter") + def __init__(self, unitSystem: UnitSystem = UnitSystem.BARE): + """ + Constructor method + """ + self.logger = logging.getLogger(__name__) self.set_unitSystem(unitSystem) self.logger.debug("set unit converter to %s", self.__str__()) - def set_unitSystem(self, unitSystem): - """change unit system""" - if ( - unitSystem is self.__UNIT_SYSTEM_BARE__ - or unitSystem is self.__UNIT_SYSTEM_MKS__ - or unitSystem is self.__UNIT_SYSTEM_FLS__ - ): + def set_unitSystem(self, unitSystem: UnitSystem): + """ + change unit system + + :param unitSystem: new unit system to use for input and output values + + :raises ValueError: unknown value for unit system + """ + if UnitSystem.has_value(unitSystem): self._unit_system = unitSystem else: self.logger.error("Unknown Unit System selected") raise ValueError("Unknown Unit System") - def toSIunit_p(self, ins): - """function toSIunit_p = toSIunit_p( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_MKS__: + def toSIunit_p(self, ins: float) -> float: + """ + convert preasure from user selected unit system to SI units + + :param ins: preasure in [bar] or [psi] + """ + if self._unit_system is UnitSystem.MKS: return float(ins / 10) # bar to MPa - elif self._unit_system is self.__UNIT_SYSTEM_FLS__: + if self._unit_system is UnitSystem.FLS: return float(ins * 0.00689475729) # psi to MPa return float(ins) - def fromSIunit_p(self, ins): - """function fromSIunit_p = fromSIunit_p( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_MKS__: + def fromSIunit_p(self, ins: float) -> float: + """ + convert preasure from SI units to user selected unit system + + :param ins: preasure in [MPa] + """ + if self._unit_system is UnitSystem.MKS: return float(ins * 10) # bar to MPa - elif self._unit_system is self.__UNIT_SYSTEM_FLS__: + if self._unit_system is UnitSystem.FLS: return float(ins / 0.00689475729) # MPa to psi return float(ins) - def toSIunit_T(self, ins): - """function toSIunit_T = toSIunit_T( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_MKS__: - return float(ins - Constants.__ABSOLUTE_ZERO_CELSIUS__) # degC to Kelvin - elif self._unit_system is self.__UNIT_SYSTEM_FLS__: - return float( - (5 / 9) * (ins - 32) - Constants.__ABSOLUTE_ZERO_CELSIUS__ - ) # degF to Kelvin + def toSIunit_T(self, ins: float) -> float: + """ + convert temperature from user selected unit system to SI units + + :param ins: temperature in [°C] or [°F] + """ + if self._unit_system is UnitSystem.MKS: + # degC to Kelvin + return float(ins - ABSOLUTE_ZERO_CELSIUS) + if self._unit_system is UnitSystem.FLS: + return float((5 / 9) * (ins - 32) - ABSOLUTE_ZERO_CELSIUS) # degF to Kelvin return float(ins) - def fromSIunit_T(self, ins): - """function fromSIunit_T = fromSIunit_T( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_MKS__: - return float(ins + Constants.__ABSOLUTE_ZERO_CELSIUS__) # Kelvin to degC - elif self._unit_system is self.__UNIT_SYSTEM_FLS__: - return float( - (ins + Constants.__ABSOLUTE_ZERO_CELSIUS__) * (9 / 5) + 32 - ) # Kelvin to degF + def fromSIunit_T(self, ins: float) -> float: + """ + convert temperature from SI units to user selected unit system + + :param ins: temperature in [K] + """ + if self._unit_system is UnitSystem.MKS: + # Kelvin to degC + return float(ins + ABSOLUTE_ZERO_CELSIUS) + if self._unit_system is UnitSystem.FLS: + return float((ins + ABSOLUTE_ZERO_CELSIUS) * (9 / 5) + 32) # Kelvin to degF return float(ins) - def toSIunit_h(self, ins): - """function toSIunit_h = toSIunit_h( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + def toSIunit_h(self, ins: float) -> float: + """ + convert enthalpy from user selected unit system to SI units + + :param ins: enthalpy [kJ / kg] or [btu / lb] + """ + if self._unit_system is UnitSystem.FLS: return float(2.32600 * ins) # btu/lb to kJ/kg return float(ins) - def fromSIunit_h(self, ins): - """function fromSIunit_h = fromSIunit_h( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + def fromSIunit_h(self, ins: float) -> float: + """ + convert enthalpy from SI units to user selected unit system + + :param ins: enthalpy [kJ / kg] + """ + if self._unit_system is UnitSystem.FLS: return float(ins / 2.32600) # kJ/kg to btu/lb return float(ins) - def toSIunit_v(self, ins): - """function toSIunit_v = toSIunit_v( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: - return float(ins * 0.0624279606) # ft^3/lb to m^3/kg + def toSIunit_v(self, ins: float) -> float: + """ + convert specific volume from user selected unit system to SI units + + :param ins: specific volume in [m³ / kg] or [ft³ / lb] + """ + if self._unit_system is UnitSystem.FLS: + return float(ins * 0.0624279606) # ft³/lb to m³/kg return float(ins) - def fromSIunit_v(self, ins): - """function fromSIunit_v = fromSIunit_v( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: - return float(ins / 0.0624279606) # m^3/kg to ft^3/lb + def fromSIunit_v(self, ins: float) -> float: + """ + convert specific volume from SI units to user selected unit system + + :param ins: specific volume in [m³ / kg] + """ + if self._unit_system is UnitSystem.FLS: + return float(ins / 0.0624279606) # m³/kg to ft³/lb return float(ins) - def toSIunit_s(self, ins): - """function toSIunit_s = toSIunit_s( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + def toSIunit_s(self, ins: float) -> float: + """ + convert specific entropy from user selected unit system to SI units + + :param ins: specific volume in [kJ / (kg °C)] or [btu / (lb °F)] + """ + if self._unit_system is UnitSystem.FLS: return float(ins / 0.238845896627) # btu/(lb degF) to kJ/(kg degC) return float(ins) - def fromSIunit_s(self, ins): - """function fromSIunit_s = fromSIunit_s( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + def fromSIunit_s(self, ins: float) -> float: + """ + convert specific entropy from SI units to user selected unit system + + :param ins: specific entropy in [kJ / (kg °C)] + """ + if self._unit_system is UnitSystem.FLS: return float(ins * 0.238845896627) # kJ/(kg degC) to btu/(lb degF) return float(ins) - def toSIunit_u(self, ins): - """function toSIunit_u = toSIunit_u( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + def toSIunit_u(self, ins: float) -> float: + """ + convert specific internal energy from user selected unit system to SI units + + :param ins: specific internal energy in [kJ / kg] or [btu / lb] + """ + if self._unit_system is UnitSystem.FLS: return float(ins * 2.32600) # btu/lb to kJ/kg return float(ins) - def fromSIunit_u(self, ins): - """function fromSIunit_u = fromSIunit_u( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + def fromSIunit_u(self, ins: float) -> float: + """ + convert specific internal energy from SI units to user selected unit system + + :param ins: specific internal energy in [kJ / kg] + """ + if self._unit_system is UnitSystem.FLS: return float(ins / 2.32600) # kJ/kg to btu/lb return float(ins) - def toSIunit_Cp(self, ins): - """function toSIunit_Cp = toSIunit_Cp( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + def toSIunit_Cp(self, ins: float) -> float: + """ + convert specific isobaric heat capacity from user selected unit + system to SI units + + :param ins: specific isobaric heat capacity in [kJ / (kg °C)] or [btu / (lb °F)] + """ + if self._unit_system is UnitSystem.FLS: return float(ins / 0.238846) # btu/(lb degF) to kJ/(kg degC) return float(ins) - def fromSIunit_Cp(self, ins): - """function fromSIunit_Cp = fromSIunit_Cp( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + def fromSIunit_Cp(self, ins: float) -> float: + """ + convert specific isobaric heat capacity from SI units to user + selected unit system + + :param ins: specific isobaric heat capacity in [kJ / (kg °C)] + """ + if self._unit_system is UnitSystem.FLS: return float(ins * 0.238846) # kJ/(kg degC) to btu/(lb degF) return float(ins) - def toSIunit_Cv(self, ins): - """function toSIunit_Cv = toSIunit_Cv( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + def toSIunit_Cv(self, ins: float) -> float: + """ + convert specific isochoric heat capacity from user selected unit + system to SI units + + :param ins: specific isochoric heat capacity in [kJ / (kg °C)] + or [btu / (lb °F)] + """ + if self._unit_system is UnitSystem.FLS: return float(ins / 0.238846) # btu/(lb degF) to kJ/(kg degC) return float(ins) - def fromSIunit_Cv(self, ins): - """function fromSIunit_Cv = fromSIunit_Cv( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + def fromSIunit_Cv(self, ins: float) -> float: + """ + convert specific isochoric heat capacity from SI units to user + selected unit system + + :param ins: specific isochoric heat capacity in [kJ / (kg °C)] + """ + if self._unit_system is UnitSystem.FLS: return float(ins * 0.238846) # kJ/(kg degC) to btu/(lb degF) return float(ins) - def toSIunit_w(self, ins): - """function toSIunit_w = toSIunit_w( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + def toSIunit_w(self, ins: float) -> float: + """ + convert speed of sound from user selected unit system to SI units + + :param ins: speed of sound in [m / s] or [ft / s] + """ + if self._unit_system is UnitSystem.FLS: return float(ins * 0.3048) # ft/s to m/s return float(ins) - def fromSIunit_w(self, ins): - """function fromSIunit_w = fromSIunit_w( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + def fromSIunit_w(self, ins: float) -> float: + """ + convert speed of sound from SI units to user selected unit system + + :param ins: speed of sound in [m / s] + """ + if self._unit_system is UnitSystem.FLS: return float(ins / 0.3048) # m/s to ft/s return float(ins) - def toSIunit_tc(self, ins): - """function toSIunit_tc = toSIunit_tc( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + def toSIunit_tc(self, ins: float) -> float: + """ + convert thermal conductivity from user selected unit + system to SI units + + :param ins: thermal conductivity in [W / (m °C)] or [btu / (h ft °F)] + """ + if self._unit_system is UnitSystem.FLS: return float(ins / 0.577789) # btu/(h*ft*degF) to W/(m*degC) return float(ins) - def fromSIunit_tc(self, ins): - """function fromSIunit_tc = fromSIunit_tc( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + def fromSIunit_tc(self, ins: float) -> float: + """ + convert thermal conductivity from SI units to user selected unit system + + :param ins: thermal conductivity in [W / (m °C)] + """ + if self._unit_system is UnitSystem.FLS: return float(ins * 0.577789) # W/(m*degC) to btu/(h*ft*degF) return float(ins) - def toSIunit_st(self, ins): - """function toSIunit_st = toSIunit_st( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + def toSIunit_st(self, ins: float) -> float: + """ + convert surface tension from user selected unit system to SI units + + :param ins: surface tension in [N / m] or [lb / ft] + """ + if self._unit_system is UnitSystem.FLS: return float(ins / 0.068521766) # lb/ft to N/m return float(ins) - def fromSIunit_st(self, ins): - """function fromSIunit_st = fromSIunit_st( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + def fromSIunit_st(self, ins: float) -> float: + """ + convert surface tension from SI units to user selected unit system + + :param ins: surface tension in [N / m] + """ + if self._unit_system is UnitSystem.FLS: return float(ins * 0.068521766) # N/m to lb/ft return float(ins) - def toSIunit_x(self, ins): - """function toSIunit_x = toSIunit_x( ins )""" + def toSIunit_x(self, ins: float) -> float: + """ + convert vapor fraction from user selected unit system to SI units + + :param ins: vapor fraction + + :raises ValueError: value of vapour fraction out of range + """ if 0.0 <= ins <= 1.0: return float(ins) self.logger.error("value of vapour fraction out of range: 0 < x < 1") raise ValueError("Vapour fraction out of Range") - def fromSIunit_x(self, ins): - """function fromSIunit_x = fromSIunit_x( ins )""" + def fromSIunit_x(self, ins: float) -> float: + """ + convert vapor fraction from SI units to user selected unit system + + :param ins: vapor fraction + + :raises ValueError: value of vapour fraction out of range + """ if 0.0 <= ins <= 1.0: return float(ins) self.logger.error("value of vapour fraction out of range: 0 < x < 1") raise ValueError("Vapour fraction out of Range") - def toSIunit_vx(self, ins): - """function toSIunit_vx = toSIunit_vx( ins )""" + def toSIunit_vx(self, ins: float) -> float: + """ + convert vapor volume fraction from user selected unit system to SI units + + :param ins: vapor volume fraction + + :raises ValueError: value of vapour volume fraction out of range + """ if 0.0 <= ins <= 1.0: return float(ins) self.logger.error("value of vapour volume fraction out of range: 0 < x < 1") raise ValueError("Vapour volume fraction out of Range") - def fromSIunit_vx(self, ins): - """function fromSIunit_vx = fromSIunit_vx( ins )""" + def fromSIunit_vx(self, ins: float) -> float: + """ + convert vapor volume fraction from SI units to user selected unit system + + :param ins: vapor volume fraction + + :raises ValueError: value of vapour volume fraction out of range + """ if 0.0 <= ins <= 1.0: return float(ins) self.logger.error("value of vapour volume fraction out of range: 0 < x < 1") raise ValueError("Vapour volume fraction out of Range") - def toSIunit_my(self, ins): - """function toSIunit_my = toSIunit_my( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: - return float(ins / 2419.088311) # lbm/ft/hr to PaS (N*s/m^2) + def toSIunit_my(self, ins: float) -> float: + """ + convert viscosity from user selected unit system to SI units + + :param ins: viscosity in [Pa s], [N s / m²] or [lbm / ft / hr] + """ + if self._unit_system is UnitSystem.FLS: + return float(ins / 2419.088311) # lbm/ft/hr to PaS (N*s/m²) return float(ins) - def fromSIunit_my(self, ins): - """function fromSIunit_my = fromSIunit_my( ins )""" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: - return float(ins * 2419.088311) # PaS (N*s/m^2) to lbm/ft/hr + def fromSIunit_my(self, ins: float) -> float: + """ + convert viscosity from SI units to user selected unit system + + :param ins: viscosity in [PaS] or [N*s/m²] + """ + if self._unit_system is UnitSystem.FLS: + return float(ins * 2419.088311) # PaS (N*s/m²) to lbm/ft/hr return float(ins) def __str__(self): - """returns string representation of the selected unit system""" + """ + :return: string representation of the selected unit system + """ result = "" - if self._unit_system is self.__UNIT_SYSTEM_FLS__: + if self._unit_system is UnitSystem.FLS: result = "FLS (ft/lb/sec/°F/psi/btu)" - elif self._unit_system is self.__UNIT_SYSTEM_MKS__: + elif self._unit_system is UnitSystem.MKS: result = "MKS (m/kg/sec/°C/bar/W)" else: result = "BARE (m/kg/sec/K/MPa/W)" diff --git a/pyXSteam/XSteam.py b/pyXSteam/XSteam.py index 6b94b10..0267d32 100755 --- a/pyXSteam/XSteam.py +++ b/pyXSteam/XSteam.py @@ -3,194 +3,234 @@ """Main module for pyXSteam""" import math import logging -from . import RegionSelection + +from .RegionSelection import ( + select_region_pT, + select_region_ph, + select_region_ps, + select_region_hs, + select_region_prho, +) from .Regions import Region1, Region2, Region3, Region4, Region5 -from . import TransportProperties -from . import Constants +from .TransportProperties import ( + my_AllRegions_pT, + my_AllRegions_ph, + tc_ptrho, + surface_tension_T, +) +from .Constants import ( + SPECIFIC_GAS_CONSTANT, + CRITICAL_TEMPERATURE, + CRITICAL_DENSITY, + CRITICAL_PRESSURE, + TRIPLE_POINT_TEMPERATURE, + TRIPLE_POINT_PRESSURE, + FREEZING_TEMPERATURE_H2O, + UnitSystem, + IceType, + DiagramRegion, +) from .UnitConverter import UnitConverter -from . import IAPWS_R14 - - -class XSteam(object): +from .IAPWS_R14 import ( + pmelt_T_iceIh, + pmelt_T_iceIII, + pmelt_T_iceV, + pmelt_T_iceVI, + pmelt_T_iceVII, + psubl_T, +) +from .IAPWS_R12 import eq10 + + +class XSteam: """Main pyXSteam object. Abstract of all other functions to allow auto selection of the correct region for each set of parameters. - Args: - unitSystem (int): set the unit system used for input and output values. - Can be eather 0 (UNIT_SYSTEM_BARE), 1 (UNIT_SYSTEM_MKS) or 2 (UNIT_SYSTEM_FLS). + :param unitSystem: unit system used for input and output values. For supported values + see the enum UnitSystem. """ - # Copy constant Values to expose them to the User - UNIT_SYSTEM_BARE = UnitConverter.__UNIT_SYSTEM_BARE__ - UNIT_SYSTEM_MKS = UnitConverter.__UNIT_SYSTEM_MKS__ - UNIT_SYSTEM_FLS = UnitConverter.__UNIT_SYSTEM_FLS__ + UNIT_SYSTEM_BARE = UnitSystem.BARE + UNIT_SYSTEM_MKS = UnitSystem.MKS + UNIT_SYSTEM_FLS = UnitSystem.FLS - TYPE_ICE_Ih = IAPWS_R14.__TYPE_ICE_Ih__ - TYPE_ICE_III = IAPWS_R14.__TYPE_ICE_III__ - TYPE_ICE_V = IAPWS_R14.__TYPE_ICE_V__ - TYPE_ICE_VI = IAPWS_R14.__TYPE_ICE_VI__ - TYPE_ICE_VII = IAPWS_R14.__TYPE_ICE_VII__ + TYPE_ICE_Ih = IceType.Ih + TYPE_ICE_III = IceType.III + TYPE_ICE_V = IceType.V + TYPE_ICE_VI = IceType.VI + TYPE_ICE_VII = IceType.VII - def __init__(self, unitSystem=UnitConverter.__UNIT_SYSTEM_BARE__): - self.logger = logging.getLogger(__name__) + def __init__(self, unitSystem: UnitSystem = UnitSystem.BARE): + """ + Constructor method + """ + self.logger = logging.getLogger("pyXSteam") self._unit_converter = UnitConverter(unitSystem) - self.logger.info( - "initialised pyXSteam with Unit System %s", self._unit_converter - ) + self.logger.info("initialised pyXSteam with Unit System %s", self._unit_converter) def specificGasConstant(self): - """returns the specific Gas Constant R in kJ kg^-1 K^-1""" - return Constants.__SPECIFIC_GAS_CONSTANT__ + """ + :return: specific Gas Constant R in kJ kg^-1 K^-1 + """ + return SPECIFIC_GAS_CONSTANT def criticalTemperatur(self): - """returns the specific temperature with conversion to the selected unit system""" - return self._unit_converter.fromSIunit_T(Constants.__CRITICAL_TEMPERATURE__) + """ + :return: specific temperature with conversion to the selected unit system + """ + return self._unit_converter.fromSIunit_T(CRITICAL_TEMPERATURE) def criticalPressure(self): - """returns the specific pressure with conversion to the selected unit system""" - return self._unit_converter.fromSIunit_p(Constants.__CRITICAL_PRESSURE__) + """ + :return: specific pressure with conversion to the selected unit system + """ + return self._unit_converter.fromSIunit_p(CRITICAL_PRESSURE) def criticalDensity(self): - """returns the specific density with conversion to the selected unit system""" - return self._unit_converter.fromSIunit_p(Constants.__CRITICAL_DENSITY__) + """ + :return: specific density with conversion to the selected unit system + """ + return self._unit_converter.fromSIunit_p(CRITICAL_DENSITY) def triplePointTemperatur(self): - """returns the temperature of the triple point with conversion to the selected unit system""" - return self._unit_converter.fromSIunit_T(Constants.__TRIPLE_POINT_TEMPERATURE__) + """ + :return: temperature of the triple point with conversion to the selected unit system + """ + return self._unit_converter.fromSIunit_T(TRIPLE_POINT_TEMPERATURE) def triplePointPressure(self): - """returns the Pressure of the triple poin with conversion to the selected unit systemt""" - return self._unit_converter.fromSIunit_p(Constants.__TRIPLE_POINT_PRESSURE__) + """ + :return: Pressure of the triple point with conversion to the selected unit systemt + """ + return self._unit_converter.fromSIunit_p(TRIPLE_POINT_PRESSURE) def zeroPointTemperature(self): - """returns the absolute zero temperature with conversion to the selected unit system""" + """ + :return: absolute zero temperature with conversion to the selected unit system + """ return self._unit_converter.fromSIunit_T(0.0) - # *********************************************************************************************************** - # Section 1.2 temperature - def tsat_p(self, p): - """Saturation-temperature as a function of pressure + def tsat_p(self, p: float) -> float: + """ + Section 1.2 temperature + Saturation-temperature as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - tsat (float): saturation temperature or NaN if arguments are out of range + :return: saturation temperature or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: return self._unit_converter.fromSIunit_T(Region4.T4_p(p)) - else: - self.logger.warning("pressure %f out of range", p) - return float("NaN") + self.logger.warning("pressure %f out of range", p) + return float("NaN") - def tsat_s(self, s): - """Saturation-temperature as a function of entropy + def tsat_s(self, s: float) -> float: + """ + Section 1.2 temperature + Saturation-temperature as a function of entropy - Args: - s (float): entropy value + :param s: specific entropy - Returns: - tsat (float): saturation temperature or NaN if arguments are out of range + :return: saturation temperature or NaN if arguments are out of range """ s = self._unit_converter.toSIunit_s(s) - if (s > -0.0001545495919) and (s < 9.155759395): + if -0.0001545495919 < s < 9.155759395: ps = Region4.p4_s(s) return self._unit_converter.fromSIunit_T(Region4.T4_p(ps)) - else: - self.logger.warning("entropy value %f is out of range", s) - return float("NaN") - def t_ph(self, p, h): - """temperature as a function of pressure and enthalpy + self.logger.warning("entropy value %f is out of range", s) + return float("NaN") + + def t_ph(self, p: float, h: float) -> float: + """ + Section 1.2 temperature + temperature as a function of pressure and enthalpy - Args: - p (float): preasure value - h (float): enthalpy value + :param p: preasure + :param h: enthalpy - Returns: - t (float): temperature or NaN if arguments are out of range + :return: temperature or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) h = self._unit_converter.toSIunit_h(h) - region = RegionSelection.region_ph(p, h) - if region == 1: + region = select_region_ph(p, h) + if region == DiagramRegion.R1: return self._unit_converter.fromSIunit_T(Region1.T1_ph(p, h)) - elif region == 2: + if region == DiagramRegion.R2: return self._unit_converter.fromSIunit_T(Region2.T2_ph(p, h)) - elif region == 3: + if region == DiagramRegion.R3: return self._unit_converter.fromSIunit_T(Region3.T3_ph(p, h)) - elif region == 4: + if region == DiagramRegion.R4: return self._unit_converter.fromSIunit_T(Region4.T4_p(p)) - elif region == 5: + if region == DiagramRegion.R5: return self._unit_converter.fromSIunit_T(Region5.T5_ph(p, h)) - else: - self.logger.warning( - "Region switch t_ph returned unknown value %d for input p %f and h %f", - region, - p, - h, - ) - return float("NaN") - def t_ps(self, p, s): - """temperature as a function of pressure and entropy + self.logger.warning( + "Region switch t_ph returned unknown value %d for input p %f and h %f", + region, + p, + h, + ) + return float("NaN") + + def t_ps(self, p: float, s: float) -> float: + """ + Section 1.2 temperature + temperature as a function of pressure and entropy - Args: - p (float): preasure value - s (float): entropy value - h (float): enthalpy value + :param p: preasure + :param s: specific entropy - Returns: - t (float): temperature or NaN if arguments are out of range + :return: temperature or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) s = self._unit_converter.toSIunit_s(s) - region = RegionSelection.region_ps(p, s) - if region == 1: + region = select_region_ps(p, s) + if region == DiagramRegion.R1: return self._unit_converter.fromSIunit_T(Region1.T1_ps(p, s)) - elif region == 2: + if region == DiagramRegion.R2: return self._unit_converter.fromSIunit_T(Region2.T2_ps(p, s)) - elif region == 3: + if region == DiagramRegion.R3: return self._unit_converter.fromSIunit_T(Region3.T3_ps(p, s)) - elif region == 4: + if region == DiagramRegion.R4: return self._unit_converter.fromSIunit_T(Region4.T4_p(p)) - elif region == 5: + if region == DiagramRegion.R5: return self._unit_converter.fromSIunit_T(Region5.T5_ps(p, s)) - else: - self.logger.warning( - "Region switch t_ps returned unknown value %d for input p %f and s %f", - region, - p, - s, - ) - return float("NaN") - def t_hs(self, h, s): - """temperature as a function of enthalpy and entropy + self.logger.warning( + "Region switch t_ps returned unknown value %d for input p %f and s %f", + region, + p, + s, + ) + return float("NaN") + + def t_hs(self, h: float, s: float) -> float: + """ + Section 1.2 temperature + temperature as a function of enthalpy and entropy - Args: - h (float): enthalpy value - s (float): entropy value + :param h: enthalpy + :param s: specific entropy - Returns: - t (float): temperature or NaN if arguments are out of range + :return: temperature or NaN if arguments are out of range """ h = self._unit_converter.toSIunit_h(h) s = self._unit_converter.toSIunit_s(s) - region = RegionSelection.region_hs(h, s) - if region == 1: + region = select_region_hs(h, s) + if region == DiagramRegion.R1: p1 = Region1.p1_hs(h, s) return self._unit_converter.fromSIunit_T(Region1.T1_ph(p1, h)) - elif region == 2: + elif region == DiagramRegion.R2: p2 = Region2.p2_hs(h, s) return self._unit_converter.fromSIunit_T(Region2.T2_ph(p2, h)) - elif region == 3: + elif region == DiagramRegion.R3: p3 = Region3.p3_hs(h, s) return self._unit_converter.fromSIunit_T(Region3.T3_ph(p3, h)) - elif region == 4: + elif region == DiagramRegion.R4: return self._unit_converter.fromSIunit_T(Region4.T4_hs(h, s)) - elif region == 5: + elif region == DiagramRegion.R5: self.logger.error( "functions t_hs is not available in region 5 for input h %f and s %f", h, @@ -206,63 +246,61 @@ def t_hs(self, h, s): ) return float("NaN") - # *********************************************************************************************************** - # Section 1.3 Pressure (p) - def psat_s(self, s): - """Saturation-Pressure as a function of entropy + def psat_s(self, s: float) -> float: + """ + Section 1.3 Pressure + Saturation-Pressure as a function of entropy - Args: - s (float): entropy value + :param s: specific entropy - Returns: - psat (float): saturation pressure or NaN if arguments are out of range + :return: saturation pressure or NaN if arguments are out of range """ s = self._unit_converter.toSIunit_s(s) - if (s > -0.0001545495919) and (s < 9.155759395): + if -0.0001545495919 < s < 9.155759395: return self._unit_converter.fromSIunit_p(Region4.p4_s(s)) - else: - self.logger.warning("entropy value %f out of range", s) - return float("NaN") - def psat_t(self, t): - """Saturation-Pressure as a function of temperature + self.logger.warning("entropy value %f out of range", s) + return float("NaN") + + def psat_t(self, t: float) -> float: + """ + Section 1.3 Pressure + Saturation-Pressure as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - psat (float): saturation pressure or NaN if arguments are out of range + :return: saturation pressure or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if (T < 647.096) and (T > 273.1): + if 273.1 < T < CRITICAL_TEMPERATURE: return self._unit_converter.fromSIunit_p(Region4.p4_T(T)) else: self.logger.warning("temperature %f out of range", T) return float("NaN") - def p_hs(self, h, s): - """Pressure as a function of enthalpy and entropy + def p_hs(self, h: float, s: float) -> float: + """ + Section 1.3 Pressure + Pressure as a function of enthalpy and entropy - Args: - h (float): enthalpy value - s (float): entropy value + :param h: enthalpy + :param s: specific entropy - Returns: - p (float): pressure or NaN if arguments are out of range + :return: pressure or NaN if arguments are out of range """ h = self._unit_converter.toSIunit_h(h) s = self._unit_converter.toSIunit_s(s) - region = RegionSelection.region_hs(h, s) - if region == 1: + region = select_region_hs(h, s) + if region == DiagramRegion.R1: return self._unit_converter.fromSIunit_p(Region1.p1_hs(h, s)) - elif region == 2: + elif region == DiagramRegion.R2: return self._unit_converter.fromSIunit_p(Region2.p2_hs(h, s)) - elif region == 3: + elif region == DiagramRegion.R3: return self._unit_converter.fromSIunit_p(Region3.p3_hs(h, s)) - elif region == 4: + elif region == DiagramRegion.R4: tSat = Region4.T4_hs(h, s) return self._unit_converter.fromSIunit_p(Region4.p4_T(tSat)) - elif region == 5: + elif region == DiagramRegion.R5: self.logger.warning( "functions p_hs is not available in region 5 for input h %f and s %f", h, @@ -278,27 +316,28 @@ def p_hs(self, h, s): ) return float("NaN") - def p_hrho(self, h, rho): - """Pressure as a function of h and rho. + def p_hrho(self, h: float, rho: float) -> float: + """ + Section 1.3 Pressure + Pressure as a function of h and rho. Very unaccurate for solid water region since it's almost incompressible! Not valid for water or sumpercritical since water rho does not change very much with p. Uses iteration to find p. - Args: - h (float): enthalpy value - rho (float): density value + :param h: enthalpy + :param rho: density - Returns: - p (float): pressure or NaN if arguments are out of range + :raises ValueError: value of density is zero or negative + + :return: pressure or NaN if arguments are out of range """ if rho <= 0.0: - self.logger.error( - "negative values for density rho not allowed %f", rho) + self.logger.error("negative values for density rho not allowed %f", rho) raise ValueError("rho out of range") h = self._unit_converter.toSIunit_h(h) High_Bound = self._unit_converter.fromSIunit_p(100) - Low_Bound = self._unit_converter.fromSIunit_p(0.000611657) + Low_Bound = self._unit_converter.fromSIunit_p(TRIPLE_POINT_PRESSURE) ps = self._unit_converter.fromSIunit_p(10) rhos = 1 / self.v_ph(ps, h) step_counter = 0 @@ -324,201 +363,177 @@ def p_hrho(self, h, rho): ps = (Low_Bound + High_Bound) / 2 return ps - # *********************************************************************************************************** - # Section 1.4 Enthalpy (h) - def hV_p(self, p): - """Saturated vapour enthalpy as a function of pressure + def hV_p(self, p: float) -> float: + """ + Section 1.4 enthalpy + Saturated vapour enthalpy as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - hV (float): saturated vapour enthalpy or NaN if arguments are out of range + :return: saturated vapour enthalpy or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: return self._unit_converter.fromSIunit_h(Region4.h4V_p(p)) - else: - self.logger.warning("pressure %f out of range", p) - return float("NaN") + self.logger.warning("pressure %f out of range", p) + return float("NaN") - def hL_p(self, p): - """Saturated liquid enthalpy as a function of pressure + def hL_p(self, p: float) -> float: + """ + Section 1.4 enthalpy + Saturated liquid enthalpy as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - hL (float): saturated liquid enthalpy or NaN if arguments are out of range + :return: saturated liquid enthalpy or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: return self._unit_converter.fromSIunit_h(Region4.h4L_p(p)) - else: - self.logger.warning("pressure %f out of range", p) - return float("NaN") + self.logger.warning("pressure %f out of range", p) + return float("NaN") - def hV_t(self, t): - """Saturated vapour enthalpy as a function of temperature + def hV_t(self, t: float) -> float: + """ + Section 1.4 enthalpy + Saturated vapour enthalpy as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - hV (float): saturated vapour enthalpy or NaN if arguments are out of range + :return: saturated vapour enthalpy or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if (T > 273.15) and (T < 647.096): + if FREEZING_TEMPERATURE_H2O < T < CRITICAL_TEMPERATURE: p = Region4.p4_T(T) return self._unit_converter.fromSIunit_h(Region4.h4V_p(p)) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + self.logger.warning("temperature %f out of range", T) + return float("NaN") - def hL_t(self, t): - """Saturated liquid enthalpy as a function of temperature + def hL_t(self, t: float) -> float: + """ + Section 1.4 enthalpy + Saturated liquid enthalpy as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - hL (float): saturated liquid enthalpy or NaN if arguments are out of range + :return: saturated liquid enthalpy or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if (T > 273.15) and (T < 647.096): + if FREEZING_TEMPERATURE_H2O < T < CRITICAL_TEMPERATURE: p = Region4.p4_T(T) return self._unit_converter.fromSIunit_h(Region4.h4L_p(p)) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + self.logger.warning("temperature %f out of range", T) + return float("NaN") - def h_pt(self, p, t): - """Entalpy as a function of pressure and temperature + def h_pt(self, p: float, t: float) -> float: + """ + Section 1.4 enthalpy + Entalpy as a function of pressure and temperature - Args: - p (float): preasure value - t (float): temperature value + :param p: preasure + :param t: temperature - Returns: - h (float): enthalpy or NaN if arguments are out of range + :return: enthalpy or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) T = self._unit_converter.toSIunit_T(t) - region = RegionSelection.region_pT(p, T) - if region == 1: + region = select_region_pT(p, T) + if region == DiagramRegion.R1: return self._unit_converter.fromSIunit_h(Region1.h1_pT(p, T)) - elif region == 2: + if region == DiagramRegion.R2: return self._unit_converter.fromSIunit_h(Region2.h2_pT(p, T)) - elif region == 3: + if region == DiagramRegion.R3: return self._unit_converter.fromSIunit_h(Region3.h3_pT(p, T)) - elif region == 4: + if region == DiagramRegion.R4: self.logger.warning( "function h_pt is not available in region 4 for input p %f and T %f", p, T, ) return float("NaN") - elif region == 5: + if region == DiagramRegion.R5: return self._unit_converter.fromSIunit_h(Region5.h5_pT(p, T)) - else: - self.logger.warning( - "Region switch h_pt returned unknown value %d for input p %f and T %f", - region, - p, - T, - ) - return float("NaN") - def h_ps(self, p, s): - """Entalpy as a function of pressure and entropy + self.logger.warning( + "Region switch h_pt returned unknown value %d for input p %f and T %f", + region, + p, + T, + ) + return float("NaN") + + def h_ps(self, p: float, s: float) -> float: + """ + Section 1.4 enthalpy + Entalpy as a function of pressure and entropy - Args: - p (float): preasure value - s (float): entropy value + :param p: preasure + :param s: specific entropy - Returns: - h (float): enthalpy or NaN if arguments are out of range + :return: enthalpy or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) s = self._unit_converter.toSIunit_s(s) - region = RegionSelection.region_ps(p, s) - if region == 1: - return self._unit_converter.fromSIunit_h( - Region1.h1_pT(p, Region1.T1_ps(p, s)) - ) - elif region == 2: - return self._unit_converter.fromSIunit_h( - Region2.h2_pT(p, Region2.T2_ps(p, s)) - ) - elif region == 3: - return self._unit_converter.fromSIunit_h( - Region3.h3_rhoT(1 / Region3.v3_ps(p, s), Region3.T3_ps(p, s)) - ) - elif region == 4: + region = select_region_ps(p, s) + if region == DiagramRegion.R1: + return self._unit_converter.fromSIunit_h(Region1.h1_pT(p, Region1.T1_ps(p, s))) + if region == DiagramRegion.R2: + return self._unit_converter.fromSIunit_h(Region2.h2_pT(p, Region2.T2_ps(p, s))) + if region == DiagramRegion.R3: + return self._unit_converter.fromSIunit_h(Region3.h3_rhoT(1 / Region3.v3_ps(p, s), Region3.T3_ps(p, s))) + if region == DiagramRegion.R4: xs = Region4.x4_ps(p, s) - return self._unit_converter.fromSIunit_h( - xs * Region4.h4V_p(p) + (1 - xs) * Region4.h4L_p(p) - ) - elif region == 5: - return self._unit_converter.fromSIunit_h( - Region5.h5_pT(p, Region5.T5_ps(p, s)) - ) - else: - self.logger.warning( - "Region switch h_ps returned unknown value %d for input p %f and s %f ", - region, - p, - s, - ) - return float("NaN") + return self._unit_converter.fromSIunit_h(xs * Region4.h4V_p(p) + (1 - xs) * Region4.h4L_p(p)) + if region == DiagramRegion.R5: + return self._unit_converter.fromSIunit_h(Region5.h5_pT(p, Region5.T5_ps(p, s))) + + self.logger.warning( + "Region switch h_ps returned unknown value %d for input p %f and s %f ", + region, + p, + s, + ) + return float("NaN") - def h_px(self, p, x): - """Entalpy as a function of pressure and vapour fraction + def h_px(self, p: float, x: float) -> float: + """ + Section 1.4 enthalpy + Entalpy as a function of pressure and vapour fraction - Args: - p (float): preasure value + :param p: preasure x (float): vapour fraction value - Returns: - h (float): enthalpy or NaN if arguments are out of range + :return: enthalpy or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) x = self._unit_converter.toSIunit_x(x) if (x > 1) or (x < 0) or (p >= 22.064): - self.logger.warning( - "Vapor fraction %f and/or pressure %f out of range", x, p - ) + self.logger.warning("Vapor fraction %f and/or pressure %f out of range", x, p) return float("NaN") hL = Region4.h4L_p(p) hV = Region4.h4V_p(p) return self._unit_converter.fromSIunit_h(hL + x * (hV - hL)) - def h_prho(self, p, rho): - """Entalpy as a function of pressure and density. Observe for low temperatures (liquid) this equation has 2 solutions + def h_prho(self, p: float, rho: float) -> float: + """ + Section 1.4 enthalpy + Entalpy as a function of pressure and density. Observe for low temperatures (liquid) this equation has 2 solutions - Args: - p (float): preasure value + :param p: preasure rho (float): density value - Returns: - h (float): enthalpy or NaN if arguments are out of range + :return: enthalpy or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) rho = 1 / self._unit_converter.toSIunit_v(1 / float(rho)) - region = RegionSelection.region_prho(p, rho) - if region == 1: - return self._unit_converter.fromSIunit_h( - Region1.h1_pT(p, Region1.T1_prho(p, rho)) - ) - elif region == 2: - return self._unit_converter.fromSIunit_h( - Region2.h2_pT(p, Region2.T2_prho(p, rho)) - ) - elif region == 3: - return self._unit_converter.fromSIunit_h( - Region3.h3_rhoT(rho, Region3.T3_prho(p, rho)) - ) - elif region == 4: + region = select_region_prho(p, rho) + if region == DiagramRegion.R1: + return self._unit_converter.fromSIunit_h(Region1.h1_pT(p, Region1.T1_prho(p, rho))) + if region == DiagramRegion.R2: + return self._unit_converter.fromSIunit_h(Region2.h2_pT(p, Region2.T2_prho(p, rho))) + if region == DiagramRegion.R3: + return self._unit_converter.fromSIunit_h(Region3.h3_rhoT(rho, Region3.T3_prho(p, rho))) + if region == DiagramRegion.R4: if p < 16.529: vV = Region2.v2_pT(p, Region4.T4_p(p)) vL = Region1.v1_pT(p, Region4.T4_p(p)) @@ -529,201 +544,163 @@ def h_prho(self, p, rho): hL = Region4.h4L_p(p) x = (1 / rho - vL) / (vV - vL) return self._unit_converter.fromSIunit_h((1 - x) * hL + x * hV) - elif region == 5: - return self._unit_converter.fromSIunit_h( - Region5.h5_pT(p, Region5.T5_prho(p, rho)) - ) - else: - self.logger.warning( - "Region switch h_prho returned unknown value %d for input p %f and rho %f", - region, - p, - rho, - ) - return float("NaN") + if region == DiagramRegion.R5: + return self._unit_converter.fromSIunit_h(Region5.h5_pT(p, Region5.T5_prho(p, rho))) + + self.logger.warning( + "Region switch h_prho returned unknown value %d for input p %f and rho %f", + region, + p, + rho, + ) + return float("NaN") - def h_tx(self, t, x): - """Entalpy as a function of temperature and vapour fraction + def h_tx(self, t: float, x: float) -> float: + """ + Section 1.4 enthalpy + Entalpy as a function of temperature and vapour fraction - Args: - t (float): temperature value + :param t: temperature x (float): vapour fraction value - Returns: - h (float): enthalpy or NaN if arguments are out of range + :return: enthalpy or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) x = self._unit_converter.toSIunit_x(x) - if (x > 1) or (x < 0) or (T >= 647.096): - self.logger.warning( - "Vapor fraction %f and/or temperature %f out of range", x, T - ) + if (x > 1) or (x < 0) or (T >= CRITICAL_TEMPERATURE): + self.logger.warning("Vapor fraction %f and/or temperature %f out of range", x, T) return float("NaN") p = Region4.p4_T(T) hL = Region4.h4L_p(p) hV = Region4.h4V_p(p) return self._unit_converter.fromSIunit_h(hL + x * (hV - hL)) - # *********************************************************************************************************** - # Section 1.5 Specific Volume (v) - def vV_p(self, p): - """Saturated vapour volume as a function of pressure + def vV_p(self, p: float) -> float: + """ + Section 1.5 Specific Volume + Saturated vapour volume as a function of pressure - Args: - p (float): preasure value + :param p: preasure x (float): vapour fraction value - Returns: - vV (float): saturated vapour volume or NaN if arguments are out of range + :return: saturated vapour volume or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: if p < 16.529: - return self._unit_converter.fromSIunit_v( - Region2.v2_pT(p, Region4.T4_p(p)) - ) - else: - return self._unit_converter.fromSIunit_v( - Region3.v3_ph(p, Region4.h4V_p(p)) - ) - else: - self.logger.warning("pressure %f out of range", p) - return float("NaN") + return self._unit_converter.fromSIunit_v(Region2.v2_pT(p, Region4.T4_p(p))) + return self._unit_converter.fromSIunit_v(Region3.v3_ph(p, Region4.h4V_p(p))) + self.logger.warning("pressure %f out of range", p) + return float("NaN") - def vL_p(self, p): - """Saturated liquid volume as a function of pressure + def vL_p(self, p: float) -> float: + """ + Section 1.5 Specific Volume + Saturated liquid volume as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - vV (float): saturated liquid volume or NaN if arguments are out of range + :return: saturated liquid volume or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: if p < 16.529: - return self._unit_converter.fromSIunit_v( - Region1.v1_pT(p, Region4.T4_p(p)) - ) - else: - return self._unit_converter.fromSIunit_v( - Region3.v3_ph(p, Region4.h4L_p(p)) - ) - else: - self.logger.warning("pressure %f out of range", p) - return float("NaN") + return self._unit_converter.fromSIunit_v(Region1.v1_pT(p, Region4.T4_p(p))) + return self._unit_converter.fromSIunit_v(Region3.v3_ph(p, Region4.h4L_p(p))) + self.logger.warning("pressure %f out of range", p) + return float("NaN") - def vV_t(self, t): - """Saturated vapour volume as a function of temperature + def vV_t(self, t: float) -> float: + """ + Section 1.5 Specific Volume + Saturated vapour volume as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - vV (float): saturated vapour volume or NaN if arguments are out of range + :return: saturated vapour volume or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if (T > 273.15) and (T < 647.096): + if FREEZING_TEMPERATURE_H2O < T < CRITICAL_TEMPERATURE: if T <= 623.15: - return self._unit_converter.fromSIunit_v( - Region2.v2_pT(Region4.p4_T(T), T) - ) - else: - return self._unit_converter.fromSIunit_v( - Region3.v3_ph(Region4.p4_T( - T), Region4.h4V_p(Region4.p4_T(T))) - ) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + return self._unit_converter.fromSIunit_v(Region2.v2_pT(Region4.p4_T(T), T)) + return self._unit_converter.fromSIunit_v(Region3.v3_ph(Region4.p4_T(T), Region4.h4V_p(Region4.p4_T(T)))) + self.logger.warning("temperature %f out of range", T) + return float("NaN") - def vL_t(self, t): - """Saturated liquid volume as a function of temperature + def vL_t(self, t: float) -> float: + """ + Section 1.5 Specific Volume + Saturated liquid volume as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - vV (float): saturated liquid volume or NaN if arguments are out of range + :return: saturated liquid volume or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if (T > 273.15) and (T < 647.096): + if FREEZING_TEMPERATURE_H2O < T < CRITICAL_TEMPERATURE: if T <= 623.15: - return self._unit_converter.fromSIunit_v( - Region1.v1_pT(Region4.p4_T(T), T) - ) - else: - return self._unit_converter.fromSIunit_v( - Region3.v3_ph(Region4.p4_T( - T), Region4.h4L_p(Region4.p4_T(T))) - ) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + return self._unit_converter.fromSIunit_v(Region1.v1_pT(Region4.p4_T(T), T)) + return self._unit_converter.fromSIunit_v(Region3.v3_ph(Region4.p4_T(T), Region4.h4L_p(Region4.p4_T(T)))) + self.logger.warning("temperature %f out of range", T) + return float("NaN") - def v_pt(self, p, t): - """Specific volume as a function of pressure and temperature + def v_pt(self, p: float, t: float) -> float: + """ + Section 1.5 Specific Volume + Specific volume as a function of pressure and temperature - Args: - p (float): preasure value - t (float): temperature value + :param p: preasure + :param t: temperature - Returns: - v (float): specific volume or NaN if arguments are out of range + :return: specific volume or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) T = self._unit_converter.toSIunit_T(t) - region = RegionSelection.region_pT(p, T) - if region == 1: + region = select_region_pT(p, T) + if region == DiagramRegion.R1: return self._unit_converter.fromSIunit_v(Region1.v1_pT(p, T)) - elif region == 2: + if region == DiagramRegion.R2: return self._unit_converter.fromSIunit_v(Region2.v2_pT(p, T)) - elif region == 3: - return self._unit_converter.fromSIunit_v( - Region3.v3_ph(p, Region3.h3_pT(p, T)) - ) - elif region == 4: + if region == DiagramRegion.R3: + return self._unit_converter.fromSIunit_v(Region3.v3_ph(p, Region3.h3_pT(p, T))) + if region == DiagramRegion.R4: self.logger.warning( "function v_pt is not available in region 4 for input p %f and T %f", p, T, ) return float("NaN") - elif region == 5: + if region == DiagramRegion.R5: return self._unit_converter.fromSIunit_v(Region5.v5_pT(p, T)) - else: - self.logger.warning( - "Region switch v_pt returned unknown value %d for input p %f and T %f", - region, - p, - T, - ) - return float("NaN") - def v_ph(self, p, h): - """Specific volume as a function of pressure and enthalpy + self.logger.warning( + "Region switch v_pt returned unknown value %d for input p %f and T %f", + region, + p, + T, + ) + return float("NaN") + + def v_ph(self, p: float, h: float) -> float: + """ + Section 1.5 Specific Volume + Specific volume as a function of pressure and enthalpy - Args: - p (float): preasure value - h (float): enthalpy value + :param p: preasure + :param h: enthalpy - Returns: - v (float): specific volume or NaN if arguments are out of range + :return: specific volume or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) h = self._unit_converter.toSIunit_h(h) - region = RegionSelection.region_ph(p, h) - if region == 1: - return self._unit_converter.fromSIunit_v( - Region1.v1_pT(p, Region1.T1_ph(p, h)) - ) - elif region == 2: - return self._unit_converter.fromSIunit_v( - Region2.v2_pT(p, Region2.T2_ph(p, h)) - ) - elif region == 3: + region = select_region_ph(p, h) + if region == DiagramRegion.R1: + return self._unit_converter.fromSIunit_v(Region1.v1_pT(p, Region1.T1_ph(p, h))) + if region == DiagramRegion.R2: + return self._unit_converter.fromSIunit_v(Region2.v2_pT(p, Region2.T2_ph(p, h))) + if region == DiagramRegion.R3: return self._unit_converter.fromSIunit_v(Region3.v3_ph(p, h)) - elif region == 4: + if region == DiagramRegion.R4: xs = Region4.x4_ph(p, h) if p < 16.529: v4v = Region2.v2_pT(p, Region4.T4_p(p)) @@ -732,42 +709,38 @@ def v_ph(self, p, h): v4v = Region3.v3_ph(p, Region4.h4V_p(p)) v4L = Region3.v3_ph(p, Region4.h4L_p(p)) return self._unit_converter.fromSIunit_v((xs * v4v + (1 - xs) * v4L)) - elif region == 5: + if region == DiagramRegion.R5: Ts = Region5.T5_ph(p, h) return self._unit_converter.fromSIunit_v(Region5.v5_pT(p, Ts)) - else: - self.logger.warning( - "Region switch v_ph returned unknown value %d for input p %f and h %f", - region, - p, - h, - ) - return float("NaN") - def v_ps(self, p, s): - """Specific volume as a function of pressure and entropy + self.logger.warning( + "Region switch v_ph returned unknown value %d for input p %f and h %f", + region, + p, + h, + ) + return float("NaN") + + def v_ps(self, p: float, s: float) -> float: + """ + Section 1.5 Specific Volume + Specific volume as a function of pressure and entropy - Args: - p (float): preasure value - s (float): entropy value + :param p: preasure + :param s: specific entropy - Returns: - v (float): specific volume or NaN if arguments are out of range + :return: specific volume or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) s = self._unit_converter.toSIunit_s(s) - region = RegionSelection.region_ps(p, s) - if region == 1: - return self._unit_converter.fromSIunit_v( - Region1.v1_pT(p, Region1.T1_ps(p, s)) - ) - elif region == 2: - return self._unit_converter.fromSIunit_v( - Region2.v2_pT(p, Region2.T2_ps(p, s)) - ) - elif region == 3: + region = select_region_ps(p, s) + if region == DiagramRegion.R1: + return self._unit_converter.fromSIunit_v(Region1.v1_pT(p, Region1.T1_ps(p, s))) + if region == DiagramRegion.R2: + return self._unit_converter.fromSIunit_v(Region2.v2_pT(p, Region2.T2_ps(p, s))) + if region == DiagramRegion.R3: return self._unit_converter.fromSIunit_v(Region3.v3_ps(p, s)) - elif region == 4: + if region == DiagramRegion.R4: xs = Region4.x4_ps(p, s) if p < 16.529: v4v = Region2.v2_pT(p, Region4.T4_p(p)) @@ -776,276 +749,242 @@ def v_ps(self, p, s): v4v = Region3.v3_ph(p, Region4.h4V_p(p)) v4L = Region3.v3_ph(p, Region4.h4L_p(p)) return self._unit_converter.fromSIunit_v((xs * v4v + (1 - xs) * v4L)) - elif region == 5: + if region == DiagramRegion.R5: Ts = Region5.T5_ps(p, s) return self._unit_converter.fromSIunit_v(Region5.v5_pT(p, Ts)) - else: - self.logger.warning( - "Region switch v_ps returned unknown value %d for input p %f and s %f", - region, - p, - s, - ) - return float("NaN") - # *********************************************************************************************************** - # Section 1.6 Density (rho) - # Density is calculated as 1/v. See section 1.5 Volume - def rhoV_p(self, p): - """Saturated vapour density as a function of pressure + self.logger.warning( + "Region switch v_ps returned unknown value %d for input p %f and s %f", + region, + p, + s, + ) + return float("NaN") + + def rhoV_p(self, p: float) -> float: + """ + Section 1.6 Density (rho) + Note: Density is calculated as 1/v. See section 1.5 Volume + Saturated vapour density as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - rhoV (float): saturated vapour density + :return: saturated vapour density """ return 1 / self.vV_p(p) - def rhoL_p(self, p): - """Saturated liquid density as a function of pressure + def rhoL_p(self, p: float) -> float: + """ + Section 1.6 Density (rho) + Note: Density is calculated as 1/v. See section 1.5 Volume + Saturated liquid density as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - rhoV (float): saturated liquid density + :return: saturated liquid density """ return 1 / self.vL_p(p) - def rhoV_t(self, t): - """Saturated vapour density as a function of temperature + def rhoV_t(self, t: float) -> float: + """ + Section 1.6 Density (rho) + Note: Density is calculated as 1/v. See section 1.5 Volume + Saturated vapour density as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - rhoV (float): saturated vapour density + :return: saturated vapour density """ return 1 / self.vV_t(t) - def rhoL_t(self, t): - """Saturated liquid density as a function of temperature + def rhoL_t(self, t: float) -> float: + """ + Section 1.6 Density (rho) + Note: Density is calculated as 1/v. See section 1.5 Volume + Saturated liquid density as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - rhoV (float): saturated liquid density + :return: saturated liquid density """ return 1 / self.vL_t(t) - def rho_pt(self, p, t): - """Density as a function of pressure and temperature + def rho_pt(self, p: float, t: float) -> float: + """ + Section 1.6 Density (rho) + Note: Density is calculated as 1/v. See section 1.5 Volume + Density as a function of pressure and temperature - Args: - p (float): preasure value - t (float): temperature value + :param p: preasure + :param t: temperature - Returns: - rho (float): density + :return: density """ return 1 / self.v_pt(p, t) - def rho_ph(self, p, h): - """Density as a function of pressure and enthalpy + def rho_ph(self, p: float, h: float) -> float: + """ + Section 1.6 Density (rho) + Note: Density is calculated as 1/v. See section 1.5 Volume + Density as a function of pressure and enthalpy - Args: - p (float): preasure value - h (float): enthalpy value + :param p: preasure + :param h: enthalpy - Returns: - rho (float): density + :return: density """ return 1 / self.v_ph(p, h) - def rho_ps(self, p, s): - """Density as a function of pressure and entropy + def rho_ps(self, p: float, s: float) -> float: + """ + Section 1.6 Density (rho) + Note: Density is calculated as 1/v. See section 1.5 Volume + Density as a function of pressure and entropy - Args: - p (float): preasure value - s (float): entropy value + :param p: preasure + :param s: specific entropy - Returns: - rho (float): density + :return: density """ return 1 / self.v_ps(p, s) - # *********************************************************************************************************** - # Section 1.7 Specific entropy (s) - def sV_p(self, p): - """Saturated vapour entropy as a function of pressure + def sV_p(self, p: float) -> float: + """ + Section 1.7 Specific entropy + Saturated vapour entropy as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - sV (float): Saturated vapour entropy or NaN if arguments are out of range + :return: Saturated vapour entropy or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: if p < 16.529: - return self._unit_converter.fromSIunit_s( - Region2.s2_pT(p, Region4.T4_p(p)) - ) - else: - return self._unit_converter.fromSIunit_s( - Region3.s3_rhoT( - 1 / (Region3.v3_ph(p, Region4.h4V_p(p))), Region4.T4_p(p) - ) - ) - else: - self.logger.warning("pressure %f out of range", p) - return float("NaN") + return self._unit_converter.fromSIunit_s(Region2.s2_pT(p, Region4.T4_p(p))) + return self._unit_converter.fromSIunit_s(Region3.s3_rhoT(1 / (Region3.v3_ph(p, Region4.h4V_p(p))), Region4.T4_p(p))) + self.logger.warning("pressure %f out of range", p) + return float("NaN") - def sL_p(self, p): - """Saturated liquid entropy as a function of pressure + def sL_p(self, p: float) -> float: + """ + Section 1.7 Specific entropy + Saturated liquid entropy as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - sL (float): Saturated liquid entropy or NaN if arguments are out of range + :return: Saturated liquid entropy or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: if p < 16.529: - return self._unit_converter.fromSIunit_s( - Region1.s1_pT(p, Region4.T4_p(p)) - ) - else: - return self._unit_converter.fromSIunit_s( - Region3.s3_rhoT( - 1 / (Region3.v3_ph(p, Region4.h4L_p(p))), Region4.T4_p(p) - ) - ) - else: - self.logger.warning("pressure %f out of range", p) - return float("NaN") + return self._unit_converter.fromSIunit_s(Region1.s1_pT(p, Region4.T4_p(p))) + return self._unit_converter.fromSIunit_s(Region3.s3_rhoT(1 / (Region3.v3_ph(p, Region4.h4L_p(p))), Region4.T4_p(p))) + self.logger.warning("pressure %f out of range", p) + return float("NaN") - def sV_t(self, t): - """Saturated vapour entropy as a function of temperature + def sV_t(self, t: float) -> float: + """ + Section 1.7 Specific entropy + Saturated vapour entropy as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - sV (float): Saturated vapour entropy or NaN if arguments are out of range + :return: Saturated vapour entropy or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if (T > 273.15) and (T < 647.096): + if FREEZING_TEMPERATURE_H2O < T < CRITICAL_TEMPERATURE: if T <= 623.15: - return self._unit_converter.fromSIunit_s( - Region2.s2_pT(Region4.p4_T(T), T) - ) - else: - return self._unit_converter.fromSIunit_s( - Region3.s3_rhoT( - 1 - / ( - Region3.v3_ph( - Region4.p4_T(T), Region4.h4V_p(Region4.p4_T(T)) - ) - ), - T, - ) + return self._unit_converter.fromSIunit_s(Region2.s2_pT(Region4.p4_T(T), T)) + return self._unit_converter.fromSIunit_s( + Region3.s3_rhoT( + 1 / (Region3.v3_ph(Region4.p4_T(T), Region4.h4V_p(Region4.p4_T(T)))), + T, ) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + ) + self.logger.warning("temperature %f out of range", T) + return float("NaN") - def sL_t(self, t): - """Saturated liquid entropy as a function of temperature + def sL_t(self, t: float) -> float: + """ + Section 1.7 Specific entropy + Saturated liquid entropy as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - sL (float): Saturated liquid entropy or NaN if arguments are out of range + :return: Saturated liquid entropy or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if (T > 273.15) and (T < 647.096): + if FREEZING_TEMPERATURE_H2O < T < CRITICAL_TEMPERATURE: if T <= 623.15: - return self._unit_converter.fromSIunit_s( - Region1.s1_pT(Region4.p4_T(T), T) - ) - else: - return self._unit_converter.fromSIunit_s( - Region3.s3_rhoT( - 1 - / ( - Region3.v3_ph( - Region4.p4_T(T), Region4.h4L_p(Region4.p4_T(T)) - ) - ), - T, - ) + return self._unit_converter.fromSIunit_s(Region1.s1_pT(Region4.p4_T(T), T)) + return self._unit_converter.fromSIunit_s( + Region3.s3_rhoT( + 1 / (Region3.v3_ph(Region4.p4_T(T), Region4.h4L_p(Region4.p4_T(T)))), + T, ) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + ) + self.logger.warning("temperature %f out of range", T) + return float("NaN") - def s_pt(self, p, t): - """Specific entropy as a function of pressure and temperature (Returns saturated vapour entalpy if mixture) + def s_pt(self, p: float, t: float) -> float: + """ + Section 1.7 Specific entropy + Specific entropy as a function of pressure and temperature (Returns saturated vapour entalpy if mixture) - Args: - p (float): preasure value - t (float): temperature value + :param p: preasure + :param t: temperature - Returns: - s (float): entropy or NaN if arguments are out of range + :return: entropy or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) T = self._unit_converter.toSIunit_T(t) - region = RegionSelection.region_pT(p, T) - if region == 1: + region = select_region_pT(p, T) + if region == DiagramRegion.R1: return self._unit_converter.fromSIunit_s(Region1.s1_pT(p, T)) - elif region == 2: + if region == DiagramRegion.R2: return self._unit_converter.fromSIunit_s(Region2.s2_pT(p, T)) - elif region == 3: + if region == DiagramRegion.R3: hs = Region3.h3_pT(p, T) rhos = 1 / Region3.v3_ph(p, hs) return self._unit_converter.fromSIunit_s(Region3.s3_rhoT(rhos, T)) - elif region == 4: - self.logger.warning( - "function s_pt is not available in region 4 (p %f, T %f)", p, T - ) + if region == DiagramRegion.R4: + self.logger.warning("function s_pt is not available in region 4 (p %f, T %f)", p, T) return float("NaN") - elif region == 5: + if region == DiagramRegion.R5: return self._unit_converter.fromSIunit_s(Region5.s5_pT(p, T)) - else: - self.logger.warning( - "Region switch s_pt returned unknown value %d for input p %f and T %f", - region, - p, - T, - ) - return float("NaN") - def s_ph(self, p, h): - """Specific entropy as a function of pressure and enthalpy + self.logger.warning( + "Region switch s_pt returned unknown value %d for input p %f and T %f", + region, + p, + T, + ) + return float("NaN") + + def s_ph(self, p: float, h: float) -> float: + """ + Section 1.7 Specific entropy + Specific entropy as a function of pressure and enthalpy - Args: - p (float): preasure value - h (float): enthalpy value + :param p: preasure + :param h: enthalpy - Returns: - s (float): entropy or NaN if arguments are out of range + :return: entropy or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) h = self._unit_converter.toSIunit_h(h) - region = RegionSelection.region_ph(p, h) - if region == 1: + region = select_region_ph(p, h) + if region == DiagramRegion.R1: T = Region1.T1_ph(p, h) return self._unit_converter.fromSIunit_s(Region1.s1_pT(p, T)) - elif region == 2: + if region == DiagramRegion.R2: T = Region2.T2_ph(p, h) return self._unit_converter.fromSIunit_s(Region2.s2_pT(p, T)) - elif region == 3: + if region == DiagramRegion.R3: rhos = 1 / Region3.v3_ph(p, h) Ts = Region3.T3_ph(p, h) return self._unit_converter.fromSIunit_s(Region3.s3_rhoT(rhos, Ts)) - elif region == 4: + if region == DiagramRegion.R4: Ts = Region4.T4_p(p) xs = Region4.x4_ph(p, h) if p < 16.529: @@ -1057,194 +996,168 @@ def s_ph(self, p, h): v4L = Region3.v3_ph(p, Region4.h4L_p(p)) s4L = Region3.s3_rhoT(1 / v4L, Ts) return self._unit_converter.fromSIunit_s((xs * s4v + (1 - xs) * s4L)) - elif region == 5: + if region == DiagramRegion.R5: T = Region5.T5_ph(p, h) return self._unit_converter.fromSIunit_s(Region5.s5_pT(p, T)) - else: - self.logger.warning( - "Region switch s_ph returned unknown value %d for input p %f and h %f", - region, - p, - h, - ) - return float("NaN") + self.logger.warning( + "Region switch s_ph returned unknown value %d for input p %f and h %f", + region, + p, + h, + ) + return float("NaN") - # *********************************************************************************************************** - # Section 1.8 Specific internal energy (u) - def uV_p(self, p): - """Saturated vapour internal energy as a function of pressure + def uV_p(self, p: float) -> float: + """ + Section 1.8 Specific internal energy + Saturated vapour internal energy as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - uV (float): saturated vapour internal energy or NaN if arguments are out of range + :return: saturated vapour internal energy or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: if p < 16.529: - return self._unit_converter.fromSIunit_u( - Region2.u2_pT(p, Region4.T4_p(p)) - ) - else: - return self._unit_converter.fromSIunit_u( - Region3.u3_rhoT( - 1 / (Region3.v3_ph(p, Region4.h4V_p(p))), Region4.T4_p(p) - ) - ) - else: - return float("NaN") + return self._unit_converter.fromSIunit_u(Region2.u2_pT(p, Region4.T4_p(p))) + return self._unit_converter.fromSIunit_u(Region3.u3_rhoT(1 / (Region3.v3_ph(p, Region4.h4V_p(p))), Region4.T4_p(p))) + return float("NaN") - def uL_p(self, p): - """Saturated liquid internal energy as a function of pressure + def uL_p(self, p: float) -> float: + """ + Section 1.8 Specific internal energy + Saturated liquid internal energy as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - uL (float): saturated liquid internal energy + :return: saturated liquid internal energy """ p = self._unit_converter.toSIunit_p(p) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: if p < 16.529: - return self._unit_converter.fromSIunit_u( - Region1.u1_pT(p, Region4.T4_p(p)) - ) - else: - return self._unit_converter.fromSIunit_u( - Region3.u3_rhoT( - 1 / (Region3.v3_ph(p, Region4.h4L_p(p))), Region4.T4_p(p) - ) - ) - else: - self.logger.warning("pressure %f out of range", p) - return float("NaN") + return self._unit_converter.fromSIunit_u(Region1.u1_pT(p, Region4.T4_p(p))) + return self._unit_converter.fromSIunit_u(Region3.u3_rhoT(1 / (Region3.v3_ph(p, Region4.h4L_p(p))), Region4.T4_p(p))) + self.logger.warning("pressure %f out of range", p) + return float("NaN") - def uV_t(self, t): - """Saturated vapour internal energy as a function of temperature + def uV_t(self, t: float) -> float: + """ + Section 1.8 Specific internal energy + Saturated vapour internal energy as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - uV (float): saturated vapour internal energy or NaN if arguments are out of range + :return: saturated vapour internal energy or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if (T > 273.15) and (T < 647.096): + if FREEZING_TEMPERATURE_H2O < T < CRITICAL_TEMPERATURE: if T <= 623.15: - return self._unit_converter.fromSIunit_u( - Region2.u2_pT(Region4.p4_T(T), T) - ) - else: - return self._unit_converter.fromSIunit_u( - Region3.u3_rhoT( - 1 - / ( - Region3.v3_ph( - Region4.p4_T(T), Region4.h4V_p(Region4.p4_T(T)) - ) - ), - T, - ) + return self._unit_converter.fromSIunit_u(Region2.u2_pT(Region4.p4_T(T), T)) + return self._unit_converter.fromSIunit_u( + Region3.u3_rhoT( + 1 / (Region3.v3_ph(Region4.p4_T(T), Region4.h4V_p(Region4.p4_T(T)))), + T, ) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + ) + self.logger.warning("temperature %f out of range", T) + return float("NaN") - def uL_t(self, t): - """Saturated liquid internal energy as a function of temperature + def uL_t(self, t: float) -> float: + """ + Section 1.8 Specific internal energy + Saturated liquid internal energy as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - uL (float): saturated liquid internal energy or NaN if arguments are out of range + :return: saturated liquid internal energy or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if (T > 273.15) and (T < 647.096): + if FREEZING_TEMPERATURE_H2O < T < CRITICAL_TEMPERATURE: if T <= 623.15: - return self._unit_converter.fromSIunit_u( - Region1.u1_pT(Region4.p4_T(T), T) - ) - else: - return self._unit_converter.fromSIunit_u( - Region3.u3_rhoT( - 1 - / ( - Region3.v3_ph( - Region4.p4_T(T), Region4.h4L_p(Region4.p4_T(T)) - ) - ), - T, - ) + return self._unit_converter.fromSIunit_u(Region1.u1_pT(Region4.p4_T(T), T)) + + return self._unit_converter.fromSIunit_u( + Region3.u3_rhoT( + 1 / (Region3.v3_ph(Region4.p4_T(T), Region4.h4L_p(Region4.p4_T(T)))), + T, ) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + ) - def u_pt(self, p, t): - """Specific internal energy as a function of pressure and temperature + self.logger.warning("temperature %f out of range", T) + return float("NaN") - Args: - p (float): preasure value - t (float): temperature value + def u_pt(self, p: float, t: float) -> float: + """ + Section 1.8 Specific internal energy + Specific internal energy as a function of pressure and temperature + + :param p: preasure + :param t: temperature - Returns: - u (float): specific internal energy or NaN if arguments are out of range + :return: specific internal energy or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) T = self._unit_converter.toSIunit_T(t) - region = RegionSelection.region_pT(p, T) - if region == 1: + region = select_region_pT(p, T) + + if region == DiagramRegion.R1: return self._unit_converter.fromSIunit_u(Region1.u1_pT(p, T)) - elif region == 2: + + if region == DiagramRegion.R2: return self._unit_converter.fromSIunit_u(Region2.u2_pT(p, T)) - elif region == 3: + + if region == DiagramRegion.R3: hs = Region3.h3_pT(p, T) rhos = 1 / Region3.v3_ph(p, hs) return self._unit_converter.fromSIunit_u(Region3.u3_rhoT(rhos, T)) - elif region == 4: + + if region == DiagramRegion.R4: self.logger.warning( "function u_pt is not available in region 4 for input p %f and T %f", p, T, ) return float("NaN") - elif region == 5: + + if region == DiagramRegion.R5: return self._unit_converter.fromSIunit_u(Region5.u5_pT(p, T)) - else: - self.logger.warning( - "Region switch u_pt returned unknown value %d for input p %f and T %f", - region, - p, - T, - ) - return float("NaN") - def u_ph(self, p, h): - """Specific internal energy as a function of pressure and enthalpy + self.logger.warning( + "Region switch u_pt returned unknown value %d for input p %f and T %f", + region, + p, + T, + ) + return float("NaN") + + def u_ph(self, p: float, h: float) -> float: + """ + Section 1.8 Specific internal energy + Specific internal energy as a function of pressure and enthalpy - Args: - p (float): preasure value - h (float): enthalpy value + :param p: preasure + :param h: enthalpy - Returns: - u (float): specific internal energy or NaN if arguments are out of range + :return: specific internal energy or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) h = self._unit_converter.toSIunit_h(h) - region = RegionSelection.region_ph(p, h) - if region == 1: + region = select_region_ph(p, h) + + if region == DiagramRegion.R1: Ts = Region1.T1_ph(p, h) return self._unit_converter.fromSIunit_u(Region1.u1_pT(p, Ts)) - elif region == 2: + + if region == DiagramRegion.R2: Ts = Region2.T2_ph(p, h) return self._unit_converter.fromSIunit_u(Region2.u2_pT(p, Ts)) - elif region == 3: + + if region == DiagramRegion.R3: rhos = 1 / Region3.v3_ph(p, h) Ts = Region3.T3_ph(p, h) return self._unit_converter.fromSIunit_u(Region3.u3_rhoT(rhos, Ts)) - elif region == 4: + + if region == DiagramRegion.R4: Ts = Region4.T4_p(p) xs = Region4.x4_ph(p, h) if p < 16.529: @@ -1256,807 +1169,765 @@ def u_ph(self, p, h): v4L = Region3.v3_ph(p, Region4.h4L_p(p)) u4L = Region3.u3_rhoT(1 / v4L, Ts) return self._unit_converter.fromSIunit_u((xs * u4v + (1 - xs) * u4L)) - elif region == 5: + + if region == DiagramRegion.R5: Ts = Region5.T5_ph(p, h) return self._unit_converter.fromSIunit_u(Region5.u5_pT(p, Ts)) - else: - self.logger.warning( - "Region switch u_ph returned unknown value %d for input p %f and h %f", - region, - p, - h, - ) - return float("NaN") - def u_ps(self, p, s): - """Specific internal energy as a function of pressure and entropy + self.logger.warning( + "Region switch u_ph returned unknown value %d for input p %f and h %f", + region, + p, + h, + ) + return float("NaN") + + def u_ps(self, p: float, s: float) -> float: + """ + Section 1.8 Specific internal energy + Specific internal energy as a function of pressure and entropy - Args: - p (float): preasure value - s (float): entropy value + :param p: preasure + :param s: specific entropy - Returns: - u (float): specific internal energy or NaN if arguments are out of range + :return: specific internal energy or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) s = self._unit_converter.toSIunit_s(s) - region = RegionSelection.region_ps(p, s) - if region == 1: + region = select_region_ps(p, s) + if region == DiagramRegion.R1: Ts = Region1.T1_ps(p, s) return self._unit_converter.fromSIunit_u(Region1.u1_pT(p, Ts)) - elif region == 2: + + if region == DiagramRegion.R2: Ts = Region2.T2_ps(p, s) return self._unit_converter.fromSIunit_u(Region2.u2_pT(p, Ts)) - elif region == 3: + + if region == DiagramRegion.R3: rhos = 1 / Region3.v3_ps(p, s) Ts = Region3.T3_ps(p, s) return self._unit_converter.fromSIunit_u(Region3.u3_rhoT(rhos, Ts)) - elif region == 4: + + if region == DiagramRegion.R4: if p < 16.529: uLp = Region1.u1_pT(p, Region4.T4_p(p)) uVp = Region2.u2_pT(p, Region4.T4_p(p)) else: - uLp = Region3.u3_rhoT( - 1 / (Region3.v3_ph(p, Region4.h4L_p(p))), Region4.T4_p(p) - ) - uVp = Region3.u3_rhoT( - 1 / (Region3.v3_ph(p, Region4.h4V_p(p))), Region4.T4_p(p) - ) + uLp = Region3.u3_rhoT(1 / (Region3.v3_ph(p, Region4.h4L_p(p))), Region4.T4_p(p)) + uVp = Region3.u3_rhoT(1 / (Region3.v3_ph(p, Region4.h4V_p(p))), Region4.T4_p(p)) xs = Region4.x4_ps(p, s) return self._unit_converter.fromSIunit_u((xs * uVp + (1 - xs) * uLp)) - elif region == 5: + + if region == DiagramRegion.R5: Ts = Region5.T5_ps(p, s) return self._unit_converter.fromSIunit_u(Region5.u5_pT(p, Ts)) - else: - self.logger.warning( - "Region switch u_ps returned unknown value %d for input p %f and s %f", - region, - p, - s, - ) - return float("NaN") - # *********************************************************************************************************** - # Section 1.9 Specific isobaric heat capacity (Cp) - def CpV_p(self, p): - """Saturated vapour heat capacity as a function of pressure + self.logger.warning( + "Region switch u_ps returned unknown value %d for input p %f and s %f", + region, + p, + s, + ) + return float("NaN") + + def CpV_p(self, p: float) -> float: + """ + Section 1.9 Specific isobaric heat capacity + Saturated vapour heat capacity as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - CpV (float): saturated vapour heat capacity or NaN if arguments are out of range + :return: saturated vapour heat capacity or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: if p < 16.529: - return self._unit_converter.fromSIunit_Cp( - Region2.Cp2_pT(p, Region4.T4_p(p)) - ) - else: - return self._unit_converter.fromSIunit_Cp( - Region3.Cp3_rhoT( - 1 / (Region3.v3_ph(p, Region4.h4V_p(p))), Region4.T4_p(p) - ) - ) - else: - self.logger.warning("preassure %f out of range", p) - return float("NaN") + return self._unit_converter.fromSIunit_Cp(Region2.Cp2_pT(p, Region4.T4_p(p))) + return self._unit_converter.fromSIunit_Cp(Region3.Cp3_rhoT(1 / (Region3.v3_ph(p, Region4.h4V_p(p))), Region4.T4_p(p))) + self.logger.warning("preassure %f out of range", p) + return float("NaN") - def CpL_p(self, p): - """Saturated liquid heat capacity as a function of pressure + def CpL_p(self, p: float) -> float: + """ + Section 1.9 Specific isobaric heat capacity + Saturated liquid heat capacity as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - CpL (float): saturated liquid heat capacity or NaN if arguments are out of range + :return: saturated liquid heat capacity or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: if p < 16.529: - return self._unit_converter.fromSIunit_Cp( - Region1.Cp1_pT(p, Region4.T4_p(p)) - ) - else: - return self._unit_converter.fromSIunit_Cp( - Region3.Cp3_rhoT( - 1 / (Region3.v3_ph(p, Region4.h4L_p(p))), Region4.T4_p(p) - ) - ) - else: - self.logger.warning("preassure %f out of range", p) - return float("NaN") + return self._unit_converter.fromSIunit_Cp(Region1.Cp1_pT(p, Region4.T4_p(p))) + return self._unit_converter.fromSIunit_Cp(Region3.Cp3_rhoT(1 / (Region3.v3_ph(p, Region4.h4L_p(p))), Region4.T4_p(p))) + self.logger.warning("preassure %f out of range", p) + return float("NaN") - def CpV_t(self, t): - """Saturated vapour heat capacity as a function of temperature + def CpV_t(self, t: float) -> float: + """ + Section 1.9 Specific isobaric heat capacity + Saturated vapour heat capacity as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - CpV (float): saturated vapour heat capacity or NaN if arguments are out of range + :return: saturated vapour heat capacity or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if (T > 273.15) and (T < 647.096): + if FREEZING_TEMPERATURE_H2O < T < CRITICAL_TEMPERATURE: if T <= 623.15: - return self._unit_converter.fromSIunit_Cp( - Region2.Cp2_pT(Region4.p4_T(T), T) + return self._unit_converter.fromSIunit_Cp(Region2.Cp2_pT(Region4.p4_T(T), T)) + return self._unit_converter.fromSIunit_Cp( + Region3.Cp3_rhoT( + 1 / (Region3.v3_ph(Region4.p4_T(T), Region4.h4V_p(Region4.p4_T(T)))), + T, ) - else: - return self._unit_converter.fromSIunit_Cp( - Region3.Cp3_rhoT( - 1 - / ( - Region3.v3_ph( - Region4.p4_T(T), Region4.h4V_p(Region4.p4_T(T)) - ) - ), - T, - ) - ) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + ) + self.logger.warning("temperature %f out of range", T) + return float("NaN") - def CpL_t(self, t): - """Saturated liquid heat capacity as a function of temperature + def CpL_t(self, t: float) -> float: + """ + Section 1.9 Specific isobaric heat capacity + Saturated liquid heat capacity as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - CpL (float): saturated liquid heat capacity or NaN if arguments are out of range + :return: saturated liquid heat capacity or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if (T > 273.15) and (T < 647.096): + if FREEZING_TEMPERATURE_H2O < T < CRITICAL_TEMPERATURE: if T <= 623.15: - return self._unit_converter.fromSIunit_Cp( - Region1.Cp1_pT(Region4.p4_T(T), T) - ) - else: - return self._unit_converter.fromSIunit_Cp( - Region3.Cp3_rhoT( - 1 - / ( - Region3.v3_ph( - Region4.p4_T(T), Region4.h4L_p(Region4.p4_T(T)) - ) - ), - T, - ) - ) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + Cp = Region1.Cp1_pT(Region4.p4_T(T), T) + return self._unit_converter.fromSIunit_Cp(Cp) + + p = Region4.p4_T(T) + rho = 1 / Region3.v3_ph(p, Region4.h4L_p(p)) + Cp = Region3.Cp3_rhoT(rho, T) + return self._unit_converter.fromSIunit_Cp(Cp) - def Cp_pt(self, p, t): - """Specific isobaric heat capacity as a function of pressure and temperature + self.logger.warning("temperature %f out of range", T) + return float("NaN") - Args: - p (float): preasure value - t (float): temperature value + def Cp_pt(self, p: float, t: float) -> float: + """ + Section 1.9 Specific isobaric heat capacity + Specific isobaric heat capacity as a function of pressure and temperature + + :param p: preasure + :param t: temperature - Returns: - Cp (float): specific isobaric heat capacity or NaN if arguments are out of range + :return: specific isobaric heat capacity or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) T = self._unit_converter.toSIunit_T(t) - region = RegionSelection.region_pT(p, T) - if region == 1: + region = select_region_pT(p, T) + + if region == DiagramRegion.R1: return self._unit_converter.fromSIunit_Cp(Region1.Cp1_pT(p, T)) - elif region == 2: + + if region == DiagramRegion.R2: return self._unit_converter.fromSIunit_Cp(Region2.Cp2_pT(p, T)) - elif region == 3: + + if region == DiagramRegion.R3: hs = Region3.h3_pT(p, T) rhos = 1 / Region3.v3_ph(p, hs) return self._unit_converter.fromSIunit_Cp(Region3.Cp3_rhoT(rhos, T)) - elif region == 4: + + if region == DiagramRegion.R4: self.logger.warning( "function Cp_pt is not available in region 4 for input p %f and T %f", p, T, ) return float("NaN") - elif region == 5: + + if region == DiagramRegion.R5: return self._unit_converter.fromSIunit_Cp(Region5.Cp5_pT(p, T)) - else: - self.logger.warning( - "Region switch Cp_pt returned unknown value %d for input p %f and T %f", - region, - p, - T, - ) - return float("NaN") - def Cp_ph(self, p, h): - """Specific isobaric heat capacity as a function of pressure and enthalpy + self.logger.warning( + "Region switch Cp_pt returned unknown value %d for input p %f and T %f", + region, + p, + T, + ) + return float("NaN") + + def Cp_ph(self, p: float, h: float) -> float: + """ + Section 1.9 Specific isobaric heat capacity + Specific isobaric heat capacity as a function of pressure and enthalpy - Args: - p (float): preasure value - h (float): enthalpy value + :param p: preasure + :param h: enthalpy - Returns: - Cp (float): specific isobaric heat capacity or NaN if arguments are out of range + :return: specific isobaric heat capacity or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) h = self._unit_converter.toSIunit_h(h) - region = RegionSelection.region_ph(p, h) - if region == 1: + region = select_region_ph(p, h) + + if region == DiagramRegion.R1: Ts = Region1.T1_ph(p, h) return self._unit_converter.fromSIunit_Cp(Region1.Cp1_pT(p, Ts)) - elif region == 2: + + if region == DiagramRegion.R2: Ts = Region2.T2_ph(p, h) return self._unit_converter.fromSIunit_Cp(Region2.Cp2_pT(p, Ts)) - elif region == 3: + + if region == DiagramRegion.R3: rhos = 1 / Region3.v3_ph(p, h) Ts = Region3.T3_ph(p, h) return self._unit_converter.fromSIunit_Cp(Region3.Cp3_rhoT(rhos, Ts)) - elif region == 4: + + if region == DiagramRegion.R4: self.logger.warning( "function Cp_ph is not available in region 4 for input p %f and h %f", p, h, ) return float("NaN") - elif region == 5: + + if region == DiagramRegion.R5: Ts = Region5.T5_ph(p, h) return self._unit_converter.fromSIunit_Cp(Region5.Cp5_pT(p, Ts)) - else: - self.logger.warning( - "Region switch Cp_ph returned unknown value %d for input p %f and h %f", - region, - p, - h, - ) - return float("NaN") - def Cp_ps(self, p, s): - """Specific isobaric heat capacity as a function of pressure and entropy + self.logger.warning( + "Region switch Cp_ph returned unknown value %d for input p %f and h %f", + region, + p, + h, + ) + return float("NaN") + + def Cp_ps(self, p: float, s: float) -> float: + """ + Section 1.9 Specific isobaric heat capacity + Specific isobaric heat capacity as a function of pressure and entropy - Args: - p (float): preasure value - s (float): entropy value + :param p: preasure + :param s: specific entropy - Returns: - Cp (float): specific isobaric heat capacity or NaN if arguments are out of range + :return: specific isobaric heat capacity or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) s = self._unit_converter.toSIunit_s(s) - region = RegionSelection.region_ps(p, s) - if region == 1: + region = select_region_ps(p, s) + + if region == DiagramRegion.R1: Ts = Region1.T1_ps(p, s) return self._unit_converter.fromSIunit_Cp(Region1.Cp1_pT(p, Ts)) - elif region == 2: + + if region == DiagramRegion.R2: Ts = Region2.T2_ps(p, s) return self._unit_converter.fromSIunit_Cp(Region2.Cp2_pT(p, Ts)) - elif region == 3: + + if region == DiagramRegion.R3: rhos = 1 / Region3.v3_ps(p, s) Ts = Region3.T3_ps(p, s) return self._unit_converter.fromSIunit_Cp(Region3.Cp3_rhoT(rhos, Ts)) - elif region == 4: + + if region == DiagramRegion.R4: self.logger.warning( "function Cp_ps is not available in region 4 for input p %f and s %f", p, s, ) return float("NaN") - elif region == 5: + + if region == DiagramRegion.R5: Ts = Region5.T5_ps(p, s) return self._unit_converter.fromSIunit_Cp(Region5.Cp5_pT(p, Ts)) - else: - self.logger.warning( - "Region switch Cp_ps returned unknown value %d for input p %f and s %f", - region, - p, - s, - ) - return float("NaN") - # *********************************************************************************************************** - # Section 1.10 Specific isochoric heat capacity (Cv) - def CvV_p(self, p): - """Saturated vapour isochoric heat capacity as a function of pressure + self.logger.warning( + "Region switch Cp_ps returned unknown value %d for input p %f and s %f", + region, + p, + s, + ) + return float("NaN") + + def CvV_p(self, p: float) -> float: + """ + Section 1.10 Specific isochoric heat capacity + Saturated vapour isochoric heat capacity as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - CvV (float): saturated vapour isochoric heat capacity or NaN if arguments are out of range + :return: saturated vapour isochoric heat capacity or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: if p < 16.529: - return self._unit_converter.fromSIunit_Cv( - Region2.Cv2_pT(p, Region4.T4_p(p)) - ) - else: - return self._unit_converter.fromSIunit_Cv( - Region3.Cv3_rhoT( - 1 / (Region3.v3_ph(p, Region4.h4V_p(p))), Region4.T4_p(p) - ) - ) - else: - self.logger.warning("pressure %f out of range", p) - return float("NaN") + Cv = Region2.Cv2_pT(p, Region4.T4_p(p)) + return self._unit_converter.fromSIunit_Cv(Cv) + + rho = 1 / Region3.v3_ph(p, Region4.h4V_p(p)) + Cv = Region3.Cv3_rhoT(rho, Region4.T4_p(p)) + return self._unit_converter.fromSIunit_Cv(Cv) + + self.logger.warning("pressure %f out of range", p) + return float("NaN") - def CvL_p(self, p): - """Saturated liquid isochoric heat capacity as a function of pressure + def CvL_p(self, p: float) -> float: + """ + Section 1.10 Specific isochoric heat capacity + Saturated liquid isochoric heat capacity as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - CvL (float): saturated liquid isochoric heat capacity or NaN if arguments are out of range + :return: saturated liquid isochoric heat capacity or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: if p < 16.529: - return self._unit_converter.fromSIunit_Cv( - Region1.Cv1_pT(p, Region4.T4_p(p)) - ) - else: - return self._unit_converter.fromSIunit_Cv( - Region3.Cv3_rhoT( - 1 / (Region3.v3_ph(p, Region4.h4L_p(p))), Region4.T4_p(p) - ) - ) - else: - self.logger.warning("pressure %f out of range", p) - return float("NaN") + Cv = Region1.Cv1_pT(p, Region4.T4_p(p)) + return self._unit_converter.fromSIunit_Cv(Cv) - def CvV_t(self, t): - """Saturated vapour isochoric heat capacity as a function of temperature + rho = 1 / Region3.v3_ph(p, Region4.h4L_p(p)) + Cv = Region3.Cv3_rhoT(rho, Region4.T4_p(p)) + return self._unit_converter.fromSIunit_Cv(Cv) + + self.logger.warning("pressure %f out of range", p) + return float("NaN") + + def CvV_t(self, t: float) -> float: + """ + Section 1.10 Specific isochoric heat capacity + Saturated vapour isochoric heat capacity as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - CvV (float): saturated vapour isochoric heat capacity or NaN if arguments are out of range + :return: saturated vapour isochoric heat capacity or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if (T > 273.15) and (T < 647.096): + if FREEZING_TEMPERATURE_H2O < T < CRITICAL_TEMPERATURE: if T <= 623.15: - return self._unit_converter.fromSIunit_Cv( - Region2.Cv2_pT(Region4.p4_T(T), T) - ) - else: - return self._unit_converter.fromSIunit_Cv( - Region3.Cv3_rhoT( - 1 - / ( - Region3.v3_ph( - Region4.p4_T(T), Region4.h4V_p(Region4.p4_T(T)) - ) - ), - T, - ) - ) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + Cv = Region2.Cv2_pT(Region4.p4_T(T), T) + return self._unit_converter.fromSIunit_Cv(Cv) - def CvL_t(self, t): - """Saturated liquid isochoric heat capacity as a function of temperature + p = Region4.p4_T(T) + rho = 1 / Region3.v3_ph(p, Region4.h4V_p(p)) + Cv = Region3.Cv3_rhoT(rho, T) + return self._unit_converter.fromSIunit_Cv(Cv) + + self.logger.warning("temperature %f out of range", T) + return float("NaN") + + def CvL_t(self, t: float) -> float: + """ + Section 1.10 Specific isochoric heat capacity + Saturated liquid isochoric heat capacity as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - CvL (float): saturated liquid isochoric heat capacity or NaN if arguments are out of range + :return: saturated liquid isochoric heat capacity or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if (T > 273.15) and (T < 647.096): + if FREEZING_TEMPERATURE_H2O < T < CRITICAL_TEMPERATURE: if T <= 623.15: - return self._unit_converter.fromSIunit_Cv( - Region1.Cv1_pT(Region4.p4_T(T), T) - ) - else: - return self._unit_converter.fromSIunit_Cv( - Region3.Cv3_rhoT( - 1 - / ( - Region3.v3_ph( - Region4.p4_T(T), Region4.h4L_p(Region4.p4_T(T)) - ) - ), - T, - ) - ) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + Cv = Region1.Cv1_pT(Region4.p4_T(T), T) + return self._unit_converter.fromSIunit_Cv(Cv) + + p = Region4.p4_T(T) + rho = 1 / Region3.v3_ph(p, Region4.h4L_p(p)) + Cv = Region3.Cv3_rhoT(rho, T) + return self._unit_converter.fromSIunit_Cv(Cv) - def Cv_pt(self, p, t): - """Specific isochoric heat capacity as a function of pressure and temperature + self.logger.warning("temperature %f out of range", T) + return float("NaN") - Args: - p (float): preasure value - t (float): temperature value + def Cv_pt(self, p: float, t: float) -> float: + """ + Section 1.10 Specific isochoric heat capacity + Specific isochoric heat capacity as a function of pressure and temperature + + :param p: preasure + :param t: temperature - Returns: - Cv (float): specific isochoric heat capacity or NaN if arguments are out of range + :return: specific isochoric heat capacity or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) T = self._unit_converter.toSIunit_T(t) - region = RegionSelection.region_pT(p, T) - if region == 1: + region = select_region_pT(p, T) + + if region == DiagramRegion.R1: return self._unit_converter.fromSIunit_Cv(Region1.Cv1_pT(p, T)) - elif region == 2: + + if region == DiagramRegion.R2: return self._unit_converter.fromSIunit_Cv(Region2.Cv2_pT(p, T)) - elif region == 3: + + if region == DiagramRegion.R3: hs = Region3.h3_pT(p, T) rhos = 1 / Region3.v3_ph(p, hs) return self._unit_converter.fromSIunit_Cv(Region3.Cv3_rhoT(rhos, T)) - elif region == 4: + + if region == DiagramRegion.R4: self.logger.warning( "function Cv_pt is not available in region 4 for input p %f and T %f", p, T, ) return float("NaN") - elif region == 5: + + if region == DiagramRegion.R5: return self._unit_converter.fromSIunit_Cv(Region5.Cv5_pT(p, T)) - else: - self.logger.warning( - "Region switch Cv_pt returned unknown value %d for input p %f and T %f", - region, - p, - T, - ) - return float("NaN") - def Cv_ph(self, p, h): - """Specific isochoric heat capacity as a function of pressure and enthalpy + self.logger.warning( + "Region switch Cv_pt returned unknown value %d for input p %f and T %f", + region, + p, + T, + ) + return float("NaN") + + def Cv_ph(self, p: float, h: float) -> float: + """ + Section 1.10 Specific isochoric heat capacity + Specific isochoric heat capacity as a function of pressure and enthalpy - Args: - p (float): preasure value - h (float): enthalpy value + :param p: preasure + :param h: enthalpy - Returns: - Cv (float): specific isochoric heat capacity or NaN if arguments are out of range + :return: specific isochoric heat capacity or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) h = self._unit_converter.toSIunit_h(h) - region = RegionSelection.region_ph(p, h) - if region == 1: + region = select_region_ph(p, h) + + if region == DiagramRegion.R1: Ts = Region1.T1_ph(p, h) return self._unit_converter.fromSIunit_Cv(Region1.Cv1_pT(p, Ts)) - elif region == 2: + + if region == DiagramRegion.R2: Ts = Region2.T2_ph(p, h) return self._unit_converter.fromSIunit_Cv(Region2.Cv2_pT(p, Ts)) - elif region == 3: + + if region == DiagramRegion.R3: rhos = 1 / Region3.v3_ph(p, h) Ts = Region3.T3_ph(p, h) return self._unit_converter.fromSIunit_Cv(Region3.Cv3_rhoT(rhos, Ts)) - elif region == 4: + + if region == DiagramRegion.R4: self.logger.warning( "function Cv_ph is not available in region 4 for input p %f and h %f", p, h, ) return float("NaN") - elif region == 5: + + if region == DiagramRegion.R5: Ts = Region5.T5_ph(p, h) return self._unit_converter.fromSIunit_Cv(Region5.Cv5_pT(p, Ts)) - else: - self.logger.warning( - "Region switch Cv_ph returned unknown value %d for input p %f and h %f", - region, - p, - h, - ) - return float("NaN") - def Cv_ps(self, p, s): - """Specific isochoric heat capacity as a function of pressure and entropy + self.logger.warning( + "Region switch Cv_ph returned unknown value %d for input p %f and h %f", + region, + p, + h, + ) + return float("NaN") + + def Cv_ps(self, p: float, s: float) -> float: + """ + Section 1.10 Specific isochoric heat capacity + Specific isochoric heat capacity as a function of pressure and entropy - Args: - p (float): preasure value - s (float): entropy value + :param p: preasure + :param s: specific entropy - Returns: - Cv (float): specific isochoric heat capacity or NaN if arguments are out of range + :return: specific isochoric heat capacity or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) s = self._unit_converter.toSIunit_s(s) - region = RegionSelection.region_ps(p, s) - if region == 1: + region = select_region_ps(p, s) + + if region == DiagramRegion.R1: Ts = Region1.T1_ps(p, s) return self._unit_converter.fromSIunit_Cv(Region1.Cv1_pT(p, Ts)) - elif region == 2: + + if region == DiagramRegion.R2: Ts = Region2.T2_ps(p, s) return self._unit_converter.fromSIunit_Cv(Region2.Cv2_pT(p, Ts)) - elif region == 3: + + if region == DiagramRegion.R3: rhos = 1 / Region3.v3_ps(p, s) Ts = Region3.T3_ps(p, s) return self._unit_converter.fromSIunit_Cv(Region3.Cv3_rhoT(rhos, Ts)) - elif region == 4: + + if region == DiagramRegion.R4: self.logger.warning( "function Cv_ps is not available in region 4 for input p %f and s %f", p, s, ) + # TODO: why is the following line here? # (xs * CvVp + (1 - xs) * CvLp) / Cv_scale - Cv_offset return float("NaN") - elif region == 5: + + if region == DiagramRegion.R5: Ts = Region5.T5_ps(p, s) return self._unit_converter.fromSIunit_Cv(Region5.Cv5_pT(p, Ts)) - else: - self.logger.warning( - "Region switch Cv_ps returned unknown value %d for input p %f and s %f", - region, - p, - s, - ) - return float("NaN") - # *********************************************************************************************************** - # Section 1.11 Speed of sound - def wV_p(self, p): - """Saturated vapour speed of sound as a function of pressure + self.logger.warning( + "Region switch Cv_ps returned unknown value %d for input p %f and s %f", + region, + p, + s, + ) + return float("NaN") + + def wV_p(self, p: float) -> float: + """ + Section 1.11 Speed of sound + Saturated vapour speed of sound as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - wV (float): speed of sound in saturated vapour or NaN if arguments are out of range + :return: speed of sound in saturated vapour or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: if p < 16.529: - return self._unit_converter.fromSIunit_w( - Region2.w2_pT(p, Region4.T4_p(p)) - ) - else: - return self._unit_converter.fromSIunit_w( - Region3.w3_rhoT( - 1 / (Region3.v3_ph(p, Region4.h4V_p(p))), Region4.T4_p(p) - ) - ) - else: - self.logger.warning("pressure %f out of range", p) - return float("NaN") + w = Region2.w2_pT(p, Region4.T4_p(p)) + return self._unit_converter.fromSIunit_w(w) + + rho = 1 / Region3.v3_ph(p, Region4.h4V_p(p)) + w = Region3.w3_rhoT(rho, Region4.T4_p(p)) + return self._unit_converter.fromSIunit_w(w) + + self.logger.warning("pressure %f out of range", p) + return float("NaN") - def wL_p(self, p): - """Saturated liquid speed of sound as a function of pressure + def wL_p(self, p: float) -> float: + """ + Section 1.11 Speed of sound + Saturated liquid speed of sound as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - wL (float): speed of sound in saturated liquid or NaN if arguments are out of range + :return: speed of sound in saturated liquid or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: if p < 16.529: - return self._unit_converter.fromSIunit_w( - Region1.w1_pT(p, Region4.T4_p(p)) - ) - else: - return self._unit_converter.fromSIunit_w( - Region3.w3_rhoT( - 1 / (Region3.v3_ph(p, Region4.h4L_p(p))), Region4.T4_p(p) - ) - ) - else: - self.logger.warning("pressure %f out of range", p) - return float("NaN") + w = Region1.w1_pT(p, Region4.T4_p(p)) + return self._unit_converter.fromSIunit_w(w) - def wV_t(self, t): - """Saturated vapour speed of sound as a function of temperature + rho = 1 / Region3.v3_ph(p, Region4.h4L_p(p)) + w = Region3.w3_rhoT(rho, Region4.T4_p(p)) + return self._unit_converter.fromSIunit_w(w) - Args: - t (float): temperature value + self.logger.warning("pressure %f out of range", p) + return float("NaN") - Returns: - wV (float): speed of sound in saturated vapour or NaN if arguments are out of range + def wV_t(self, t: float) -> float: + """ + Section 1.11 Speed of sound + Saturated vapour speed of sound as a function of temperature + + :param t: temperature + + :return: speed of sound in saturated vapour or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if (T > 273.15) and (T < 647.096): + if FREEZING_TEMPERATURE_H2O < T < CRITICAL_TEMPERATURE: if T <= 623.15: - return self._unit_converter.fromSIunit_w( - Region2.w2_pT(Region4.p4_T(T), T) - ) - else: - return self._unit_converter.fromSIunit_w( - Region3.w3_rhoT( - 1 - / ( - Region3.v3_ph( - Region4.p4_T(T), Region4.h4V_p(Region4.p4_T(T)) - ) - ), - T, - ) - ) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + w = Region2.w2_pT(Region4.p4_T(T), T) + return self._unit_converter.fromSIunit_w(w) + + p = Region4.p4_T(T) + rho = 1 / Region3.v3_ph(p, Region4.h4V_p(p)) + w = Region3.w3_rhoT(rho, T) + return self._unit_converter.fromSIunit_w(w) + + self.logger.warning("temperature %f out of range", T) + return float("NaN") - def wL_t(self, t): - """Saturated liquid speed of sound as a function of temperature + def wL_t(self, t: float) -> float: + """ + Section 1.11 Speed of sound + Saturated liquid speed of sound as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - wL (float): speed of sound in saturated liquid or NaN if arguments are out of range + :return: speed of sound in saturated liquid or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if (T > 273.15) and (T < 647.096): + if FREEZING_TEMPERATURE_H2O < T < CRITICAL_TEMPERATURE: if T <= 623.15: - return self._unit_converter.fromSIunit_w( - Region1.w1_pT(Region4.p4_T(T), T) - ) - else: - return self._unit_converter.fromSIunit_w( - Region3.w3_rhoT( - 1 - / ( - Region3.v3_ph( - Region4.p4_T(T), Region4.h4L_p(Region4.p4_T(T)) - ) - ), - T, - ) - ) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + w = Region1.w1_pT(Region4.p4_T(T), T) + return self._unit_converter.fromSIunit_w(w) + + p = Region4.p4_T(T) + roh = 1 / Region3.v3_ph(p, Region4.h4L_p(p)) + w = Region3.w3_rhoT(roh, T) + return self._unit_converter.fromSIunit_w(w) - def w_pt(self, p, t): - """Speed of sound as a function of pressure and temperature + self.logger.warning("temperature %f out of range", T) + return float("NaN") - Args: - p (float): preasure value - t (float): temperature value + def w_pt(self, p: float, t: float) -> float: + """ + Section 1.11 Speed of sound + Speed of sound as a function of pressure and temperature + + :param p: preasure + :param t: temperature - Returns: - w (float): speed of sound or NaN if arguments are out of range + :return: speed of sound or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) T = self._unit_converter.toSIunit_T(t) - region = RegionSelection.region_pT(p, T) - if region == 1: + region = select_region_pT(p, T) + + if region == DiagramRegion.R1: return self._unit_converter.fromSIunit_w(Region1.w1_pT(p, T)) - elif region == 2: + + if region == DiagramRegion.R2: return self._unit_converter.fromSIunit_w(Region2.w2_pT(p, T)) - elif region == 3: + + if region == DiagramRegion.R3: hs = Region3.h3_pT(p, T) rhos = 1 / Region3.v3_ph(p, hs) return self._unit_converter.fromSIunit_w(Region3.w3_rhoT(rhos, T)) - elif region == 4: + + if region == DiagramRegion.R4: self.logger.warning( "function w_pt is not available in region 4 for input p %f and T %f", p, T, ) return float("NaN") - elif region == 5: + + if region == DiagramRegion.R5: return self._unit_converter.fromSIunit_w(Region5.w5_pT(p, T)) - else: - self.logger.warning( - "Region switch w_pt returned unknown value %d for input p %f and T %f", - region, - p, - T, - ) - return float("NaN") - def w_ph(self, p, h): - """Speed of sound as a function of pressure and enthalpy + self.logger.warning( + "Region switch w_pt returned unknown value %d for input p %f and T %f", + region, + p, + T, + ) + return float("NaN") + + def w_ph(self, p: float, h: float) -> float: + """ + Section 1.11 Speed of sound + Speed of sound as a function of pressure and enthalpy - Args: - p (float): preasure value - h (float): enthalpy value + :param p: preasure + :param h: enthalpy - Returns: - w (float): speed of sound or NaN if arguments are out of range + :return: speed of sound or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) h = self._unit_converter.toSIunit_h(h) - region = RegionSelection.region_ph(p, h) - if region == 1: + region = select_region_ph(p, h) + + if region == DiagramRegion.R1: Ts = Region1.T1_ph(p, h) return self._unit_converter.fromSIunit_w(Region1.w1_pT(p, Ts)) - elif region == 2: + + if region == DiagramRegion.R2: Ts = Region2.T2_ph(p, h) return self._unit_converter.fromSIunit_w(Region2.w2_pT(p, Ts)) - elif region == 3: + + if region == DiagramRegion.R3: rhos = 1 / Region3.v3_ph(p, h) Ts = Region3.T3_ph(p, h) return self._unit_converter.fromSIunit_w(Region3.w3_rhoT(rhos, Ts)) - elif region == 4: - self.logger.warning( - "function w_ph is not available in region 4 p %f and h %f", p, h - ) + + if region == DiagramRegion.R4: + self.logger.warning("function w_ph is not available in region 4 p %f and h %f", p, h) return float("NaN") - elif region == 5: + + if region == DiagramRegion.R5: Ts = Region5.T5_ph(p, h) return self._unit_converter.fromSIunit_w(Region5.w5_pT(p, Ts)) - else: - self.logger.warning( - "Region switch w_ph returned unknown value %d for input p %f and h %f", - region, - p, - h, - ) - return float("NaN") - def w_ps(self, p, s): - """Speed of sound as a function of pressure and entropy + self.logger.warning( + "Region switch w_ph returned unknown value %d for input p %f and h %f", + region, + p, + h, + ) + return float("NaN") + + def w_ps(self, p: float, s: float) -> float: + """ + Section 1.11 Speed of sound + Speed of sound as a function of pressure and entropy - Args: - p (float): preasure value - s (float): entropy value + :param p: preasure + :param s: specific entropy - Returns: - w (float): speed of sound or NaN if arguments are out of range + :return: speed of sound or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) s = self._unit_converter.toSIunit_s(s) - region = RegionSelection.region_ps(p, s) - if region == 1: + region = select_region_ps(p, s) + + if region == DiagramRegion.R1: Ts = Region1.T1_ps(p, s) return self._unit_converter.fromSIunit_w(Region1.w1_pT(p, Ts)) - elif region == 2: + + if region == DiagramRegion.R2: Ts = Region2.T2_ps(p, s) return self._unit_converter.fromSIunit_w(Region2.w2_pT(p, Ts)) - elif region == 3: + + if region == DiagramRegion.R3: rhos = 1 / Region3.v3_ps(p, s) Ts = Region3.T3_ps(p, s) return self._unit_converter.fromSIunit_w(Region3.w3_rhoT(rhos, Ts)) - elif region == 4: + + if region == DiagramRegion.R4: self.logger.warning( "function w_ps is not available in region 4 for input p %f and s %f", p, s, ) + # TODO: why is the following line here? # (xs * wVp + (1 - xs) * wLp) / w_scale - w_offset return float("NaN") - elif region == 5: + + if region == DiagramRegion.R5: Ts = Region5.T5_ps(p, s) return self._unit_converter.fromSIunit_w(Region5.w5_pT(p, Ts)) - else: - self.logger.warning( - "Region switch w_ps returned unknown value %d for input p %f and s %f", - region, - p, - s, - ) - return float("NaN") - # *********************************************************************************************************** - # Section 1.12 Viscosity - # Viscosity is not part of IAPWS Steam IF97. Equations from - # "Revised Release on the IAPWS Formulation 1985 for the Viscosity of Ordinary Water Substance", 2003 are used. - # Viscosity in the mixed region (4) is interpolated according to the density. This is not true since it will be two phases. - def my_pt(self, p, t): - """Viscosity as a function of pressure and temperature + self.logger.warning( + "Region switch w_ps returned unknown value %d for input p %f and s %f", + region, + p, + s, + ) + return float("NaN") + + def my_pt(self, p: float, t: float) -> float: + """ + Section 1.12 Viscosity + Note: Viscosity is not part of IAPWS Steam IF97. Equations from "Revised Release on the IAPWS Formulation 1985 for the + Viscosity of Ordinary Water Substance", 2003 are used. Viscosity in the mixed region (4) is interpolated according to the + density. This is not true since it will be two phases. + Viscosity as a function of pressure and temperature - Args: - p (float): preasure value - t (float): temperature value + :param p: preasure + :param t: temperature - Returns: - my (float): viscosity or NaN if arguments are out of range + :return: viscosity or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) T = self._unit_converter.toSIunit_T(t) - region = RegionSelection.region_pT(p, T) - if region == 4: + region = select_region_pT(p, T) + if region == DiagramRegion.R4: self.logger.warning( "function my_pt is not available in region 4 for input p %f and T %f", p, T, ) return float("NaN") - elif region in [1, 2, 3, 5]: - return self._unit_converter.fromSIunit_my( - TransportProperties.my_AllRegions_pT(p, T) - ) - else: + + if region == DiagramRegion.NILL: self.logger.warning( "Region switch my_pt returned unknown value %d for input p %f and T %f", region, @@ -2065,31 +1936,35 @@ def my_pt(self, p, t): ) return float("NaN") - def my_ph(self, p, h): - """Viscosity as a function of pressure and enthalpy + return self._unit_converter.fromSIunit_my(my_AllRegions_pT(p, T)) + + def my_ph(self, p: float, h: float) -> float: + """ + Section 1.12 Viscosity + Note: Viscosity is not part of IAPWS Steam IF97. Equations from "Revised + Release on the IAPWS Formulation 1985 for the Viscosity of Ordinary Water + Substance", 2003 are used. Viscosity in the mixed region (4) is interpolated + according to the density. This is not true since it will be two phases. + Viscosity as a function of pressure and enthalpy - Args: - p (float): preasure value - h (float): enthalpy value + :param p: preasure + :param h: enthalpy - Returns: - my (float): viscosity or NaN if arguments are out of range + :return: viscosity or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) h = self._unit_converter.toSIunit_h(h) - region = RegionSelection.region_ph(p, h) - if region in [1, 2, 3, 5]: - return self._unit_converter.fromSIunit_my( - TransportProperties.my_AllRegions_ph(p, h) - ) - elif region == 4: + region = select_region_ph(p, h) + + if region == DiagramRegion.R4: self.logger.warning( "function my_pt is not available in region 4 for input p %f and h %f", p, h, ) return float("NaN") - else: + + if region == DiagramRegion.NILL: self.logger.warning( "Region switch my_ph returned unknown value %d for input p %f and h %f", region, @@ -2098,93 +1973,91 @@ def my_ph(self, p, h): ) return float("NaN") - def my_ps(self, p, s): - """Viscosity as a function of pressure and entropy + return self._unit_converter.fromSIunit_my(my_AllRegions_ph(p, h)) + + def my_ps(self, p: float, s: float) -> float: + """ + Section 1.12 Viscosity + Note: Viscosity is not part of IAPWS Steam IF97. Equations + from "Revised Release on the IAPWS Formulation 1985 for the + Viscosity of Ordinary Water Substance", 2003 are used. Viscosity in + the mixed region (4) is interpolated according to the density. This + is not true since it will be two phases. + Viscosity as a function of pressure and entropy - Args: - p (float): preasure value - s (float): entropy value + :param p: preasure + :param s: specific entropy - Returns: - my (float): viscosity + :return: viscosity """ h = self.h_ps(p, s) return self.my_ph(p, h) - # *********************************************************************************************************** - # Section 1.13 Prandtl - def pr_pt(self, p, t): - """Prandtl number as a function of preasuere and temperature + def pr_pt(self, p: float, t: float) -> float: + """ + Section 1.13 Prandtl + Prandtl number as a function of preasuere and temperature - Args: - p (float): preasure value - t (float): temperature value + :param p: preasure + :param t: temperature - Returns: - pr (float): prandtl number + :return: prandtl number """ Cp = self._unit_converter.toSIunit_Cp(self.Cp_pt(p, t)) my = self._unit_converter.toSIunit_my(self.my_pt(p, t)) tc = self._unit_converter.toSIunit_tc(self.tc_pt(p, t)) return Cp * 1000 * my / tc - def pr_ph(self, p, h): - """Prandtl number as a function of preasuere and enthalpy + def pr_ph(self, p: float, h: float) -> float: + """ + Section 1.13 Prandtl + Prandtl number as a function of preasuere and enthalpy - Args: - p (float): preasure value - h (float): enthalpy value + :param p: preasure + :param h: enthalpy - Returns: - pr (float): prandtl number + :return: prandtl number """ Cp = self._unit_converter.toSIunit_Cp(self.Cp_ph(p, h)) my = self._unit_converter.toSIunit_my(self.my_ph(p, h)) tc = self._unit_converter.toSIunit_tc(self.tc_ph(p, h)) return Cp * 1000 * my / tc - # *********************************************************************************************************** - # Section 1.15 Surface tension - def st_t(self, t): - """Surface tension for two phase water/steam as a function of temperature + def st_t(self, t: float) -> float: + """ + Section 1.15 Surface tension + Surface tension for two phase water/steam as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - st (float): surface tension + :return: surface tension """ T = self._unit_converter.toSIunit_T(t) - return self._unit_converter.fromSIunit_st( - TransportProperties.Surface_Tension_T(T) - ) + return self._unit_converter.fromSIunit_st(surface_tension_T(T)) - def st_p(self, p): - """Surface tension for two phase water/steam as a function of preasure + def st_p(self, p: float) -> float: + """ + Section 1.15 Surface tension + Surface tension for two phase water/steam as a function of preasure - Args: - p (float): preasure value + :param p: preasure - Returns: - st (float): surface tension + :return: surface tension """ T = self.tsat_p(p) T = self._unit_converter.toSIunit_T(T) - return self._unit_converter.fromSIunit_st( - TransportProperties.Surface_Tension_T(T) - ) + return self._unit_converter.fromSIunit_st(surface_tension_T(T)) - # *********************************************************************************************************** - # Section 1.16 Thermal conductivity - # Revised release on the IAPS Formulation 1985 for the Thermal Conductivity of ordinary water substance (IAPWS 1998) - def tcL_p(self, p): - """Saturated liquid thermal conductivity as a function of pressure + def tcL_p(self, p: float) -> float: + """ + Section 1.16 Thermal conductivity + Note: Revised release on the IAPS Formulation 1985 for the Thermal + Conductivity of ordinary water substance (IAPWS 1998) + Saturated liquid thermal conductivity as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - tcL (float): saturated liquid thermal conductivity + :return: saturated liquid thermal conductivity """ t = self.tsat_p(p) v = self.vL_p(p) @@ -2192,18 +2065,18 @@ def tcL_p(self, p): T = self._unit_converter.toSIunit_T(t) v = self._unit_converter.toSIunit_v(v) rho = 1.0 / v - return self._unit_converter.fromSIunit_tc( - TransportProperties.tc_ptrho(p, T, rho) - ) + return self._unit_converter.fromSIunit_tc(tc_ptrho(p, T, rho)) - def tcV_p(self, p): - """Saturated vapour thermal conductivity as a function of pressure + def tcV_p(self, p: float) -> float: + """ + Section 1.16 Thermal conductivity + Note: Revised release on the IAPS Formulation 1985 for the Thermal + Conductivity of ordinary water substance (IAPWS 1998) + Saturated vapour thermal conductivity as a function of pressure - Args: - p (float): preasure value + :param p: preasure - Returns: - tcV (float): saturated vapour thermal conductivity + :return: saturated vapour thermal conductivity """ ps = p T = self.tsat_p(p) @@ -2212,18 +2085,18 @@ def tcV_p(self, p): T = self._unit_converter.toSIunit_T(T) v = self._unit_converter.toSIunit_v(v) rho = 1.0 / v - return self._unit_converter.fromSIunit_tc( - TransportProperties.tc_ptrho(p, T, rho) - ) + return self._unit_converter.fromSIunit_tc(tc_ptrho(p, T, rho)) - def tcL_t(self, t): - """Saturated vapour thermal conductivity as a function of temperature + def tcL_t(self, t: float) -> float: + """ + Section 1.16 Thermal conductivity + Note: Revised release on the IAPS Formulation 1985 for the Thermal + Conductivity of ordinary water substance (IAPWS 1998) + Saturated vapour thermal conductivity as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - tcL (float): saturated liquid thermal conductivity + :return: saturated liquid thermal conductivity """ Ts = t p = self.psat_t(Ts) @@ -2232,18 +2105,18 @@ def tcL_t(self, t): T = self._unit_converter.toSIunit_T(Ts) v = self._unit_converter.toSIunit_v(v) rho = 1 / v - return self._unit_converter.fromSIunit_tc( - TransportProperties.tc_ptrho(p, T, rho) - ) + return self._unit_converter.fromSIunit_tc(tc_ptrho(p, T, rho)) - def tcV_t(self, t): - """Saturated liquid thermal conductivity as a function of temperature + def tcV_t(self, t: float) -> float: + """ + Section 1.16 Thermal conductivity + Note: Revised release on the IAPS Formulation 1985 for the Thermal + Conductivity of ordinary water substance (IAPWS 1998) + Saturated liquid thermal conductivity as a function of temperature - Args: - t (float): temperature value + :param t: temperature - Returns: - tcV (float): saturated vapour thermal conductivity + :return: saturated vapour thermal conductivity """ Ts = t p = self.psat_t(Ts) @@ -2252,19 +2125,19 @@ def tcV_t(self, t): T = self._unit_converter.toSIunit_T(Ts) v = self._unit_converter.toSIunit_v(v) rho = 1 / v - return self._unit_converter.fromSIunit_tc( - TransportProperties.tc_ptrho(p, T, rho) - ) + return self._unit_converter.fromSIunit_tc(tc_ptrho(p, T, rho)) - def tc_pt(self, p, t): - """Thermal conductivity as a function of pressure and temperature + def tc_pt(self, p: float, t: float) -> float: + """ + Section 1.16 Thermal conductivity + Note: Revised release on the IAPS Formulation 1985 for the Thermal + Conductivity of ordinary water substance (IAPWS 1998) + Thermal conductivity as a function of pressure and temperature - Args: - p (float): preasure value - t (float): temperature value + :param p: preasure + :param t: temperature - Returns: - tc (float): thermal conductivity + :return: thermal conductivity """ Ts = t @@ -2275,19 +2148,19 @@ def tc_pt(self, p, t): v = self._unit_converter.toSIunit_v(v) rho = 1 / v - return self._unit_converter.fromSIunit_tc( - TransportProperties.tc_ptrho(p, T, rho) - ) + return self._unit_converter.fromSIunit_tc(tc_ptrho(p, T, rho)) - def tc_ph(self, p, h): - """Thermal conductivity as a function of pressure and enthalpy + def tc_ph(self, p: float, h: float) -> float: + """ + Section 1.16 Thermal conductivity + Note: Revised release on the IAPS Formulation 1985 for the Thermal + Conductivity of ordinary water substance (IAPWS 1998) + Thermal conductivity as a function of pressure and enthalpy - Args: - p (float): preasure value - h (float): enthalpy value + :param p: preasure + :param h: enthalpy - Returns: - tc (float): thermal conductivity + :return: thermal conductivity """ hs = h ps = p @@ -2297,19 +2170,19 @@ def tc_ph(self, p, h): T = self._unit_converter.toSIunit_T(T) v = self._unit_converter.toSIunit_v(v) rho = 1 / v - return self._unit_converter.fromSIunit_tc( - TransportProperties.tc_ptrho(p, T, rho) - ) + return self._unit_converter.fromSIunit_tc(tc_ptrho(p, T, rho)) - def tc_hs(self, h, s): - """Thermal conductivity as a function of enthalpy and entropy + def tc_hs(self, h: float, s: float) -> float: + """ + Section 1.16 Thermal conductivity + Note: Revised release on the IAPS Formulation 1985 for the Thermal + Conductivity of ordinary water substance (IAPWS 1998) + Thermal conductivity as a function of enthalpy and entropy - Args: - h (float): enthalpy value - s (float): entropy value + :param h: enthalpy + :param s: specific entropy - Returns: - tc (float): thermal conductivity + :return: thermal conductivity """ hs = h p = self.p_hs(hs, s) @@ -2320,63 +2193,55 @@ def tc_hs(self, h, s): T = self._unit_converter.toSIunit_T(T) v = self._unit_converter.toSIunit_v(v) rho = 1 / v - return self._unit_converter.fromSIunit_tc( - TransportProperties.tc_ptrho(p, T, rho) - ) + return self._unit_converter.fromSIunit_tc(tc_ptrho(p, T, rho)) - # *********************************************************************************************************** - # Section 1.17 Vapour fraction - def x_ph(self, p, h): - """Vapour fraction as a function of pressure and enthalpy + def x_ph(self, p: float, h: float) -> float: + """ + Section 1.17 Vapour fraction + Vapour fraction as a function of pressure and enthalpy - Args: - p (float): preasure value - h (float): enthalpy value + :param p: preasure + :param h: enthalpy - Returns: - x (float): vapour fraction or NaN if arguments are out of range + :return: vapour fraction or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) h = self._unit_converter.toSIunit_h(h) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: return self._unit_converter.fromSIunit_x(Region4.x4_ph(p, h)) - else: - self.logger.warning("pressure out of range") - return float("NaN") + self.logger.warning("pressure out of range") + return float("NaN") - def x_ps(self, p, s): - """Vapour fraction as a function of pressure and entropy + def x_ps(self, p: float, s: float) -> float: + """ + Section 1.17 Vapour fraction + Vapour fraction as a function of pressure and entropy - Args: - p (float): preasure value - s (float): entropy value + :param p: preasure + :param s: specific entropy - Returns: - x (float): vapour fraction or NaN if arguments are out of range + :return: vapour fraction or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) s = self._unit_converter.toSIunit_s(s) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: return self._unit_converter.fromSIunit_x(Region4.x4_ps(p, s)) - else: - self.logger.warning("pressure %f out of range", p) - return float("NaN") + self.logger.warning("pressure %f out of range", p) + return float("NaN") - # *********************************************************************************************************** - # Section 1.18 Vapour Volume Fraction - def vx_ph(self, p, h): - """Vapour volume fraction as a function of pressure and enthalpy + def vx_ph(self, p: float, h: float) -> float: + """ + Section 1.18 Vapour Volume Fraction + Vapour volume fraction as a function of pressure and enthalpy - Args: - p (float): preasure value - h (float): enthalpy value + :param p: preasure + :param h: enthalpy - Returns: - vx (float): vapour volume fraction or NaN if arguments are out of range + :return: vapour volume fraction or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) h = self._unit_converter.toSIunit_h(h) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: if p < 16.529: vL = Region1.v1_pT(p, Region4.T4_p(p)) vV = Region2.v2_pT(p, Region4.T4_p(p)) @@ -2384,26 +2249,25 @@ def vx_ph(self, p, h): vL = Region3.v3_ph(p, Region4.h4L_p(p)) vV = Region3.v3_ph(p, Region4.h4V_p(p)) xs = Region4.x4_ph(p, h) - return self._unit_converter.fromSIunit_vx( - (xs * vV / (xs * vV + (1 - xs) * vL)) - ) - else: - self.logger.warning("pressure %f out of range", p) - return float("NaN") + vx = xs * vV / (xs * vV + (1 - xs) * vL) + return self._unit_converter.fromSIunit_vx(vx) - def vx_ps(self, p, s): - """Vapour volume fraction as a function of pressure and entropy + self.logger.warning("pressure %f out of range", p) + return float("NaN") - Args: - p (float): preasure value - s (float): entropy value + def vx_ps(self, p: float, s: float) -> float: + """ + Section 1.18 Vapour Volume Fraction + Vapour volume fraction as a function of pressure and entropy + + :param p: preasure + :param s: specific entropy - Returns: - vx (float): vapour volume fraction or NaN if arguments are out of range + :return: vapour volume fraction or NaN if arguments are out of range """ p = self._unit_converter.toSIunit_p(p) s = self._unit_converter.toSIunit_s(s) - if (p > 0.000611657) and (p < 22.06395): + if TRIPLE_POINT_PRESSURE < p < CRITICAL_PRESSURE: if p < 16.529: vL = Region1.v1_pT(p, Region4.T4_p(p)) vV = Region2.v2_pT(p, Region4.T4_p(p)) @@ -2411,112 +2275,133 @@ def vx_ps(self, p, s): vL = Region3.v3_ph(p, Region4.h4L_p(p)) vV = Region3.v3_ph(p, Region4.h4V_p(p)) xs = Region4.x4_ps(p, s) - return self._unit_converter.fromSIunit_vx( - (xs * vV / (xs * vV + (1 - xs) * vL)) - ) - else: - self.logger.warning("pressure %f out of range", p) - return float("NaN") + vx = xs * vV / (xs * vV + (1 - xs) * vL) + return self._unit_converter.fromSIunit_vx(vx) + + self.logger.warning("pressure %f out of range", p) + return float("NaN") + + def pmelt_t(self, t: float, hint: IceType = IceType.NONE) -> float: + """ + Revised Release on the Pressure along the Melting and Sublimation Curves of + Ordinary Water Substance + Release IAPWS R14-08(2011) + http://www.iapws.org/relguide/MeltSub2011.pdf - # *********************************************************************************************************** - # Revised Release on the Pressure along the Melting and Sublimation Curves of Ordinary Water Substance - # Release IAPWS R14-08(2011) - # http://www.iapws.org/relguide/MeltSub2011.pdf - def pmelt_t(self, t, hint=None): - """Pressure along the melting curve as a function of temperature. Based on IAPWS R14-08(2011) + Pressure along the melting curve as a function of temperature. Based + on IAPWS R14-08(2011) http://www.iapws.org/relguide/MeltSub2011.pdf - Because of the shape of the meltin curve it is not possible to automatically select the correct region - automatically. Therefore the optional hint-parameter is used to tell the function which area you are interested in. + Because of the shape of the meltin curve it is not possible to automatically + select the correct region automatically. Therefore the optional + hint-parameter is used to tell the function which area you are interested in. The hint-values are namend after the ice types. - XSteam.TYPE_ICE_Ih = 1 - XSteam.TYPE_ICE_III = 3 - XSteam.TYPE_ICE_V = 5 - XSteam.TYPE_ICE_VI = 6 - XSteam.TYPE_ICE_VII = 7 + `IceType.Ih` = 1 + `IceType.III` = 3 + `IceType.V` = 5 + `IceType.VI` = 6 + `IceType.VII` = 7 If the hint is not one of the values above or None(Default), an Exception is raised - Args: - t (float): temperature value - hint (int): (optional) hint for the selection logic to decide which part of the melting curve to use + :param t: temperature + :param hint: hint for the selection logic to decide which part of the melting curve to use. For supported values see IceType - Returns: - p (float): preassure or NaN if arguments are out of range + :raises ValueError: unknown value for hint + + :return: preassure or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if hint is None: - if T >= 251.165 and T < 256.164: - self.logger.error( - "can't select ice type based on temperature %f, hint required", T - ) + if hint is None or hint == IceType.NONE: + if 251.165 <= T < 256.164: + self.logger.error("can't select ice type based on temperature %f, hint required", T) return float("NaN") - elif T >= 256.164 and T < 273.31: + + if 256.164 <= T < 273.31: self.logger.debug("chose ice type V based on temperature") - return self._unit_converter.fromSIunit_p(IAPWS_R14.pmelt_T_iceV(T)) - elif T >= 273.31 and T < 355: + return self._unit_converter.fromSIunit_p(pmelt_T_iceV(T)) + + if 273.31 <= T < 355: self.logger.debug("chose ice type VI based on temperature") - return self._unit_converter.fromSIunit_p(IAPWS_R14.pmelt_T_iceVI(T)) - elif T >= 355 and T < 751: + return self._unit_converter.fromSIunit_p(pmelt_T_iceVI(T)) + + if 355 <= T < 751: self.logger.debug("chose ice type VII based on temperature") - return self._unit_converter.fromSIunit_p(IAPWS_R14.pmelt_T_iceVII(T)) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + return self._unit_converter.fromSIunit_p(pmelt_T_iceVII(T)) - elif hint is self.TYPE_ICE_Ih: - if T >= 251.165 and T < 273.16: - return self._unit_converter.fromSIunit_p(IAPWS_R14.pmelt_T_iceIh(T)) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + self.logger.warning("temperature %f out of range", T) + return float("NaN") - elif hint is self.TYPE_ICE_III: - if T >= 251.165 and T < 256.164: - return self._unit_converter.fromSIunit_p(IAPWS_R14.pmelt_T_iceIII(T)) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + if hint == IceType.Ih: + if 251.165 <= T < 273.16: + return self._unit_converter.fromSIunit_p(pmelt_T_iceIh(T)) + self.logger.warning("temperature %f out of range", T) + return float("NaN") - elif hint is self.TYPE_ICE_V: - if T >= 256.164 and T < 273.31: - return self._unit_converter.fromSIunit_p(IAPWS_R14.pmelt_T_iceV(T)) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + if hint == IceType.III: + if 251.165 <= T < 256.164: + return self._unit_converter.fromSIunit_p(pmelt_T_iceIII(T)) + self.logger.warning("temperature %f out of range", T) + return float("NaN") - elif hint is self.TYPE_ICE_VI: - if T >= 273.31 and T < 355: - return self._unit_converter.fromSIunit_p(IAPWS_R14.pmelt_T_iceVI(T)) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + if hint == IceType.V: + if 256.164 <= T < 273.31: + return self._unit_converter.fromSIunit_p(pmelt_T_iceV(T)) + self.logger.warning("temperature %f out of range", T) + return float("NaN") - elif hint is self.TYPE_ICE_VII: - if T >= 355 and T < 751: - return self._unit_converter.fromSIunit_p(IAPWS_R14.pmelt_T_iceVII(T)) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + if hint == IceType.VI: + if 273.31 <= T < 355: + return self._unit_converter.fromSIunit_p(pmelt_T_iceVI(T)) + self.logger.warning("temperature %f out of range", T) + return float("NaN") - else: - self.logger.error( - "unknown value for parameter 'hint' %s, can't select ice type", hint - ) - raise ValueError("unknown value for parameter 'hint'") + if hint == IceType.VII: + if 355 <= T < 751: + return self._unit_converter.fromSIunit_p(pmelt_T_iceVII(T)) + self.logger.warning("temperature %f out of range", T) + return float("NaN") + + self.logger.error("unknown value for parameter 'hint' %s, can't select ice type", hint) + raise ValueError("unknown value for parameter 'hint'") - def psubl_t(self, t): - """Pressure along the sublimation curve as a function of temperature. Based on IAPWS R14-08(2011) + def psubl_t(self, t: float) -> float: + """Pressure along the sublimation curve as a function of temperature. Based + on IAPWS R14-08(2011) http://www.iapws.org/relguide/MeltSub2011.pdf - Args: - t (float): temperature value + Revised Release on the Pressure along the Melting and Sublimation Curves of + Ordinary Water Substance + Release IAPWS R14-08(2011) + http://www.iapws.org/relguide/MeltSub2011.pdf + + :param t: temperature - Returns: - p (float): preassure or NaN if arguments are out of range + :return: preassure or NaN if arguments are out of range """ T = self._unit_converter.toSIunit_T(t) - if T >= 50 and T < 273.16: - return self._unit_converter.fromSIunit_p(IAPWS_R14.psubl_T(T)) - else: - self.logger.warning("temperature %f out of range", T) - return float("NaN") + if 50 <= T < 273.16: + return self._unit_converter.fromSIunit_p(psubl_T(T)) + self.logger.warning("temperature %f out of range", T) + return float("NaN") + + def R12_my_rhot(self, rho: float, t: float, industrial_application: bool = True) -> float: + """shear viscosity of pure water substance over an extensive range of fluid states + + Release on the IAPWS Formulation 2008 for the Viscosity of Ordinary Water Substance + IAPWS R12-08 + http://www.iapws.org/relguide/visc.pdf + + :param rho: density + :param t: temperature + :param industrial_application: select if simple or detailes approximation should be used + + :return: shear viscosity + """ + self.logger.warning("this function is still experimental, use at your own risk!") + + T = self._unit_converter.toSIunit_T(t) + + my_my = eq10(T, rho, industrial=industrial_application) + my = my_my * 10e5 + + return self._unit_converter.fromSIunit_my(my) diff --git a/pyXSteam/XSteam_HW.py b/pyXSteam/XSteam_HW.py index 354d3b3..3e7d80f 100755 --- a/pyXSteam/XSteam_HW.py +++ b/pyXSteam/XSteam_HW.py @@ -2,50 +2,59 @@ # -*- coding: utf-8 -*- """Main module for the heavy water parts of pyXSteam""" import logging -from . import Constants +from .Constants import ( + CRITICAL_TEMPERATURE_D20_1992, + CRITICAL_PRESSURE_D20_1992, + CRITICAL_DENSITY_D20_1992, + UnitSystem, +) from .UnitConverter import UnitConverter -from . import IAPWS_R4 +from .IAPWS_R4 import myHW_rhoT_R4, tcHW_rhoT_R4 +from .TransportProperties_HW import surface_tension_T class XSteam_HW: """Main pyXSteam for Heavy Water object. Abstract of all other functions to allow auto selection of the correct region for each set of parameters. - Args: - unitSystem (int): set the unit system used for input and output values. - Can be eather 0 (UNIT_SYSTEM_BARE), 1 (UNIT_SYSTEM_MKS) or 2 (UNIT_SYSTEM_FLS). + :param unitSystem: unit system used for input and output values. For supported values + see the enum UnitSystem. """ - # Copy constant Values to expose them to the User - UNIT_SYSTEM_BARE = UnitConverter.__UNIT_SYSTEM_BARE__ - UNIT_SYSTEM_MKS = UnitConverter.__UNIT_SYSTEM_MKS__ - UNIT_SYSTEM_FLS = UnitConverter.__UNIT_SYSTEM_FLS__ + UNIT_SYSTEM_BARE = UnitSystem.BARE + UNIT_SYSTEM_MKS = UnitSystem.MKS + UNIT_SYSTEM_FLS = UnitSystem.FLS - def __init__(self, unitSystem=UnitConverter.__UNIT_SYSTEM_BARE__): - self.logger = logging.getLogger(__name__) - self.unit_converter = UnitConverter(unitSystem) + def __init__(self, unitSystem: UnitSystem = UnitSystem.BARE): + """ + Constructor method + """ + self.logger = logging.getLogger("pyXSteam:Heavy Water") + self._unit_converter = UnitConverter(unitSystem) self.logger.info( "initialised pyXSteam for Heavy Water with Unit System %s", - self.unit_converter, + self._unit_converter, ) def criticalTemperatur(self): - """returns the specific temperature with conversion to the selected unit system""" - return self.unit_converter.fromSIunit_T( - Constants.__CRITICAL_TEMPERATURE_D20_1992__ - ) + """ + :return: specific temperature with conversion to the selected unit system + """ + return self._unit_converter.fromSIunit_T(CRITICAL_TEMPERATURE_D20_1992) def criticalPressure(self): - """returns the specific pressure with conversion to the selected unit system""" - return self.unit_converter.fromSIunit_p( - Constants.__CRITICAL_PRESSURE_D20_1992__ - ) + """ + :return: specific pressure with conversion to the selected unit system + """ + return self._unit_converter.fromSIunit_p(CRITICAL_PRESSURE_D20_1992) def criticalDensity(self): - """returns the specific density with conversion to the selected unit system""" - return self.unit_converter.fromSIunit_p(Constants.__CRITICAL_DENSITY_D20_1992__) + """ + :return: specific density with conversion to the selected unit system + """ + return self._unit_converter.fromSIunit_p(CRITICAL_DENSITY_D20_1992) - def my_rhoT(self, rho, T): + def my_rhoT(self, rho: float, T: float) -> float: """Viscosity as a function of density and temperature for heavy water substance @@ -54,25 +63,27 @@ def my_rhoT(self, rho, T): http://www.iapws.org/relguide/TransD2O-2007.pdf Appendix A - Args: - rho (float): density value for heavy water - T (float): temperature value for heavy water + :param rho: density for heavy water + :param T: temperature for heavy water - Returns: - my (float): viscosity or NaN if arguments are out of range + :raises ValueError: value of density is zero or negative + + :return: viscosity or NaN if arguments are out of range """ - rho = self.unit_converter.toSIunit_p(rho) - T = self.unit_converter.toSIunit_T(T) + if rho <= 0.0: + self.logger.error("negative values for density rho not allowed %f", rho) + raise ValueError("rho out of range") + + rho = self._unit_converter.toSIunit_p(rho) + T = self._unit_converter.toSIunit_T(T) if T < 277.0 or T > 775.0: self.logger.error("temperature out of range") return float("NaN") - self.logger.warning("input for desity wasn't checked!") - - return self.unit_converter.fromSIunit_T(IAPWS_R4.myHW_rhoT_R4(rho, T)) + return self._unit_converter.fromSIunit_T(myHW_rhoT_R4(rho, T)) - def tc_rhoT(self, rho, T): + def tc_rhoT(self, rho: float, T: float) -> float: """Thermal conductivity as a function of density and temperature for heavy water substance @@ -81,20 +92,33 @@ def tc_rhoT(self, rho, T): http://www.iapws.org/relguide/TransD2O-2007.pdf Appendix B - Args: - rho (float): density value for heavy water - T (float): temperature value for heavy water + :param rho: density for heavy water + :param T: temperature for heavy water - Returns: - λ (float): thermal conductivity or NaN if arguments are out of range + :raises ValueError: value of density is zero or negative + + :return: thermal conductivity or NaN if arguments are out of range """ - rho = self.unit_converter.toSIunit_p(rho) - T = self.unit_converter.toSIunit_T(T) + if rho <= 0.0: + self.logger.error("negative values for density rho not allowed %f", rho) + raise ValueError("rho out of range") + + rho = self._unit_converter.toSIunit_p(rho) + T = self._unit_converter.toSIunit_T(T) if T < 277.0 or T > 825.0: self.logger.error("temperature out of range") return float("NaN") - self.logger.warning("input for desity wasn't checked!") + return self._unit_converter.fromSIunit_tc(tcHW_rhoT_R4(rho, T)) - return self.unit_converter.fromSIunit_tc(IAPWS_R4.tcHW_rhoT_R4(rho, T)) + def st_t(self, t: float) -> float: + """ + Surface tension for two phase water/steam as a function of temperature + + :param t: temperature + + :return: surface tension + """ + T = self._unit_converter.toSIunit_T(t) + return self._unit_converter.fromSIunit_st(surface_tension_T(T)) diff --git a/pyXSteam/__init__.py b/pyXSteam/__init__.py index bb137c5..c5ded9e 100755 --- a/pyXSteam/__init__.py +++ b/pyXSteam/__init__.py @@ -6,6 +6,12 @@ .. Source at https://github.com/drunsinn/pyXSteam this is the pyXSteam package""" +from .XSteam import XSteam +from .XSteam_HW import XSteam_HW +from .UnitConverter import UnitConverter +from .Constants import UnitSystem, IceType -name = "pyXSteam" -__version__ = "0.4.9" +__version__ = "0.5.0" +__author__ = "drunsinn" +__license__ = "MIT" +__email__ = "dr.unsinn@googlemail.com" diff --git a/pyXSteam/scripts/__init__.py b/pyXSteam/scripts/__init__.py new file mode 100755 index 0000000..79f701a --- /dev/null +++ b/pyXSteam/scripts/__init__.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +.. codeauthor:: drunsinn +.. Licensed under the GNU General Public License v2 (GPLv2) +.. Source at https://github.com/drunsinn/pyXSteam + +Collection of demo scripts for pyXSteam""" diff --git a/bin/pyXSteamDemo.py b/pyXSteam/scripts/pyXSteamDemo.py similarity index 55% rename from bin/pyXSteamDemo.py rename to pyXSteam/scripts/pyXSteamDemo.py index 2b96d0b..c99b4a6 100644 --- a/bin/pyXSteamDemo.py +++ b/pyXSteam/scripts/pyXSteamDemo.py @@ -3,7 +3,7 @@ """collection of demos presenting the functionality of pyXSteam""" import time import logging -import matplotlib.pyplot as pyplot +from matplotlib import pyplot import numpy as np from pyXSteam.XSteam import XSteam from pyXSteam.XSteam_HW import XSteam_HW @@ -12,70 +12,83 @@ def demo_simpel_values(): """calculate values and print the results""" steam_table = XSteam(XSteam.UNIT_SYSTEM_MKS) - # get saturated liquid enthalpy for a preasure of 220 bar - print("hV_p(220.0) =", steam_table.hL_p(220.0)) - # get saturated vapour enthalpy for a preasure of 220 bar - print("hV_p(220.0) =", steam_table.hV_p(220.0)) - print("tcL_p(1.0) =", steam_table.tcL_p(1.0)) - print("tcL_t(25.0) =", steam_table.tcL_t(25.0)) - print("tcV_p(1.0) =", steam_table.tcV_p(1.0)) - print("tcL_t(25.0) =", steam_table.tcV_t(25.0)) - print("tc_hs(100.0, 0.34) =", steam_table.tc_hs(100.0, 0.34)) - print("tc_ph(1.0, 100.0) =", steam_table.tc_ph(1.0, 100.0)) - print("tc_pt(1.0, 25.0) =", steam_table.tc_pt(1.0, 25.0)) - print("w_ps(1.0, 1.0) =", steam_table.w_ps(1.0, 1.0)) - - -def demo_generate_ph_diagramm(path=None, precision=1.0): + print("saturated liquid enthalpy @ 220 bar") + print(f" hV_p(220.0) = {steam_table.hL_p(220.0)}") + print("saturated vapour enthalpy @ 220 bar") + print(f" hV_p(220.0) = {steam_table.hV_p(220.0)}") + print("saturated liquid thermal conductivity @ 1 bar") + print(f" tcL_p(1.0) = {steam_table.tcL_p(1.0)}") + print("saturated liquid thermal conductivity @ 25 °C") + print(f" tcL_t(25.0) = {steam_table.tcL_t(25.0)}") + print("saturated vapour thermal conductivity @ 1 bar") + print(f" tcV_p(1.0) = {steam_table.tcV_p(1.0)}") + print("saturated vapour thermal conductivity @ 25 °C") + print(f" tcL_t(25.0) = {steam_table.tcV_t(25.0)}") + print("thermal conductivity @ enthalpy 100 kJ / kg and specific entropy 0.34 kJ / (kg °C)") + print(f" tc_hs(100.0, 0.34) = {steam_table.tc_hs(100.0, 0.34)}") + print("thermal conductivity @ 1 bar and enthalpy 100 kJ / kg") + print(f" tc_ph(1.0, 100.0) = {steam_table.tc_ph(1.0, 100.0)}") + print("thermal conductivity @ 1 bar and 25 °C") + print(f" tc_pt(1.0, 25.0) = {steam_table.tc_pt(1.0, 25.0)}") + print("speef of sound @ 1 bar and specific entropy 1.0 kJ / (kg °C)") + print(f" w_ps(1.0, 1.0) = {steam_table.w_ps(1.0, 1.0)}") + + +def demo_generate_ph_diagramm(precision=1.0): """Generate a p(h) Diagram showing the Saturation Line""" steam_table = XSteam(XSteam.UNIT_SYSTEM_MKS) - p_krit = ( - steam_table.criticalPressure() - 0.0001 - ) # minus 0.0001 or else hL_V returns NaN + + p_krit = steam_table.criticalPressure() - 0.0001 # minus 0.0001 or else hL_V returns NaN + h_krit = steam_table.hL_p(p_krit) - p = np.arange(0.0, 1000, precision) - p2 = np.arange(0.5, p_krit, precision) - vapor_fraction = np.arange(0.1, 1.0, 0.1) - h = np.arange(200.0, 4500.0, 100.0) - rho = np.arange(1, 15.0, precision * 2) + + p_range = np.arange(0.0, 1000, precision) + p2_range = np.arange(0.5, p_krit, precision) + vf_range = np.arange(0.1, 1.0, 0.1) + # h_range = np.arange(200.0, 4500.0, 100.0) + temp_range = np.arange(0, 900, 30) + nph_px = np.frompyfunc(steam_table.h_px, 2, 1) nph_pt = np.frompyfunc(steam_table.h_pt, 2, 1) nphL_p = np.frompyfunc(steam_table.hL_p, 1, 1) nphV_p = np.frompyfunc(steam_table.hV_p, 1, 1) - npp_hrho = np.frompyfunc(steam_table.p_hrho, 2, 1) # boiling and dew lines - hL = nphL_p(p) - hV = nphV_p(p) + hL = nphL_p(p_range) + hV = nphV_p(p_range) # vapor fraction - for vf in vapor_fraction: - h_px = nph_px(p2, vf) - pyplot.plot(h_px, p2, linewidth=1, color="g") + for i, vf in enumerate(vf_range): + h_px = nph_px(p2_range, vf) + if i == 0: + pyplot.plot(h_px, p2_range, linewidth=1, color="g", label="vapour fraction") + else: + pyplot.plot(h_px, p2_range, linewidth=1, color="g") # temperature - for temp in range(0, 900, 30): - h_pt = nph_pt(p, temp) - pyplot.plot(h_pt, p, linewidth=1, color="r") - - # density - for r in rho: - p_hrho = npp_hrho(h, r) - pyplot.plot(h, p_hrho, linewidth=1, color="y") + for i, temp in enumerate(temp_range): + h_pt = nph_pt(p_range, temp) + if i == 0: + pyplot.plot(h_pt, p_range, linewidth=1, color="r", label="temperature") + else: + pyplot.plot(h_pt, p_range, linewidth=1, color="r") # critical point - pyplot.plot([h_krit], [p_krit], marker="s", mfc="k", ms=8) - (line1,) = pyplot.plot(hL, p, linewidth=2, color="b") - (line2,) = pyplot.plot(hV, p, linewidth=2, color="r") + pyplot.plot([h_krit], [p_krit], marker="s", mfc="k", ms=8, label="critical point") + _ = pyplot.plot(hL, p_range, linewidth=2, color="b", label="liquide line") + _ = pyplot.plot(hV, p_range, linewidth=2, color="r", label="vapour line") + + pyplot.title("saturation Line p(h)") + + pyplot.legend(loc="upper right") pyplot.xlabel("h in [kJ/kg]") pyplot.ylabel("p in [bar]") + pyplot.yscale("log") pyplot.grid() - if path is None: - pyplot.show() - else: - pyplot.savefig(path, bbox_inches="tight") + + pyplot.show() def demo_generate_Tp_diagramm(): @@ -85,16 +98,18 @@ def demo_generate_Tp_diagramm(): ntsat_p = np.frompyfunc(steam_table.tsat_p, 1, 1) tsat = ntsat_p(p) (line1,) = pyplot.plot(tsat, p) - pyplot.xlabel("t") - pyplot.ylabel("p") pyplot.setp(line1, linewidth=1, color="b") + + pyplot.title("Saturtion curve t(p)") + pyplot.xlabel("t in [°C]") + pyplot.ylabel("p in [bar]") pyplot.show() def demo_generate_pvT_diagramm(): """Generate a Diagram showing the v(p,T) as a 3D survace""" steam_table = XSteam(XSteam.UNIT_SYSTEM_MKS) - fig = pyplot.figure() + # fig = pyplot.figure() ax = pyplot.axes(projection="3d") p = np.arange(0.0, 300.0, 5.0) @@ -104,34 +119,35 @@ def demo_generate_pvT_diagramm(): v = npv_pt(p, t) colour_map = pyplot.get_cmap("hot") - ax.plot_surface( - p, t, v, cmap=colour_map, rstride=1, cstride=1, linewidth=0, shade=True - ) - - ax.set_xlabel("p") - ax.set_ylabel("t") - ax.set_zlabel("v") + ax.plot_surface(p, t, v, cmap=colour_map, rstride=1, cstride=1, linewidth=0, shade=True) + pyplot.title("v(p,t)") + ax.set_xlabel("p in [bar]") + ax.set_ylabel("t in [°C]") + ax.set_zlabel("v in [m³ / kg]") pyplot.show() def demo_moillier_diagramm(): """Generate a moillier diagram""" steam_table = XSteam(XSteam.UNIT_SYSTEM_MKS) - s = np.arange(2.0, 10.0, 0.01) + s = np.arange(2.0, 15.0, 0.01) pSteps = [0.006117, 0.01, 0.02, 1.0, 2.0, 3.0, 10, 100, 1000] nph_ps = np.frompyfunc(steam_table.h_ps, 2, 1) for pstep in pSteps: h = nph_ps(pstep, s) (hline,) = pyplot.plot(s, h) - pyplot.setp(hline, linewidth=1, color="b") + pyplot.setp(hline, linewidth=1, label=f"{pstep} bar") + + pyplot.title("Moillier Diagram") + pyplot.legend(loc="upper left") pyplot.xlabel("s in [kJ/(kg K)]") pyplot.ylabel("h in [kJ/kg]") pyplot.show() def demo_ice_diagramm(): - """Generate a diagram showing the sublimation and melting preasure""" + """Generate a diagram showing the sublimation and melting preasure of ice""" steam_table = XSteam(XSteam.UNIT_SYSTEM_BARE) t_subl = np.arange(50.0, 273.16, 2.0) t_melt_Ih = np.arange(251.165, 273.16, 2.0) @@ -143,45 +159,51 @@ def demo_ice_diagramm(): psubl_func = np.frompyfunc(steam_table.psubl_t, 1, 1) pmelt_func = np.frompyfunc(steam_table.pmelt_t, 2, 1) - pyplot.plot(t_subl, psubl_func(t_subl), linewidth=1, color="b", label="t_subl") + pyplot.plot( + t_subl, + psubl_func(t_subl), + linewidth=1, + color="b", + label="sublimation temperature", + ) pyplot.plot( t_melt_Ih, pmelt_func(t_melt_Ih, steam_table.TYPE_ICE_Ih), linewidth=2, color="g", - label="t_melt_Ih", + label="melting temperature for ice type Ih", ) pyplot.plot( t_melt_III, pmelt_func(t_melt_III, steam_table.TYPE_ICE_III), linewidth=1, color="r", - label="t_melt_III", + label="melting temperature for ice type III", ) pyplot.plot( t_melt_V, pmelt_func(t_melt_V, steam_table.TYPE_ICE_V), linewidth=2, color="y", - label="t_melt_V", + label="melting temperature for ice type V", ) pyplot.plot( t_melt_VI, pmelt_func(t_melt_VI, steam_table.TYPE_ICE_VI), linewidth=1, color="g", - label="t_melt_VI", + label="melting temperature for ice type VI", ) pyplot.plot( t_melt_VII, pmelt_func(t_melt_VII, steam_table.TYPE_ICE_VII), linewidth=2, color="r", - label="t_melt_VII", + label="melting temperature for ice type VII", ) + pyplot.title("Sublimation and melting preasure of ice") pyplot.legend(loc="upper left") - pyplot.xlabel("T in [K]") pyplot.ylabel("p in [MPa]") @@ -191,16 +213,15 @@ def demo_ice_diagramm(): def demo_simpel_values_heavy_water(): """calculate values for heavy water and print the results""" steam_table_hw = XSteam_HW(XSteam_HW.UNIT_SYSTEM_MKS) - print("my_rhoT(1.0, 320.0) =", steam_table_hw.my_rhoT(1.0, 320.0)) - print("my_rhoT(1.0, 320.0) =", steam_table_hw.tc_rhoT(1.0, 320.0)) + print("calculate values for heavy water D2O") + print("* viscolity @ 320 °C:") + print(f" my_rhoT(1.0, 320.0) = {steam_table_hw.my_rhoT(1.0, 320.0)}") + print("* thermal conductivity @ 320 °C:") + print(f" tc_rhoT(1.0, 320.0) = {steam_table_hw.tc_rhoT(1.0, 320.0)}") -if __name__ == "__main__": - logger = logging.getLogger("pyXSteam") - logger.setLevel(logging.ERROR) - sh = logging.StreamHandler() - sh.setFormatter(logging.Formatter("%(name)s - %(levelname)s - %(message)s")) - logger.addHandler(sh) +def main(): + logging.basicConfig(level=logging.ERROR) print("Collection of simple demos on how to use pyXSteam") print("requires matplotlib and numpy") @@ -222,38 +243,42 @@ def demo_simpel_values_heavy_water(): start = time.process_time() demo_simpel_values() duration = time.process_time() - start - print("Demo took %d seconds to complete", duration) + print(f"Demo took {duration:.4f} seconds to complete") elif selection == "2": start = time.process_time() demo_generate_ph_diagramm() duration = time.process_time() - start - print("Demo took %d seconds to complete", duration) + print(f"Demo took {duration:.4f} seconds to complete") elif selection == "3": start = time.process_time() demo_generate_Tp_diagramm() duration = time.process_time() - start - print("Demo took %d seconds to complete", duration) + print(f"Demo took {duration:.4f} seconds to complete") elif selection == "4": start = time.process_time() demo_generate_pvT_diagramm() duration = time.process_time() - start - print("Demo took %d seconds to complete", duration) + print(f"Demo took {duration:.4f} seconds to complete") elif selection == "5": start = time.process_time() demo_moillier_diagramm() duration = time.process_time() - start - print("Demo took %d seconds to complete", duration) + print(f"Demo took {duration:.4f} seconds to complete") elif selection == "6": start = time.process_time() demo_ice_diagramm() duration = time.process_time() - start - print("Demo took %d seconds to complete", duration) + print(f"Demo took {duration:.4f} seconds to complete") elif selection == "7": start = time.process_time() demo_simpel_values_heavy_water() duration = time.process_time() - start - print("Demo took %d seconds to complete", duration) + print(f"Demo took {duration:.4f} seconds to complete") else: print("Unknown selection") print("------------------------------") + + +if __name__ == "__main__": + main() diff --git a/bin/pyXSteamRankineDemo.py b/pyXSteam/scripts/pyXSteamRankineDemo.py similarity index 62% rename from bin/pyXSteamRankineDemo.py rename to pyXSteam/scripts/pyXSteamRankineDemo.py index f434800..a5d9012 100644 --- a/bin/pyXSteamRankineDemo.py +++ b/pyXSteam/scripts/pyXSteamRankineDemo.py @@ -36,21 +36,21 @@ def demo_simple_cycle(): # %% State Point 1 # condenser outlet / feed pump inlet - state_point_1 = dict() - state_point_1["P"] = 0.08 # bar - given + state_point_1 = {} + state_point_1["p"] = 0.08 # bar - given state_point_1["x"] = 0.0 # given - state_point_1["T"] = steam_table.tsat_p(state_point_1["P"]) - state_point_1["h"] = steam_table.hL_p(state_point_1["P"]) - state_point_1["s"] = steam_table.sL_p(state_point_1["P"]) + state_point_1["t"] = steam_table.tsat_p(state_point_1["p"]) + state_point_1["h"] = steam_table.hL_p(state_point_1["p"]) + state_point_1["s"] = steam_table.sL_p(state_point_1["p"]) # %% State Point 2 # feed pump discharge / Reactor core inlet # process: isentropic compression - state_point_2 = dict() + state_point_2 = {} state_point_2["s"] = state_point_1["s"] - state_point_2["P"] = 71.1 # bar - given - state_point_2["h"] = steam_table.t_ps(state_point_2["P"], state_point_2["s"]) - state_point_2["T"] = steam_table.t_ph(state_point_2["P"], state_point_2["h"]) + state_point_2["p"] = 71.1 # bar - given + state_point_2["h"] = steam_table.t_ps(state_point_2["p"], state_point_2["s"]) + state_point_2["t"] = steam_table.t_ph(state_point_2["p"], state_point_2["h"]) # state_point_2["x"] = float("NaN") pump_work = state_point_1["h"] - state_point_2["h"] @@ -58,24 +58,24 @@ def demo_simple_cycle(): # %% State Point 3 # reactor core outlet / turbine inlet # % process: isobaric heat addition - state_point_3 = dict() - state_point_3["P"] = state_point_2["P"] + state_point_3 = {} + state_point_3["p"] = state_point_2["p"] state_point_3["x"] = 1.0 - state_point_3["T"] = steam_table.tsat_p(state_point_3["P"]) - state_point_3["h"] = steam_table.hV_p(state_point_3["P"]) - state_point_3["s"] = steam_table.sV_p(state_point_3["P"]) + state_point_3["t"] = steam_table.tsat_p(state_point_3["p"]) + state_point_3["h"] = steam_table.hV_p(state_point_3["p"]) + state_point_3["s"] = steam_table.sV_p(state_point_3["p"]) heat_in = state_point_3["h"] - state_point_2["h"] # %% State Point 4 # turbine exhaust / condenser inlet # % process: isentropic expansion - state_point_4 = dict() + state_point_4 = {} state_point_4["s"] = state_point_3["s"] - state_point_4["P"] = state_point_1["P"] + state_point_4["p"] = state_point_1["p"] # % for isobaric heat rejection in next step - state_point_4["h"] = steam_table.h_ps(state_point_4["P"], state_point_4["s"]) - state_point_4["x"] = steam_table.x_ph(state_point_4["P"], state_point_4["h"]) + state_point_4["h"] = steam_table.h_ps(state_point_4["p"], state_point_4["s"]) + state_point_4["x"] = steam_table.x_ph(state_point_4["p"], state_point_4["h"]) turbine_work = state_point_3["h"] - state_point_4["h"] @@ -99,9 +99,7 @@ def demo_ms_and_ofwh(): converted example from Stu Blair, found at https://github.com/stu314159/xsteam/blob/42767648a05c6759ad11aea95256cb24e4fc9499/Examples/Rankine_MS_and_OFWH.m """ print("converted example from Stu Blair / https://github.com/stu314159") - print( - "Purpose: test XSteam functionality with slightly more complex Rankine. Uses scipy.optimize.fsolve" - ) + print("Purpose: test XSteam functionality with slightly more complex Rankine. Uses scipy.optimize.fsolve") print( """Problem Description: A Pressurized Water Reactor transfers heat to a Rankine cycle with the following properties: @@ -119,82 +117,74 @@ def demo_ms_and_ofwh(): # % Calculations # %% state point 1 - condenser outlet - state_point_1 = dict() - state_point_1["P"] = 3.0 # % psia - given + state_point_1 = {} + state_point_1["p"] = 3.0 # % psia - given state_point_1["x"] = 0.0 # % quality - given - state_point_1["T"] = steam_table.hL_p(state_point_1["P"]) - state_point_1["h"] = steam_table.tsat_p(state_point_1["P"]) - state_point_1["s"] = steam_table.sL_p(state_point_1["P"]) + state_point_1["t"] = steam_table.hL_p(state_point_1["p"]) + state_point_1["h"] = steam_table.tsat_p(state_point_1["p"]) + state_point_1["s"] = steam_table.sL_p(state_point_1["p"]) # %% state point 2 # % compression in main condensate pump eta_mcp = 0.84 # % pump isentropic efficiency - given - state_point_2 = dict() + state_point_2 = {} state_point_2["s_s"] = state_point_1["s"] - state_point_2["P"] = 164.0 # % psia - given - state_point_2["h_s"] = steam_table.h_ps(state_point_2["P"], state_point_2["s_s"]) - state_point_2["h"] = ( - state_point_1["h"] - (state_point_1["h"] - state_point_2["h_s"]) / eta_mcp - ) + state_point_2["p"] = 164.0 # % psia - given + state_point_2["h_s"] = steam_table.h_ps(state_point_2["p"], state_point_2["s_s"]) + state_point_2["h"] = state_point_1["h"] - (state_point_1["h"] - state_point_2["h_s"]) / eta_mcp # %% state point 3 OFWH exit - state_point_3 = dict() - state_point_3["P"] = state_point_2["P"] # % constant pressure in OFWH + state_point_3 = {} + state_point_3["p"] = state_point_2["p"] # % constant pressure in OFWH state_point_3["x"] = 0.0 - state_point_3["h"] = steam_table.hL_p(state_point_3["P"]) - state_point_3["s"] = steam_table.sL_p(state_point_3["P"]) + state_point_3["h"] = steam_table.hL_p(state_point_3["p"]) + state_point_3["s"] = steam_table.sL_p(state_point_3["p"]) # %% State point 4 MFP exit eta_mfp = 0.84 - state_point_4 = dict() - state_point_4["P"] = 820.0 # % psia - given + state_point_4 = {} + state_point_4["p"] = 820.0 # % psia - given state_point_4["s_s"] = state_point_3["s"] - state_point_4["h_s"] = steam_table.h_ps(state_point_4["P"], state_point_4["s_s"]) - state_point_4["h"] = ( - state_point_3["h"] - (state_point_3["h"] - state_point_4["h_s"]) / eta_mfp - ) + state_point_4["h_s"] = steam_table.h_ps(state_point_4["p"], state_point_4["s_s"]) + state_point_4["h"] = state_point_3["h"] - (state_point_3["h"] - state_point_4["h_s"]) / eta_mfp # %% State point 5 S/G Exit - state_point_5 = dict() - state_point_5["P"] = state_point_4["P"] # % assume isobaric in S/G + state_point_5 = {} + state_point_5["p"] = state_point_4["p"] # % assume isobaric in S/G state_point_5["x"] = 1.0 # % saturated steam; given - state_point_5["h"] = steam_table.hV_p(state_point_5["P"]) - state_point_5["s"] = steam_table.sV_p(state_point_5["P"]) + state_point_5["h"] = steam_table.hV_p(state_point_5["p"]) + state_point_5["s"] = steam_table.sV_p(state_point_5["p"]) # %% State point 6 HP Turbine Exhaust eta_hpt = 0.94 # % hp turbine isentropic efficiency; given - state_point_6 = dict() - state_point_6["P"] = 164.0 # % psia - given + state_point_6 = {} + state_point_6["p"] = 164.0 # % psia - given state_point_6["s_s"] = state_point_5["s"] - state_point_6["h_s"] = steam_table.h_ps(state_point_6["P"], state_point_6["s_s"]) - state_point_6["h"] = state_point_5["h"] - eta_hpt * ( - state_point_5["h"] - state_point_6["h_s"] - ) - state_point_6["x"] = steam_table.x_ph(state_point_6["P"], state_point_6["h"]) + state_point_6["h_s"] = steam_table.h_ps(state_point_6["p"], state_point_6["s_s"]) + state_point_6["h"] = state_point_5["h"] - eta_hpt * (state_point_5["h"] - state_point_6["h_s"]) + state_point_6["x"] = steam_table.x_ph(state_point_6["p"], state_point_6["h"]) # %% State point 7 Moisture Separator vapor exit - state_point_7 = dict() - state_point_7["P"] = state_point_6["P"] # assume isobaric process in M/S + state_point_7 = {} + state_point_7["p"] = state_point_6["p"] # assume isobaric process in M/S state_point_7["x"] = 1.0 # quality - given - state_point_7["h"] = steam_table.hV_p(state_point_7["P"]) - state_point_7["s"] = steam_table.sV_p(state_point_7["P"]) + state_point_7["h"] = steam_table.hV_p(state_point_7["p"]) + state_point_7["s"] = steam_table.sV_p(state_point_7["p"]) # %% State point 8 LP Turbine exhaust eta_lpt = 0.94 # % lp turbine isentropic efficiency; given - state_point_8 = dict() - state_point_8["P"] = state_point_1["P"] + state_point_8 = {} + state_point_8["p"] = state_point_1["p"] state_point_8["s_s"] = state_point_7["s"] - state_point_8["h_s"] = steam_table.h_ps(state_point_8["P"], state_point_8["s_s"]) - state_point_8["h"] = state_point_7["h"] - eta_lpt * ( - state_point_7["h"] - state_point_8["h_s"] - ) - state_point_8["x"] = steam_table.x_ph(state_point_8["P"], state_point_8["h"]) + state_point_8["h_s"] = steam_table.h_ps(state_point_8["p"], state_point_8["s_s"]) + state_point_8["h"] = state_point_7["h"] - eta_lpt * (state_point_7["h"] - state_point_8["h_s"]) + state_point_8["x"] = steam_table.x_ph(state_point_8["p"], state_point_8["h"]) # %% State point 9 Moisture Separator liquid drain to OFWH - state_point_9 = dict() + state_point_9 = {} # % same pressure as HP Turbine exhaust - state_point_9["P"] = state_point_6["P"] - state_point_9["h"] = steam_table.hL_p(state_point_9["P"]) + state_point_9["p"] = state_point_6["p"] + state_point_9["h"] = steam_table.hL_p(state_point_9["p"]) # http://mathesaurus.sourceforge.net/matlab-numpy.html @@ -245,102 +235,90 @@ def demo_reheat_ms_ofwh(): steam_table = XSteam(XSteam.UNIT_SYSTEM_FLS) # %% State point 1 - condenser exit - state_point_1 = dict() - state_point_1["P"] = 1.5 # % psia - state_point_1["h"] = steam_table.hL_p(state_point_1["P"]) - state_point_1["s"] = steam_table.sL_p(state_point_1["P"]) + state_point_1 = {} + state_point_1["p"] = 1.5 # % psia + state_point_1["h"] = steam_table.hL_p(state_point_1["p"]) + state_point_1["s"] = steam_table.sL_p(state_point_1["p"]) # %% State point 1 -> 2, main condensate pump eta_mcp = 0.84 - state_point_2 = dict() - state_point_2["P"] = 164.0 # % psia + state_point_2 = {} + state_point_2["p"] = 164.0 # % psia state_point_2["s_s"] = state_point_1["s"] - state_point_2["h_s"] = steam_table.h_ps(state_point_2["P"], state_point_2["s_s"]) - state_point_2["h"] = ( - state_point_1["h"] - (state_point_1["h"] - state_point_2["h_s"]) / eta_mcp - ) + state_point_2["h_s"] = steam_table.h_ps(state_point_2["p"], state_point_2["s_s"]) + state_point_2["h"] = state_point_1["h"] - (state_point_1["h"] - state_point_2["h_s"]) / eta_mcp # %% State point 3, OFWH exit, saturated liquid - state_point_3 = dict() - state_point_3["P"] = state_point_2["P"] - state_point_3["h"] = steam_table.hL_p(state_point_3["P"]) - state_point_3["s"] = steam_table.sL_p(state_point_3["P"]) + state_point_3 = {} + state_point_3["p"] = state_point_2["p"] + state_point_3["h"] = steam_table.hL_p(state_point_3["p"]) + state_point_3["s"] = steam_table.sL_p(state_point_3["p"]) # %% State point 3 -> 4, main feed pump eta_mfp = 0.84 - state_point_4 = dict() - state_point_4["P"] = 820.0 # % psia + state_point_4 = {} + state_point_4["p"] = 820.0 # % psia state_point_4["s_s"] = state_point_3["s"] - state_point_4["h_s"] = steam_table.h_ps(state_point_4["P"], state_point_4["s_s"]) - state_point_4["h"] = ( - state_point_3["h"] - (state_point_3["h"] - state_point_4["h_s"]) / eta_mfp - ) + state_point_4["h_s"] = steam_table.h_ps(state_point_4["p"], state_point_4["s_s"]) + state_point_4["h"] = state_point_3["h"] - (state_point_3["h"] - state_point_4["h_s"]) / eta_mfp # %% State point 5 - Steam generator exit - state_point_5 = dict() - state_point_5["P"] = state_point_4["P"] - state_point_5["h"] = steam_table.hV_p(state_point_5["P"]) - state_point_5["s"] = steam_table.sV_p(state_point_5["P"]) + state_point_5 = {} + state_point_5["p"] = state_point_4["p"] + state_point_5["h"] = steam_table.hV_p(state_point_5["p"]) + state_point_5["s"] = steam_table.sV_p(state_point_5["p"]) # %% State point 6 - HP Turbine Exhaust eta_hpt = 0.94 - state_point_6 = dict() - state_point_6["P"] = 164.0 # % psia + state_point_6 = {} + state_point_6["p"] = 164.0 # % psia state_point_6["s_s"] = state_point_5["s"] - state_point_6["h_s"] = steam_table.h_ps(state_point_6["P"], state_point_6["s_s"]) - state_point_6["h"] = state_point_5["h"] - eta_hpt * ( - state_point_5["h"] - state_point_6["h_s"] - ) - state_point_6["x"] = steam_table.x_ph(state_point_6["P"], state_point_6["h"]) + state_point_6["h_s"] = steam_table.h_ps(state_point_6["p"], state_point_6["s_s"]) + state_point_6["h"] = state_point_5["h"] - eta_hpt * (state_point_5["h"] - state_point_6["h_s"]) + state_point_6["x"] = steam_table.x_ph(state_point_6["p"], state_point_6["h"]) # %% State point 7 - Moisture Separator Exit - state_point_7 = dict() - state_point_7["P"] = state_point_6["P"] - state_point_7["h"] = steam_table.hV_p(state_point_7["P"]) - state_point_7["s"] = steam_table.sV_p(state_point_7["P"]) + state_point_7 = {} + state_point_7["p"] = state_point_6["p"] + state_point_7["h"] = steam_table.hV_p(state_point_7["p"]) + state_point_7["s"] = steam_table.sV_p(state_point_7["p"]) # %% State point 8 - Reheater Mid-Pressure Steam exit - state_point_8 = dict() - state_point_8["P"] = state_point_7["P"] - state_point_8["T"] = 490.0 # % degrees F - state_point_8["h"] = steam_table.h_pt(state_point_8["P"], state_point_8["T"]) - state_point_8["s"] = steam_table.s_pt(state_point_8["P"], state_point_8["T"]) + state_point_8 = {} + state_point_8["p"] = state_point_7["p"] + state_point_8["t"] = 490.0 # % degrees F + state_point_8["h"] = steam_table.h_pt(state_point_8["p"], state_point_8["t"]) + state_point_8["s"] = steam_table.s_pt(state_point_8["p"], state_point_8["t"]) # %% State point 9 - LP Turbine Exhaust - state_point_9 = dict() - state_point_9["P"] = state_point_1["P"] + state_point_9 = {} + state_point_9["p"] = state_point_1["p"] eta_lpt = 0.94 state_point_9["s_s"] = state_point_8["s"] - state_point_9["h_s"] = steam_table.h_ps(state_point_9["P"], state_point_9["s_s"]) - state_point_9["h"] = state_point_8["h"] - eta_lpt * ( - state_point_8["h"] - state_point_9["h_s"] - ) + state_point_9["h_s"] = steam_table.h_ps(state_point_9["p"], state_point_9["s_s"]) + state_point_9["h"] = state_point_8["h"] - eta_lpt * (state_point_8["h"] - state_point_9["h_s"]) # %% State point 10 - Reheater HP Steam exit - state_point_10 = dict() - state_point_10["P"] = state_point_5["P"] + state_point_10 = {} + state_point_10["p"] = state_point_5["p"] # % assume steam exits as a saturated liquid. - state_point_10["h"] = steam_table.hL_p(state_point_10["P"]) + state_point_10["h"] = steam_table.hL_p(state_point_10["p"]) # %% State point 11 - pressure trap exit to OFWH - state_point_11 = dict() - state_point_11["P"] = state_point_2["P"] + state_point_11 = {} + state_point_11["p"] = state_point_2["p"] # % assume isenthalpic expansion in the trap. state_point_11["h"] = state_point_10["h"] # %% State point 12 - Moisture Separator liquid drain to OFWH - state_point_12 = dict() - state_point_12["P"] = state_point_6["P"] - state_point_12["h"] = steam_table.hL_p(state_point_12["P"]) + state_point_12 = {} + state_point_12["p"] = state_point_6["p"] + state_point_12["h"] = steam_table.hL_p(state_point_12["p"]) # %% Heat Balance - find the flow fractions def RH_heatBalance(f): - return ( - f[0] * state_point_5["h"] - + (1 - f[0]) * state_point_6["x"] * (1 - f[1]) * state_point_7["h"] - ) - ( - f[0] * state_point_10["h"] - + (1 - f[0]) * state_point_6["x"] * (1 - f[1]) * state_point_8["h"] + return (f[0] * state_point_5["h"] + (1 - f[0]) * state_point_6["x"] * (1 - f[1]) * state_point_7["h"]) - ( + f[0] * state_point_10["h"] + (1 - f[0]) * state_point_6["x"] * (1 - f[1]) * state_point_8["h"] ) def OFWH_heatBalance(f): @@ -360,29 +338,14 @@ def totalFunctional(f): f = fmin(func=totalFunctional, x0=initialGuess) # % % calculate heat and energy balances - w_mcp = ( - (state_point_1["h"] - state_point_2["h"]) - * (1 - f[0]) - * (1 - f[1]) - * state_point_6["x"] - ) + w_mcp = (state_point_1["h"] - state_point_2["h"]) * (1 - f[0]) * (1 - f[1]) * state_point_6["x"] w_mfp = state_point_3["h"] - state_point_4["h"] w_hpt = (state_point_5["h"] - state_point_6["h"]) * (1 - f[0]) - w_lpt = ( - (state_point_8["h"] - state_point_9["h"]) - * (1 - f[0]) - * (1 - f[1]) - * state_point_6["x"] - ) + w_lpt = (state_point_8["h"] - state_point_9["h"]) * (1 - f[0]) * (1 - f[1]) * state_point_6["x"] w_net = w_mcp + w_mfp + w_hpt + w_lpt - q_cond = ( - (state_point_1["h"] - state_point_9["h"]) - * (1 - f[0]) - * (1 - f[1]) - * state_point_6["x"] - ) + q_cond = (state_point_1["h"] - state_point_9["h"]) * (1 - f[0]) * (1 - f[1]) * state_point_6["x"] q_sg = state_point_5["h"] - state_point_4["h"] q_net = q_cond + q_sg @@ -394,7 +357,7 @@ def totalFunctional(f): print(f"Thermal efficiency: {eta_th*100:.2f} percent") -if __name__ == "__main__": +def main(): logger = logging.getLogger("pyXSteam") logger.setLevel(logging.ERROR) sh = logging.StreamHandler() @@ -434,3 +397,7 @@ def totalFunctional(f): print("Unknown selection") print("------------------------------") + + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..efbf7f9 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,219 @@ +[build-system] +requires = ["setuptools", "wheel", "setuptools_scm[toml]>=6.0"] +build-backend = "setuptools.build_meta" + +[tool.setuptools_scm] + +[project] +name = "pyXSteam" +authors = [{ name = "drunsinn", email = "dr.unsinn@googlemail.com" }] +description = "pyXSteam is a port of the Matlab/Excel Package XSteam by Magnus Holmgren, www.x-eng.com to Python 3" +requires-python = ">=3.8" +keywords = ["steam", "water", "ice", "XSteam"] +dynamic = ["version", "readme"] +dependencies = [] + +[project.license] +file = "LICENSE" + +[project.optional-dependencies] +SSH = ["numpy", "scipy", "matplotlib"] + +[project.urls] +"Homepage" = "https://github.com/drunsinn/pyXSteam" +"Bug Tracker" = "https://github.com/drunsinn/pyXSteam/issues" + +[project.scripts] +pyXSteamDemo = "pyXSteam.scripts.pyXSteamDemo:main" +pyXSteamRankineDemo = "pyXSteam.scripts.pyXSteamRankineDemo:main" + +[tool.setuptools] +packages = ["pyXSteam"] + +[tool.setuptools.dynamic] +version = { attr = "pyXSteam.__version__" } +readme = { file = ["README.md"], content-type = "text/markdown" } + +[tool.black] +line-length = 140 +target-version = ["py38"] +include = "\\.pyi?$" +verbose = true + +[tool.pytest.ini_options] +log_cli = true +log_cli_level = "INFO" +log_format = "%(asctime)s %(levelname)s %(message)s" +log_date_format = "%Y-%m-%d %H:%M:%S" + +[tool.codespell] +skip = "*.po,*.ts,./docs/build/*,./build/*,./dist/*,./.git,./.venv,*.pdf,*.m" +count = "" +quiet-level = 3 + +[tool.pylint.main] +fail-under = 9 +ignore = ["CVS"] +ignore-patterns = ["^\\.#"] +jobs = 0 +limit-inference-results = 100 +persistent = true +py-version = "3.8" +suggestion-mode = true + +[tool.pylint.basic] +argument-naming-style = "any" +attr-naming-style = "snake_case" +bad-names = ["foo", "bar", "baz", "toto", "tutu", "tata"] +class-attribute-naming-style = "any" +class-const-naming-style = "any" +class-naming-style = "PascalCase" +const-naming-style = "UPPER_CASE" +docstring-min-length = -1 +function-naming-style = "any" +good-names = ["i", "j", "k", "ex", "Run", "_", "pyXSteam"] +inlinevar-naming-style = "any" +method-naming-style = "any" +module-naming-style = "any" +no-docstring-rgx = "^_" +property-classes = ["abc.abstractproperty"] +variable-naming-style = "any" + +[tool.pylint.classes] +defining-attr-methods = [ + "__init__", + "__new__", + "setUp", + "asyncSetUp", + "__post_init__", +] +exclude-protected = [ + "_asdict", + "_fields", + "_replace", + "_source", + "_make", + "os._exit", +] +valid-classmethod-first-arg = ["cls"] +valid-metaclass-classmethod-first-arg = ["mcs"] + +[tool.pylint.design] +max-args = 5 +max-attributes = 7 +max-bool-expr = 5 +max-branches = 12 +max-locals = 15 +max-parents = 7 +max-public-methods = 20 +max-returns = 6 +max-statements = 50 +min-public-methods = 2 + +[tool.pylint.exceptions] +overgeneral-exceptions = ["builtins.BaseException", "builtins.Exception"] + +[tool.pylint.format] +ignore-long-lines = "^\\s*(# )??$" +indent-after-paren = 4 +indent-string = " " +max-line-length = 140 +max-module-lines = 1000 + +[tool.pylint.imports] +known-third-party = ["enchant"] + +[tool.pylint.logging] +logging-format-style = "old" +logging-modules = ["logging"] + +[tool.pylint."messages control"] +confidence = [ + "HIGH", + "CONTROL_FLOW", + "INFERENCE", + "INFERENCE_FAILURE", + "UNDEFINED", +] +disable = [ + #"raw-checker-failed", + #"bad-inline-option", + #"locally-disabled", + #"file-ignored", + #"suppressed-message", + #"useless-suppression", + #"deprecated-pragma", + #"use-symbolic-message-instead", + #"use-implicit-booleaness-not-comparison-to-string", + #"use-implicit-booleaness-not-comparison-to-zero", + #"consider-using-f-string", +] + +[tool.pylint.method_args] + +timeout-methods = [ + "requests.api.delete", + "requests.api.get", + "requests.api.head", + "requests.api.options", + "requests.api.patch", + "requests.api.post", + "requests.api.put", + "requests.api.request", +] + +[tool.pylint.miscellaneous] +notes = ["FIXME", "XXX", "TODO", "ToDo"] + +[tool.pylint.refactoring] +max-nested-blocks = 5 +never-returning-functions = ["sys.exit", "argparse.parse_error"] + +[tool.pylint.reports] +evaluation = "max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))" +score = true + +[tool.pylint.similarities] +ignore-comments = true +ignore-docstrings = true +ignore-imports = true +ignore-signatures = true +min-similarity-lines = 4 + +[tool.pylint.spelling] +max-spelling-suggestions = 4 +spelling-ignore-comment-directives = "fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:" + +[tool.pylint.typecheck] +contextmanager-decorators = ["contextlib.contextmanager"] +ignore-none = true +ignore-on-opaque-inference = true +ignored-checks-for-mixins = [ + "no-member", + "not-async-context-manager", + "not-context-manager", + "attribute-defined-outside-init", +] +ignored-classes = [ + "optparse.Values", + "thread._local", + "_thread._local", + "argparse.Namespace", +] +missing-member-hint = true +missing-member-hint-distance = 1 +missing-member-max-choices = 1 +mixin-class-rgx = ".*[Mm]ixin" + +[tool.pylint.variables] +allow-global-unused-variables = true +callbacks = ["cb_", "_cb"] +dummy-variables-rgx = "_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_" +ignored-argument-names = "_.*|^ignored_|^unused_" +redefining-builtins-modules = [ + "six.moves", + "past.builtins", + "future.builtins", + "builtins", + "io", +] diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index 3b0dbf6..0000000 --- a/pytest.ini +++ /dev/null @@ -1,3 +0,0 @@ -[pytest] -console_output_style = classic -addopts = -v diff --git a/setup.py b/setup.py deleted file mode 100755 index 763bdd1..0000000 --- a/setup.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -"""create python packages for publishing""" -from pyXSteam import __version__ - -try: - from setuptools import setup -except ImportError: - from distutils.core import setup - -with open("README.md", "r") as fh: - long_description = fh.read() - -setup( - name="pyXSteam", - version=__version__, - author="drunsinn", - author_email="dr.unsinn@googlemail.com", - keywords="steam water ice XSteam", - description="""pyXSteam is a port of the Matlab/Excel Package XSteam - by Magnus Holmgren, www.x-eng.com to Python 3""", - long_description=long_description, - long_description_content_type="text/markdown", - url="https://github.com/drunsinn/pyXSteam", - classifiers=[ - "Programming Language :: Python :: 3", - "License :: OSI Approved :: GNU General Public License v2 (GPLv2)", - "Operating System :: OS Independent", - "Topic :: Scientific/Engineering :: Physics", - "Development Status :: 4 - Beta", - ], - packages=["pyXSteam"], - install_requires=[], - python_requires=">=3.4", - include_package_data=True, - zip_safe=True, - scripts=["bin/pyXSteamDemo.py"], -) diff --git a/tests/test_HeavyWater.py b/tests/test_HeavyWater.py new file mode 100644 index 0000000..840bbe0 --- /dev/null +++ b/tests/test_HeavyWater.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- + +import math +import unittest +import numpy + +from pyXSteam import XSteam_HW +from pyXSteam.Constants import TRIPLE_POINT_TEMPERATURE, CRITICAL_TEMPERATURE +from pyXSteam.TransportProperties_HW import surface_tension_T + + +class HWTester(unittest.TestCase): + """tester for functions specific to heavy water in XSteam_HW""" + + def setUp(self): + self.max_error = 1e-6 + self.steam_table = XSteam_HW(XSteam_HW.UNIT_SYSTEM_MKS) + + def tearDown(self): + pass + + def test_R5_surface_tension(self): + """R5-85(1994) test calculation of surface tension from T""" + # selected values from Table 1 + in_T = [3.8, 5, 30, 55, 80, 105, 130, 155, 180, 205, 230, 255, 280, 305, 330, 355, 370] + in_T = [t + TRIPLE_POINT_TEMPERATURE for t in in_T] # # quick convert to Klevin + ref = [74.93, 74.76, 71.09, 67.06, 62.67, 57.96, 52.95, 47.67, 42.16, 36.45, 30.59, 24.65, 18.69, 12.83, 7.24, 2.26, 0.05] + res = numpy.zeros(len(ref)) + + for i, t in enumerate(in_T): + res[i] = surface_tension_T(t) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, 1e-1, "Test of st_D2O(t) failed") + + assert math.isnan(surface_tension_T(TRIPLE_POINT_TEMPERATURE - 0.01)) + + assert math.isnan(surface_tension_T(CRITICAL_TEMPERATURE + 0.01)) diff --git a/tests/test_MKS.py b/tests/test_MKS.py index 393a7b1..3f7b860 100644 --- a/tests/test_MKS.py +++ b/tests/test_MKS.py @@ -5,724 +5,329 @@ """ import unittest -from pyXSteam.XSteam import XSteam +from pyXSteam import XSteam, UnitSystem -class MKS_FunctionTester(unittest.TestCase): +class MKSFunctionTester(unittest.TestCase): def setUp(self): - self.maxError = 1e-6 - self.steamTable = XSteam(XSteam.UNIT_SYSTEM_MKS) + self.max_error = 1e-6 + self.steam_table = XSteam(UnitSystem.MKS) def tearDown(self): pass def test_tsat_p(self): - error = self.steamTable.tsat_p(1.0) - 99.60591861 - self.assertLess( - error, - self.maxError, - "tsat_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.tsat_p(1.0) - 99.60591861) + self.assertLess(error, self.max_error, "test of tsat_p not passed") def test_t_ph(self): - error = self.steamTable.t_ph(1.0, 100.0) - 23.84481908 - self.assertLess( - error, - self.maxError, - "t_ph not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.t_ph(1.0, 100.0) - 23.84481908) + self.assertLess(error, self.max_error, "test of t_ph not passed") def test_t_ps(self): - error = self.steamTable.t_ps(1.0, 1.0) - 73.70859421 - self.assertLess( - error, - self.maxError, - "t_ps not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.t_ps(1.0, 1.0) - 73.70859421) + self.assertLess(error, self.max_error, "test of t_ps not passed") def test_t_hs(self): - error = self.steamTable.t_hs(100.0, 0.2) - 13.84933511 - self.assertLess( - error, - self.maxError, - "t_hs not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.t_hs(100.0, 0.2) - 13.84933511) + self.assertLess(error, self.max_error, "test of t_hs not passed") def test_psat_t(self): - error = self.steamTable.psat_t(100.0) - 1.014179779 - self.assertLess( - error, - self.maxError, - "psat_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.psat_t(100.0) - 1.014179779) + self.assertLess(error, self.max_error, "test of psat_t not passed") def test_p_hs(self): - error = self.steamTable.p_hs(84.0, 0.296) - 2.295498269 - self.assertLess( - error, - self.maxError, - "p_hs not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.p_hs(84.0, 0.296) - 2.295498269) + self.assertLess(error, self.max_error, "test of p_hs not passed") def test_hV_p(self): - error = self.steamTable.hV_p(1.0) - 2674.949641 - self.assertLess( - error, - self.maxError, - "hV_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.hV_p(1.0) - 2674.949641) + self.assertLess(error, self.max_error, "test of hV_p not passed") def test_hL_p(self): - error = self.steamTable.hL_p(1.0) - 417.4364858 - self.assertLess( - error, - self.maxError, - "hL_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.hL_p(1.0) - 417.4364858) + self.assertLess(error, self.max_error, "test of hL_p not passed") def test_hV_t(self): - error = self.steamTable.hV_t(100.0) - 2675.572029 - self.assertLess( - error, - self.maxError, - "hV_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.hV_t(100.0) - 2675.572029) + self.assertLess(error, self.max_error, "test of hV_t not passed") def test_hL_t(self): - error = self.steamTable.hL_t(100.0) - 419.099155 - self.assertLess( - error, - self.maxError, - "hL_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.hL_t(100.0) - 419.099155) + self.assertLess(error, self.max_error, "test of hL_t not passed") def test_h_pt(self): - error = self.steamTable.h_pt(1.0, 20.0) - 84.01181117 - self.assertLess( - error, - self.maxError, - "h_pt not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.h_pt(1.0, 20.0) - 84.01181117) + self.assertLess(error, self.max_error, "test of h_pt not passed") def test_h_ps(self): - error = self.steamTable.h_ps(1.0, 1.0) - 308.6107171 - self.assertLess( - error, - self.maxError, - "h_ps not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.h_ps(1.0, 1.0) - 308.6107171) + self.assertLess(error, self.max_error, "test of h_ps not passed") def test_h_px(self): - error = self.steamTable.h_px(1.0, 0.5) - 1546.193063 - self.assertLess( - error, - self.maxError, - "h_px not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.h_px(1.0, 0.5) - 1546.193063) + self.assertLess(error, self.max_error, "test of h_px not passed") def test_h_prho(self): - error = self.steamTable.h_prho(1.0, 2.0) - 1082.773391 - self.assertLess( - error, - self.maxError, - "h_prho not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.h_prho(1.0, 2.0) - 1082.773391) + self.assertLess(error, self.max_error, "test of h_prho not passed") def test_h_tx(self): - error = self.steamTable.h_tx(100.0, 0.5) - 1547.33559211 - self.assertLess( - error, - self.maxError, - "h_tx not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.h_tx(100.0, 0.5) - 1547.33559211) + self.assertLess(error, self.max_error, "test of h_tx not passed") def test_vV_p(self): - error = self.steamTable.vV_p(1.0) - 1.694022523 - self.assertLess( - error, - self.maxError, - "vV_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.vV_p(1.0) - 1.694022523) + self.assertLess(error, self.max_error, "test of vV_p not passed") def test_vL_p(self): - error = self.steamTable.vL_p(1.0) - 0.001043148 - self.assertLess( - error, - self.maxError, - "vL_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.vL_p(1.0) - 0.001043148) + self.assertLess(error, self.max_error, "test of vL_p not passed") def test_vV_t(self): - error = self.steamTable.vV_t(100.0) - 1.671860601 - self.assertLess( - error, - self.maxError, - "vV_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.vV_t(100.0) - 1.671860601) + self.assertLess(error, self.max_error, "test of vV_t not passed") def test_vL_t(self): - error = self.steamTable.vL_t(100.0) - 0.001043455 - self.assertLess( - error, - self.maxError, - "vL_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.vL_t(100.0) - 0.001043455) + self.assertLess(error, self.max_error, "test of vL_t not passed") def test_v_pt(self): - error = self.steamTable.v_pt(1.0, 100.0) - 1.695959407 - self.assertLess( - error, - self.maxError, - "v_pt not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.v_pt(1.0, 100.0) - 1.695959407) + self.assertLess(error, self.max_error, "test of v_pt not passed") def test_v_ph(self): - error = self.steamTable.v_ph(1.0, 1000.0) - 0.437925658 - self.assertLess( - error, - self.maxError, - "v_ph not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.v_ph(1.0, 1000.0) - 0.437925658) + self.assertLess(error, self.max_error, "test of v_ph not passed") def test_v_ps(self): - error = self.steamTable.v_ps(1.0, 5.0) - 1.03463539 - self.assertLess( - error, - self.maxError, - "v_ps not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.v_ps(1.0, 5.0) - 1.03463539) + self.assertLess(error, self.max_error, "test of v_ps not passed") def test_rhoV_p(self): - error = self.steamTable.rhoV_p(1.0) - 0.590310924 - self.assertLess( - error, - self.maxError, - "rhoV_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.rhoV_p(1.0) - 0.590310924) + self.assertLess(error, self.max_error, "test of rhoV_p not passed") def test_rhoL_p(self): - error = self.steamTable.rhoL_p(1.0) - 958.6368897 - self.assertLess( - error, - self.maxError, - "rhoL_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.rhoL_p(1.0) - 958.6368897) + self.assertLess(error, self.max_error, "test of rhoL_p not passed") def test_rhoV_t(self): - error = self.steamTable.rhoV_t(100.0) - 0.598135993 - self.assertLess( - error, - self.maxError, - "rhoV_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.rhoV_t(100.0) - 0.598135993) + self.assertLess(error, self.max_error, "test of rhoV_t not passed") def test_rhoL_t(self): - error = self.steamTable.rhoL_t(100.0) - 958.3542773 - self.assertLess( - error, - self.maxError, - "rhoL_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.rhoL_t(100.0) - 958.3542773) + self.assertLess(error, self.max_error, "test of rhoL_t not passed") def test_rho_pt(self): - error = self.steamTable.rho_pt(1.0, 100.0) - 0.589636754 - self.assertLess( - error, - self.maxError, - "rho_pt not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.rho_pt(1.0, 100.0) - 0.589636754) + self.assertLess(error, self.max_error, "test of rho_pt not passed") def test_rho_ph(self): - error = self.steamTable.rho_ph(1.0, 1000.0) - 2.283492601 - self.assertLess( - error, - self.maxError, - "rho_ph not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.rho_ph(1.0, 1000.0) - 2.283492601) + self.assertLess(error, self.max_error, "test of rho_ph not passed") def test_rho_ps(self): - error = self.steamTable.rho_ps(1.0, 1.0) - 975.6236788 - self.assertLess( - error, - self.maxError, - "rho_ps not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.rho_ps(1.0, 1.0) - 975.6236788) + self.assertLess(error, self.max_error, "test of rho_ps not passed") def test_sV_p(self): - error = self.steamTable.sV_p(0.006117) - 9.155465556 - self.assertLess( - error, - self.maxError, - "sV_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.sV_p(0.006117) - 9.155465556) + self.assertLess(error, self.max_error, "test of sV_p not passed") def test_sL_p(self): - error = self.steamTable.sL_p(0.0061171) - 1.8359e-05 - self.assertLess( - error, - self.maxError, - "sL_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.sL_p(0.0061171) - 1.8359e-05) + self.assertLess(error, self.max_error, "test of sL_p not passed") def test_sV_t(self): - error = self.steamTable.sV_t(0.0001) - 9.155756716 - self.assertLess( - error, - self.maxError, - "sV_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.sV_t(0.0001) - 9.155756716) + self.assertLess(error, self.max_error, "test of sV_t not passed") def test_sL_t(self): - error = self.steamTable.sL_t(100.0) - 1.307014328 - self.assertLess( - error, - self.maxError, - "sL_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.sL_t(100.0) - 1.307014328) + self.assertLess(error, self.max_error, "test of sL_t not passed") def test_s_pt(self): - error = self.steamTable.s_pt(1.0, 20.0) - 0.296482921 - self.assertLess( - error, - self.maxError, - "s_pt not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.s_pt(1.0, 20.0) - 0.296482921) + self.assertLess(error, self.max_error, "test of s_pt not passed") def test_s_ph(self): - error = self.steamTable.s_ph(1.0, 84.01181117) - 0.296813845 - self.assertLess( - error, - self.maxError, - "s_ph not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.s_ph(1.0, 84.01181117) - 0.296813845) + self.assertLess(error, self.max_error, "test of s_ph not passed") def test_uV_p(self): - error = self.steamTable.uV_p(1.0) - 2505.547389 - self.assertLess( - error, - self.maxError, - "uV_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.uV_p(1.0) - 2505.547389) + self.assertLess(error, self.max_error, "test of uV_p not passed") def test_uL_p(self): - error = self.steamTable.uL_p(1.0) - 417.332171 - self.assertLess( - error, - self.maxError, - "uL_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.uL_p(1.0) - 417.332171) + self.assertLess(error, self.max_error, "test of uL_p not passed") def test_uV_t(self): - error = self.steamTable.uV_t(100.0) - 2506.015308 - self.assertLess( - error, - self.maxError, - "uV_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.uV_t(100.0) - 2506.015308) + self.assertLess(error, self.max_error, "test of uV_t not passed") def test_uL_t(self): - error = self.steamTable.uL_t(100.0) - 418.9933299 - self.assertLess( - error, - self.maxError, - "uL_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.uL_t(100.0) - 418.9933299) + self.assertLess(error, self.max_error, "test of uL_t not passed") def test_u_pt(self): - error = self.steamTable.u_pt(1.0, 100.0) - 2506.171426 - self.assertLess( - error, - self.maxError, - "u_pt not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.u_pt(1.0, 100.0) - 2506.171426) + self.assertLess(error, self.max_error, "test of u_pt not passed") def test_u_ph(self): - error = self.steamTable.u_ph(1.0, 1000.0) - 956.2074342 - self.assertLess( - error, - self.maxError, - "u_ph not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.u_ph(1.0, 1000.0) - 956.2074342) + self.assertLess(error, self.max_error, "test of u_ph not passed") def test_u_ps(self): - error = self.steamTable.u_ps(1.0, 1.0) - 308.5082185 - self.assertLess( - error, - self.maxError, - "u_ps not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.u_ps(1.0, 1.0) - 308.5082185) + self.assertLess(error, self.max_error, "test of u_ps not passed") def test_CpV_p(self): - error = self.steamTable.CpV_p(1.0) - 2.075938025 - self.assertLess( - error, - self.maxError, - "cpV_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.CpV_p(1.0) - 2.075938025) + self.assertLess(error, self.max_error, "test of cpV_p not passed") def test_CpL_p(self): - error = self.steamTable.CpL_p(1.0) - 4.216149431 - self.assertLess( - error, - self.maxError, - "cpL_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.CpL_p(1.0) - 4.216149431) + self.assertLess(error, self.max_error, "test of cpL_p not passed") def test_CpV_t(self): - error = self.steamTable.CpV_t(100.0) - 2.077491868 - self.assertLess( - error, - self.maxError, - "cpV_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.CpV_t(100.0) - 2.077491868) + self.assertLess(error, self.max_error, "test of cpV_t not passed") def test_CpL_t(self): - error = self.steamTable.CpL_t(100.0) - 4.216645119 - self.assertLess( - error, - self.maxError, - "cpL_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.CpL_t(100.0) - 4.216645119) + self.assertLess(error, self.max_error, "test of cpL_t not passed") def test_Cp_pt(self): - error = self.steamTable.Cp_pt(1.0, 100.0) - 2.074108555 - self.assertLess( - error, - self.maxError, - "cp_pt not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.Cp_pt(1.0, 100.0) - 2.074108555) + self.assertLess(error, self.max_error, "test of cp_pt not passed") def test_Cp_ph(self): - error = self.steamTable.Cp_ph(1.0, 200.0) - 4.17913573169 - self.assertLess( - error, - self.maxError, - "Cp_ph not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.Cp_ph(1.0, 200.0) - 4.17913573169) + self.assertLess(error, self.max_error, "test of Cp_ph not passed") def test_Cp_ps(self): - error = self.steamTable.Cp_ps(1.0, 1.0) - 4.190607038 - self.assertLess( - error, - self.maxError, - "Cp_ps not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.Cp_ps(1.0, 1.0) - 4.190607038) + self.assertLess(error, self.max_error, "test of Cp_ps not passed") def test_CvV_p(self): - error = self.steamTable.CvV_p(1.0) - 1.552696979 - self.assertLess( - error, - self.maxError, - "CvV_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.CvV_p(1.0) - 1.552696979) + self.assertLess(error, self.max_error, "test of CvV_p not passed") def test_CvL_p(self): - error = self.steamTable.CvL_p(1.0) - 3.769699683 - self.assertLess( - error, - self.maxError, - "CvL_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.CvL_p(1.0) - 3.769699683) + self.assertLess(error, self.max_error, "test of CvL_p not passed") def test_CvV_t(self): - error = self.steamTable.CvV_t(100.0) - 1.553698696 - self.assertLess( - error, - self.maxError, - "CvV_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.CvV_t(100.0) - 1.553698696) + self.assertLess(error, self.max_error, "test of CvV_t not passed") def test_CvL_t(self): - error = self.steamTable.CvL_t(100.0) - 3.76770022 - self.assertLess( - error, - self.maxError, - "CvL_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.CvL_t(100.0) - 3.76770022) + self.assertLess(error, self.max_error, "test of CvL_t not passed") def test_Cv_pt(self): - error = self.steamTable.Cv_pt(1.0, 100.0) - 1.551397249 - self.assertLess( - error, - self.maxError, - "Cv_pt not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.Cv_pt(1.0, 100.0) - 1.551397249) + self.assertLess(error, self.max_error, "test of Cv_pt not passed") def test_Cv_ph(self): - error = self.steamTable.Cv_ph(1.0, 200.0) - 4.035176364 - self.assertLess( - error, - self.maxError, - "Cv_ph not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.Cv_ph(1.0, 200.0) - 4.035176364) + self.assertLess(error, self.max_error, "test of Cv_ph not passed") def test_Cv_ps(self): - error = self.steamTable.Cv_ps(1.0, 1.0) - 3.902919468 - self.assertLess( - error, - self.maxError, - "Cv_ps not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.Cv_ps(1.0, 1.0) - 3.902919468) + self.assertLess(error, self.max_error, "test of Cv_ps not passed") def test_wV_p(self): - error = self.steamTable.wV_p(1.0) - 472.0541571 - self.assertLess( - error, - self.maxError, - "wV_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.wV_p(1.0) - 472.0541571) + self.assertLess(error, self.max_error, "test of wV_p not passed") def test_wL_p(self): - error = self.steamTable.wL_p(1.0) - 1545.451948 - self.assertLess( - error, - self.maxError, - "wL_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.wL_p(1.0) - 1545.451948) + self.assertLess(error, self.max_error, "test of wL_p not passed") def test_wV_t(self): - error = self.steamTable.wV_t(100.0) - 472.2559492 - self.assertLess( - error, - self.maxError, - "wV_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.wV_t(100.0) - 472.2559492) + self.assertLess(error, self.max_error, "test of wV_t not passed") def test_wL_t(self): - error = self.steamTable.wL_t(100.0) - 1545.092249 - self.assertLess( - error, - self.maxError, - "wL_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.wL_t(100.0) - 1545.092249) + self.assertLess(error, self.max_error, "test of wL_t not passed") def test_w_pt(self): - error = self.steamTable.w_pt(1.0, 100.0) - 472.3375235 - self.assertLess( - error, - self.maxError, - "w_pt not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.w_pt(1.0, 100.0) - 472.3375235) + self.assertLess(error, self.max_error, "test of w_pt not passed") def test_w_ph(self): - error = self.steamTable.w_ph(1.0, 200.0) - 1542.682475 - self.assertLess( - error, - self.maxError, - "w_ph not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.w_ph(1.0, 200.0) - 1542.682475) + self.assertLess(error, self.max_error, "test of w_ph not passed") def test_w_ps(self): - error = self.steamTable.w_ps(1.0, 1.0) - 1557.858535 - self.assertLess( - error, - self.maxError, - "w_ps not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.w_ps(1.0, 1.0) - 1557.858535) + self.assertLess(error, self.max_error, "test of w_ps not passed") def test_my_pt(self): - error = self.steamTable.my_pt(1.0, 100.0) - 1.22704e-05 - self.assertLess( - error, - self.maxError, - "my_pt not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.my_pt(1.0, 100.0) - 1.22704e-05) + self.assertLess(error, self.max_error, "test of my_pt not passed") def test_my_ph(self): - error = self.steamTable.my_ph(1.0, 100.0) - 0.000914003770302 - self.assertLess( - error, - self.maxError, - "my_ph not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.my_ph(1.0, 100.0) - 0.000914003770302) + self.assertLess(error, self.max_error, "test of my_ph not passed") def test_my_ps(self): - error = self.steamTable.my_ps(1.0, 1.0) - 0.000384222 - self.assertLess( - error, - self.maxError, - "my_ps not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.my_ps(1.0, 1.0) - 0.000384222) + self.assertLess(error, self.max_error, "test of my_ps not passed") def test_tcL_p(self): - error = self.steamTable.tcL_p(1.0) - 0.677593822 - self.assertLess( - error, - self.maxError, - "tcL_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.tcL_p(1.0) - 0.677593822) + self.assertLess(error, self.max_error, "test of tcL_p not passed") def test_tcV_p(self): - error = self.steamTable.tcV_p(1.0) - 0.024753668 - self.assertLess( - error, - self.maxError, - "tcV_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.tcV_p(1.0) - 0.024753668) + self.assertLess(error, self.max_error, "test of tcV_p not passed") def test_tcL_t(self): - error = self.steamTable.tcL_t(25.0) - 0.607458162 - self.assertLess( - error, - self.maxError, - "tcL_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.tcL_t(25.0) - 0.607458162) + self.assertLess(error, self.max_error, "test of tcL_t not passed") def test_tcV_t(self): - error = self.steamTable.tcV_t(25.0) - 0.018326723 - self.assertLess( - error, - self.maxError, - "tcV_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.tcV_t(25.0) - 0.018326723) + self.assertLess(error, self.max_error, "test of tcV_t not passed") def test_tc_pt(self): - error = self.steamTable.tc_pt(1.0, 25.0) - 0.607509806 - self.assertLess( - error, - self.maxError, - "tc_pt not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.tc_pt(1.0, 25.0) - 0.607509806) + self.assertLess(error, self.max_error, "test of tc_pt not passed") def test_tc_ph(self): - error = self.steamTable.tc_ph(1.0, 100.0) - 0.605710062 - self.assertLess( - error, - self.maxError, - "tc_ph not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.tc_ph(1.0, 100.0) - 0.605710062) + self.assertLess(error, self.max_error, "test of tc_ph not passed") def test_tc_hs(self): - error = self.steamTable.tc_hs(100.0, 0.34) - 0.606283124 - self.assertLess( - error, - self.maxError, - "tc_hs not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.tc_hs(100.0, 0.34) - 0.606283124) + self.assertLess(error, self.max_error, "test of tc_hs not passed") def test_st_t(self): - error = self.steamTable.st_t(100.0) - 0.0589118685877 - self.assertLess( - error, - self.maxError, - "st_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.st_t(100.0) - 58.9118685877) + self.assertLess(error, self.max_error, "test of st_t not passed") def test_st_p(self): - error = self.steamTable.st_p(1.0) - 0.058987784 - self.assertLess( - error, - self.maxError, - "st_p not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.st_p(1.0) - 58.987784) + self.assertLess(error, self.max_error, "test of st_p not passed") def test_x_ph(self): - error = self.steamTable.x_ph(1.0, 1000.0) - 0.258055424 - self.assertLess( - error, - self.maxError, - "x_ph not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.x_ph(1.0, 1000.0) - 0.258055424) + self.assertLess(error, self.max_error, "test of x_ph not passed") def test_x_ps(self): - error = self.steamTable.x_ps(1.0, 4.0) - 0.445397961 - self.assertLess( - error, - self.maxError, - "x_ps not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.x_ps(1.0, 4.0) - 0.445397961) + self.assertLess(error, self.max_error, "test of x_ps not passed") def test_vx_ph(self): - error = self.steamTable.vx_ph(1.0, 418.0) - 0.288493093 - self.assertLess( - error, - self.maxError, - "vx_ph not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.vx_ph(1.0, 418.0) - 0.288493093) + self.assertLess(error, self.max_error, "test of vx_ph not passed") def test_vx_ps(self): - error = self.steamTable.vx_ps(1.0, 4.0) - 0.999233827 - self.assertLess( - error, - self.maxError, - "vx_ps not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.steam_table.vx_ps(1.0, 4.0) - 0.999233827) + self.assertLess(error, self.max_error, "test of vx_ps not passed") diff --git a/tests/test_R12.py b/tests/test_R12.py new file mode 100644 index 0000000..cbc25ee --- /dev/null +++ b/tests/test_R12.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- + +import unittest +from pyXSteam import IAPWS_R12 + + +class R12_FunctionTester(unittest.TestCase): + def setUp(self): + self.maxError = 1e-6 + + def tearDown(self): + pass + + def test_R12_industrial(self): + values = list() + values.append({"T": 298.15, "rho": 998, "result": 889.735100e-6}) + values.append({"T": 298.15, "rho": 1200, "result": 1437.649467e-6}) + values.append({"T": 373.15, "rho": 1000, "result": 307.883622e-6}) + values.append({"T": 433.15, "rho": 1, "result": 14.538324e-6}) + values.append({"T": 433.15, "rho": 1000, "result": 217.685358e-6}) + values.append({"T": 873.15, "rho": 1, "result": 32.619287e-6}) + values.append({"T": 873.15, "rho": 100, "result": 35.802262e-6}) + values.append({"T": 873.15, "rho": 600, "result": 77.430195e-6}) + values.append({"T": 1173.15, "rho": 1, "result": 44.217245e-6}) + values.append({"T": 1173.15, "rho": 100, "result": 47.640433e-6}) + values.append({"T": 1173.15, "rho": 400, "result": 64.154608e-6}) + + for value in values: + calc = IAPWS_R12.eq10(T=value["T"], rho=value["rho"], industrial=True) + error = calc - value["result"] + self.assertLess( + error, + self.maxError, + "ep10 not passed for values T %(T)f rho %(rho)f: Error is %(error)e allowed: %(max)e" + % { + "T": value["T"], + "rho": value["rho"], + "error": error, + "max": self.maxError, + }, + ) + + def test_R12(self): + values = list() + values.append({"T": 647.35, "rho": 122, "result": 25.520677e-6}) + values.append({"T": 647.35, "rho": 222, "result": 31.337589e-6}) + # values.append({"T": 647.35, "rho": 272, "result": 36.228143e-6}) + # values.append({"T": 647.35, "rho": 322, "result": 42.961579e-6}) + # values.append({"T": 647.35, "rho": 372, "result": 45.688204e-6}) + values.append({"T": 647.35, "rho": 422, "result": 49.436256e-6}) + + for value in values: + calc = IAPWS_R12.eq10(T=value["T"], rho=value["rho"], industrial=False) + error = calc - value["result"] + self.assertLess( + error, + self.maxError, + "ep10 not passed for values T %(T)f rho %(rho)f: Error is %(error)e allowed: %(max)e" + % { + "T": value["T"], + "rho": value["rho"], + "error": error, + "max": self.maxError, + }, + ) diff --git a/tests/test_R14.py b/tests/test_R14.py index 93ba288..906cb2e 100644 --- a/tests/test_R14.py +++ b/tests/test_R14.py @@ -21,8 +21,7 @@ def test_R14_pmelt_T_function_Ih_1(self): self.assertLess( error, self.maxError_ice_Ih, - "pmelt_T_iceIh not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError_ice_Ih}, + "pmelt_T_iceIh not passed Error %(error)e allowed: %(max)e" % {"error": error, "max": self.maxError_ice_Ih}, ) def test_R14_pmelt_T_function_Ih_2(self): @@ -30,8 +29,7 @@ def test_R14_pmelt_T_function_Ih_2(self): self.assertLess( error, self.maxError_ice_Ih, - "pmelt_T_iceIh not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError_ice_Ih}, + "pmelt_T_iceIh not passed Error %(error)e allowed: %(max)e" % {"error": error, "max": self.maxError_ice_Ih}, ) def test_R14_pmelt_T_function_III_1(self): @@ -39,8 +37,7 @@ def test_R14_pmelt_T_function_III_1(self): self.assertLess( error, self.maxError_ice_III, - "pmelt_T_iceIII not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError_ice_III}, + "pmelt_T_iceIII not passed Error %(error)e allowed: %(max)e" % {"error": error, "max": self.maxError_ice_III}, ) def test_R14_pmelt_T_function_III_2(self): @@ -48,8 +45,7 @@ def test_R14_pmelt_T_function_III_2(self): self.assertLess( error, self.maxError_ice_III, - "pmelt_T_iceIII not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError_ice_III}, + "pmelt_T_iceIII not passed Error %(error)e allowed: %(max)e" % {"error": error, "max": self.maxError_ice_III}, ) def test_R14_pmelt_T_function_V_1(self): @@ -57,8 +53,7 @@ def test_R14_pmelt_T_function_V_1(self): self.assertLess( error, self.maxError_ice_V, - "pmelt_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError_ice_V}, + "pmelt_t not passed Error %(error)e allowed: %(max)e" % {"error": error, "max": self.maxError_ice_V}, ) def test_R14_pmelt_T_function_V_2(self): @@ -66,8 +61,7 @@ def test_R14_pmelt_T_function_V_2(self): self.assertLess( error, self.maxError_ice_V, - "pmelt_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError_ice_V}, + "pmelt_t not passed Error %(error)e allowed: %(max)e" % {"error": error, "max": self.maxError_ice_V}, ) def test_R14_pmelt_T_function_VI_1(self): @@ -75,8 +69,7 @@ def test_R14_pmelt_T_function_VI_1(self): self.assertLess( error, self.maxError_ice_VI, - "pmelt_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError_ice_VI}, + "pmelt_t not passed Error %(error)e allowed: %(max)e" % {"error": error, "max": self.maxError_ice_VI}, ) def test_R14_pmelt_T_function_VI_2(self): @@ -84,8 +77,7 @@ def test_R14_pmelt_T_function_VI_2(self): self.assertLess( error, self.maxError_ice_VI, - "pmelt_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError_ice_VI}, + "pmelt_t not passed Error %(error)e allowed: %(max)e" % {"error": error, "max": self.maxError_ice_VI}, ) def test_R14_pmelt_T_function_VII_1(self): @@ -93,8 +85,7 @@ def test_R14_pmelt_T_function_VII_1(self): self.assertLess( error, self.maxError_ice_VII, - "pmelt_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError_ice_VII}, + "pmelt_t not passed Error %(error)e allowed: %(max)e" % {"error": error, "max": self.maxError_ice_VII}, ) def test_R14_pmelt_T_function_VII_2(self): @@ -102,8 +93,7 @@ def test_R14_pmelt_T_function_VII_2(self): self.assertLess( error, self.maxError_ice_VII, - "pmelt_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError_ice_VII}, + "pmelt_t not passed Error %(error)e allowed: %(max)e" % {"error": error, "max": self.maxError_ice_VII}, ) def test_R14_psubl_T_function(self): @@ -111,6 +101,5 @@ def test_R14_psubl_T_function(self): self.assertLess( error, self.maxError, - "psubl_t not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, + "psubl_t not passed Error %(error)e allowed: %(max)e" % {"error": error, "max": self.maxError}, ) diff --git a/tests/test_RegionBorders.py b/tests/test_RegionBorders.py new file mode 100644 index 0000000..de30cb1 --- /dev/null +++ b/tests/test_RegionBorders.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- + +import unittest + +from test_Regions import REGION_ERROR +import pyXSteam.RegionBorders as RB + + +class BordersTester(unittest.TestCase): + def setUp(self): + self.max_error = REGION_ERROR + + def tearDown(self): + pass + + def _calc_err( + self, + val, + ref, + ): + return abs(val - ref) / ref + + def test_R7_97_B23(self): + """R7-97(2012): computer-program verification for boundary between regions 2 and 3, Eqs. (5) and (6)""" + error = self._calc_err(RB.pB23_T(0.623150000e3), 0.165291643e2) + self.assertLess(error, self.max_error, "Error for p_B23(T) too big") + + error = self._calc_err(RB.TB23_p(0.165291643e2), 0.623150000e3) + self.assertLess(error, self.max_error, "Error for T_B23(p) too big") + + def test_R7_97_B2bc(self): + """R7-97(2012): computer-program verification for boundary between sub regions 2b and 2c, Eqs. (20) and (21)""" + error = self._calc_err(RB.pB2bc_h(0.3516004323e4), 0.100000000e3) + self.assertLess(error, self.max_error, "Error for pB2bc(T) too big") + + error = self._calc_err(RB.hB2bc_p(0.100000000e3), 0.3516004323e4) + self.assertLess(error, self.max_error, "Error for hB2bc(p) too big") + + def test_SR2_01_B2bc(self): + """SR2-01(2016): computer-program verification for boundary between sub regions 2b and 2c, Eq. (2)""" + error = self._calc_err(RB.hB2bc_s(7.0), 3376.437884) / 3376.437884 + self.assertLess(error, self.max_error, "Error for hB2bc(s) too big") + + def test_SR4_04_B13(self): + """SR4-04(2014): computer-program verification for boundary between regions 1 and 3, Eq. (7)""" + # Table 24 + error = self._calc_err(RB.hB13_s(3.7), 1.632525047e3) + self.assertLess(error, self.max_error, "Error for hB13(s) too big") + + error = self._calc_err(RB.hB13_s(3.6), 1.593027215e3) + self.assertLess(error, self.max_error, "Error for hB13(s) too big") + + error = self._calc_err(RB.hB13_s(3.5), 1.566104611e3) + self.assertLess(error, self.max_error, "Error for hB13(s) too big") + + def test_SR4_04_B23(self): + """SR4-04(2014): computer-program verification for boundary between regions 2 and 3, Eq. (8)""" + error = self._calc_err(RB.TB23_hs(2600.0, 5.1), 7.135259364e2) + self.assertLess(error, self.max_error, "Error for hB13(s) to big") + + error = self._calc_err(RB.TB23_hs(2700.0, 5.15), 7.685345532e2) + self.assertLess(error, self.max_error, "Error for hB13(s) to big") + + error = self._calc_err(RB.TB23_hs(2800.0, 5.2), 8.176202120e2) + self.assertLess(error, self.max_error, "Error for hB13(s) to big") diff --git a/tests/test_Regions.py b/tests/test_Regions.py index 2eaab19..0e31ddb 100644 --- a/tests/test_Regions.py +++ b/tests/test_Regions.py @@ -9,554 +9,497 @@ import numpy from pyXSteam.Regions import Region1, Region2, Region3, Region4, Region5 +REGION_ERROR = 1e-8 +REGION_MATRIX_ERROR = REGION_ERROR * 2.0 # The accumulated Error is bigger than the error of each single function + class Region1Tester(unittest.TestCase): + """tests for functions in region 1""" + def setUp(self): - self.maxError = 1e-8 - self.maxMatrixError = 2e-8 # The accumulated Error is bigger than the error of each single function + pass def tearDown(self): pass def test_pT_functions(self): - """Tests to verify all functions with the Parameters p and T of Region 1 by comparing the Results to IF-97 Page 9 Table 5""" - # %* 7.1 Verify region 1 - # %IF-97 Table 5, Page 9 - p = [3.0, 80.0, 3.0] - T = [300.0, 300.0, 500.0] - IF97 = [ - [0.00100215168, 0.000971180894, 0.001202418], - [115.331273, 184.142828, 975.542239], - [112.324818, 106.448356, 971.934985], - [0.392294792, 0.368563852, 2.58041912], - [4.17301218, 4.01008987, 4.65580682], - [1507.73921, 1634.69054, 1240.71337], + """R7-97(2012) Tests to verify all functions with the Parameters p and T of Region 1""" + # Table 5 + in_p = [3.0, 80.0, 3.0] + in_T = [300.0, 300.0, 500.0] + ref = [ + [0.100215168e-2, 0.971180894e-3, 0.120241800e-2], # v + [0.115331273e3, 0.184142828e3, 0.975542239e3], # h + [0.112324818e3, 0.106448356e3, 0.971934985e3], # u + [0.392294792, 0.368563852, 0.258041912e1], # s + [0.417301218e1, 0.401008987e1, 0.465580682e1], # cp + [0.150773921e4, 0.163469054e4, 0.124071337e4], # w ] - R1 = numpy.zeros((6, 3)) - - for i in range(0, 3): - R1[0][i] = Region1.v1_pT(p[i], T[i]) - R1[1][i] = Region1.h1_pT(p[i], T[i]) - R1[2][i] = Region1.u1_pT(p[i], T[i]) - R1[3][i] = Region1.s1_pT(p[i], T[i]) - R1[4][i] = Region1.Cp1_pT(p[i], T[i]) - R1[5][i] = Region1.w1_pT(p[i], T[i]) - - Region1_error = numpy.sum(numpy.absolute((R1 - IF97) / IF97)) - self.assertLess( - Region1_error, - self.maxMatrixError, - "Test of p,T Functions for Region 1 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": Region1_error, "max": self.maxMatrixError}, - ) + res = numpy.zeros((6, 3)) + for i, (p, T) in enumerate(zip(in_p, in_T)): + res[0][i] = Region1.v1_pT(p, T) + res[1][i] = Region1.h1_pT(p, T) + res[2][i] = Region1.u1_pT(p, T) + res[3][i] = Region1.s1_pT(p, T) + res[4][i] = Region1.Cp1_pT(p, T) + res[5][i] = Region1.w1_pT(p, T) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_MATRIX_ERROR, "Test of *(p,T) functions for Region 1 failed.") def test_ph_function(self): - """Tests to verify all functions with the Parameters p and h of Region 1 by comparing the Results to IF-97 Page 11 Table 7""" - # % IF - 97 Table 7, Page 11 - p = [3.0, 80.0, 80.0] - h = [500.0, 500.0, 1500.0] - IF97 = [391.798509, 378.108626, 611.041229] - R1 = numpy.zeros(3) - for i in range(0, 3): - R1[i] = Region1.T1_ph(p[i], h[i]) - - T1_ph_error = numpy.sum(numpy.absolute((R1 - IF97) / IF97)) - self.assertLess( - T1_ph_error, - self.maxError, - "Test of T(p,h) Function for Region 1 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": T1_ph_error, "max": self.maxError}, - ) + """R7-97(2012) Tests to verify all functions with the Parameters p and h of Region 1""" + # Table 7 + in_p = [3.0, 80.0, 80.0] + in_h = [500.0, 500.0, 1500.0] + ref = [0.391798509e3, 0.378108626e3, 0.611041229e3] + res = numpy.zeros(3) + for i, (p, h) in enumerate(zip(in_p, in_h)): + res[i] = Region1.T1_ph(p, h) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_ERROR, "Test of T(p,h) Function for Region 1 failed") def test_ps_function(self): - """Tests to verify all functions with the Parameters p and s of Region 1 by comparing the Results to IF-97 Page 12 Table 9""" - # % IF - 97 Table 9, Page 12 - p = [3.0, 80.0, 80.0] - s = [0.5, 0.5, 3.0] - IF97 = [307.842258, 309.979785, 565.899909] - R1 = numpy.zeros(3) - for i in range(0, 3): - R1[i] = Region1.T1_ps(p[i], s[i]) - - T1_ps_error = numpy.sum(numpy.absolute((R1 - IF97) / IF97)) - self.assertLess( - T1_ps_error, - self.maxError, - "Test of T(p,s) Function for Region 1 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": T1_ps_error, "max": self.maxError}, - ) + """R7-97(2012) Tests to verify all functions with the Parameters p and s of Region 1""" + # Table 9 + in_p = [3.0, 80.0, 80.0] + in_s = [0.5, 0.5, 3.0] + ref = [0.307842258e3, 0.309979785e3, 0.565899909e3] + res = numpy.zeros(3) + for i, (p, s) in enumerate(zip(in_p, in_s)): + res[i] = Region1.T1_ps(p, s) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_ERROR, "Test of T(p,s) Function for Region 1 failed.") def test_hs_function(self): - """Tests to verify all functions with the Parameters h and s of Region 1 by comparing the Results to IF-97 Page 6 Table 3""" - # % Supplementary Release on Backward Equations - # % for Pressure as a Function of Enthalpy and Entropy p(h, s) - # % Table 3, Page 6 - h = [0.001, 90.0, 1500.0] - s = [0.0, 0.0, 3.4] - IF97 = [0.0009800980612, 91.929547272, 58.68294423] - R1 = numpy.zeros(3) - for i in range(0, 3): - R1[i] = Region1.p1_hs(h[i], s[i]) - - p1_hs_error = numpy.sum(numpy.absolute((R1 - IF97) / IF97)) - self.assertLess( - p1_hs_error, - self.maxError, - "Test of p(h,s) Function for Region 1 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": p1_hs_error, "max": self.maxError}, - ) + """SR2-01(2014) Tests to verify all functions with the Parameters h and s of Region 1""" + # Table 3 + in_h = [0.001, 90.0, 1500.0] + in_s = [0.0, 0.0, 3.4] + ref = [9.800980612e-4, 9.192954727e1, 5.868294423e1] + res = numpy.zeros(3) + for i, (h, s) in enumerate(zip(in_h, in_s)): + res[i] = Region1.p1_hs(h, s) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_ERROR, "Test of p(h,s) Function for Region 1 failed.") class Region2Tester(unittest.TestCase): + """tests for functions in region 2""" + def setUp(self): - self.maxError = 1e-8 - self.maxMatrixError = 2e-8 # The accumulated Error is bigger than the error of each single function + pass def tearDown(self): pass def test_pT_function(self): - """Tests to verify all functions with the Parameters p and T of Region 2 by comparing the Results to IF-97 Page 17 Table 15""" - # %* 7.2 Verify region 2 - # % IF-97 Table 15, Page 17 - p = [0.0035, 0.0035, 30.0] - T = [300.0, 700.0, 700.0] - # Fun = {'v2_pT', 'h2_pT', 'u2_pT', 's2_pT', 'Cp2_pT', 'w2_pT'}; - IF97 = [ - [39.4913866, 92.3015898, 0.00542946619], - [2549.91145, 3335.68375, 2631.49474], - [2411.6916, 3012.62819, 2468.61076], - [8.52238967, 10.1749996, 5.17540298], - [1.91300162, 2.08141274, 10.3505092], - [427.920172, 644.289068, 480.386523], + """R7-97(2012) Tests to verify all functions with the Parameters p and T of Region 2""" + # Table 15 + in_p = [0.0035, 0.0035, 30.0] + in_T = [300.0, 700.0, 700.0] + ref = [ + [0.394913866e2, 0.923015898e2, 0.542946619e-2], # v + [0.254991145e4, 0.333568375e4, 0.263149474e4], # h + [0.241169160e4, 0.301262819e4, 0.246861076e4], # u + [0.852238967e1, 0.101749996e2, 0.517540298e1], # s + [0.191300162e1, 0.208141274e1, 0.103505092e2], # cp + [0.427920172e3, 0.644289068e3, 0.480386523e3], # w + ] + res = numpy.zeros((6, 3)) + + for i, (p, T) in enumerate(zip(in_p, in_T)): + res[0][i] = Region2.v2_pT(p, T) + res[1][i] = Region2.h2_pT(p, T) + res[2][i] = Region2.u2_pT(p, T) + res[3][i] = Region2.s2_pT(p, T) + res[4][i] = Region2.Cp2_pT(p, T) + res[5][i] = Region2.w2_pT(p, T) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_MATRIX_ERROR, "Test of *(p,T) Functions for Region 2 failed") + + def test_pT_meta_function(self): + """R7-97(2012) Tests to verify all functions with the Parameters p and T of Metastable-Vapor Region 2""" + # Table 18 + in_p = [1.0, 1.0, 1.5] + in_T = [450.0, 440.0, 450.0] + + ref = [ + [0.192516540, 0.186212297, 0.121685206], # v + [0.276881115e4, 0.274015123e4, 0.272134539e4], # h + [0.257629461e4, 0.255393894e4, 0.253881758e4], # u + [0.656660377e1, 0.650218759e1, 0.629170440e1], # s + [0.276349265e1, 0.298166443e1, 0.362795578e1], # cp + [0.498408101e3, 0.489363295e3, 0.481941819e3], # w ] - R2 = numpy.zeros((6, 3)) - - for i in range(0, 3): - R2[0][i] = Region2.v2_pT(p[i], T[i]) - R2[1][i] = Region2.h2_pT(p[i], T[i]) - R2[2][i] = Region2.u2_pT(p[i], T[i]) - R2[3][i] = Region2.s2_pT(p[i], T[i]) - R2[4][i] = Region2.Cp2_pT(p[i], T[i]) - R2[5][i] = Region2.w2_pT(p[i], T[i]) - - Region2_error = numpy.sum(numpy.absolute((R2 - IF97) / IF97)) - self.assertLess( - Region2_error, - self.maxMatrixError, - "Test of p,T Functions for Region 2 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": Region2_error, "max": self.maxMatrixError}, - ) + res = numpy.zeros((6, 3)) + + for i, (p, T) in enumerate(zip(in_p, in_T)): + res[0][i] = Region2.v2_pT_meta(p, T) + res[1][i] = Region2.h2_pT_meta(p, T) + res[2][i] = Region2.u2_pT_meta(p, T) + res[3][i] = Region2.s2_pT_meta(p, T) + res[4][i] = Region2.Cp2_pT_meta(p, T) + res[5][i] = Region2.w2_pT_meta(p, T) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_MATRIX_ERROR, "Test of *_meta(p,T) Functions for metastable-vapor Region 2 failed.") def test_ph_function(self): - """Tests to verify all functions with the Parameters p and h of Region 2 by comparing the Results to IF-97 Page 25 Table 24""" - # % IF - 97 Table 24, Page 25 - p = [ - 0.01 / 10, - 30 / 10, - 30 / 10, - 50 / 10, - 50 / 10, - 250 / 10, - 400 / 10, - 600 / 10, - 600 / 10, + """R7-97(2012) Tests to verify all functions with the Parameters p and h of subregion 2a, 2b and 2c""" + # Table 24 + in_p = [0.001, 3.0, 3.0, 5.0, 5.0, 25.0, 40.0, 60.0, 60.0] + in_h = [3000.0, 3000.0, 4000.0, 3500.0, 4000.0, 3500.0, 2700.0, 2700.0, 3200.0] + ref = [ + 0.534433241e3, + 0.575373370e3, + 0.101077577e4, + 0.801299102e3, + 0.101531583e4, + 0.875279054e3, + 0.743056411e3, + 0.791137067e3, + 0.882756860e3, ] - h = [3000.0, 3000.0, 4000.0, 3500.0, 4000.0, 3500.0, 2700.0, 2700.0, 3200.0] - IF97 = [ - 534.433241, - 575.37337, - 1010.77577, - 801.299102, - 1015.31583, - 875.279054, - 743.056411, - 791.137067, - 882.75686, - ] - R2 = numpy.zeros(9) - for i in range(0, 9): - R2[i] = Region2.T2_ph(p[i], h[i]) - T2_ph_error = numpy.sum(numpy.absolute((R2 - IF97) / IF97)) - self.assertLess( - T2_ph_error, - self.maxMatrixError, - "Test of ph Function for Region 2 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": T2_ph_error, "max": self.maxMatrixError}, - ) + res = numpy.zeros(9) + for i, (p, h) in enumerate(zip(in_p, in_h)): + res[i] = Region2.T2_ph(p, h) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_MATRIX_ERROR, "Test of T(p,h) Function for Region 2 failed") def test_ps_function(self): - """Tests to verify all functions with the Parameters p and s of Region 2 by comparing the Results to IF-97 Page 29 Table 29""" - # % IF - 97 Table 29, Page 29 - p = [0.1, 0.1, 2.5, 8.0, 8.0, 90.0, 20.0, 80.0, 80.0] - s = [7.5, 8.0, 8.0, 6.0, 7.5, 6.0, 5.75, 5.25, 5.75] - IF97 = [ - 399.517097, - 514.127081, - 1039.84917, - 600.48404, - 1064.95556, - 1038.01126, - 697.992849, - 854.011484, - 949.017998, + """R7-97(2012) Tests to verify all functions with the Parameters p and s of subregion 2a, 2b and 2c""" + # Table 29 + in_p = [0.1, 0.1, 2.5, 8.0, 8.0, 90.0, 20.0, 80.0, 80.0] + in_s = [7.5, 8.0, 8.0, 6.0, 7.5, 6.0, 5.75, 5.25, 5.75] + ref = [ + 0.399517097e3, + 0.514127081e3, + 0.103984917e4, + 0.600484040e3, + 0.106495556e4, + 0.103801126e4, + 0.697992849e3, + 0.854011484e3, + 0.949017998e3, ] - R2 = numpy.zeros(9) - for i in range(0, 9): - R2[i] = Region2.T2_ps(p[i], s[i]) - T2_ps_error = numpy.sum(numpy.absolute((R2 - IF97) / IF97)) - self.assertLess( - T2_ps_error, - self.maxMatrixError, - "Test of ps Function for Region 2 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": T2_ps_error, "max": self.maxMatrixError}, - ) + res = numpy.zeros(9) + for i, (p, s) in enumerate(zip(in_p, in_s)): + res[i] = Region2.T2_ps(p, s) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_MATRIX_ERROR, "Test of T(p,s) Function for Region 2 failed") def test_hs_function(self): - """Tests to verify all functions with the Parameters h and s of Region 2 by comparing the Results to IF-97 Page 6 Table 3""" - # % Supplementary Release on Backward Equations for Pressure as a Function of Enthalpy and Entropy p(h, s) - # % Table 3, Page 6 - h = [2800.0, 2800.0, 4100.0, 2800.0, 3600.0, 3600.0, 2800.0, 2800.0, 3400.0] - s = [6.5, 9.5, 9.5, 6, 6, 7, 5.1, 5.8, 5.8] - IF97 = [ + """SR2-01(2014) Tests to verify all functions with the Parameters h and s of Region 2""" + # Table 9 + in_h = [2800.0, 2800.0, 4100.0, 2800.0, 3600.0, 3600.0, 2800.0, 2800.0, 3400.0] + in_s = [6.5, 9.5, 9.5, 6.0, 6.0, 7.0, 5.1, 5.8, 5.8] + ref = [ 1.371012767, - 0.001879743844, - 0.1024788997, + 1.879743844e-3, + 1.024788997e-1, 4.793911442, - 83.95519209, + 8.395519209e1, 7.527161441, - 94.3920206, + 9.439202060e1, 8.414574124, - 83.76903879, + 8.376903879e1, ] - R2 = numpy.zeros(9) - for i in range(0, 9): - R2[i] = Region2.p2_hs(h[i], s[i]) - p2_hs_error = numpy.sum(numpy.absolute((R2 - IF97) / IF97)) - self.assertLess( - p2_hs_error, - self.maxError, - "Test of hs Function for Region 2 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": p2_hs_error, "max": self.maxError}, - ) + res = numpy.zeros(9) + for i, (h, s) in enumerate(zip(in_h, in_s)): + res[i] = Region2.p2_hs(h, s) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_ERROR, "Test of p(h,s) Function for Region 2 failed") class Region3Tester(unittest.TestCase): + """tests for functions in region 3""" + def setUp(self): - self.maxError = 1e-8 - self.maxMatrixError = 2e-8 # The accumulated Error is bigger than the error of each single function + pass def tearDown(self): pass def test_rhoT_function(self): - """Tests to verify all functions with the Parameters rho and T of Region 3 by comparing the Results to IF-97 Page 32 Table 33""" - # % IF-97 Table 33, Page 32 - T = [650.0, 650.0, 750.0] - rho = [500.0, 200.0, 500.0] - # Fun={'p3_rhoT','h3_rhoT','u3_rhoT','s3_rhoT','Cp3_rhoT','w3_rhoT'}; - IF97 = [ - [25.5837018, 22.2930643, 78.3095639], - [1863.43019, 2375.12401, 2258.68845], - [1812.26279, 2263.65868, 2102.06932], - [4.05427273, 4.85438792, 4.46971906], - [13.8935717, 44.6579342, 6.34165359], - [502.005554, 383.444594, 760.696041], + """R7-97(2012) Tests to verify all functions with the Parameters rho and T of region 3""" + # Table 33 + in_T = [650.0, 650.0, 750.0] + in_rho = [500.0, 200.0, 500.0] + ref = [ + [0.255837018e2, 0.222930643e2, 0.783095639e2], # p + [0.186343019e4, 0.237512401e4, 0.225868845e4], # h + [0.181226279e4, 0.226365868e4, 0.210206932e4], # u + [0.405427273e1, 0.485438792e1, 0.446971906e1], # s + [0.138935717e2, 0.446579342e2, 0.634165359e1], # cp + [0.502005554e3, 0.383444594e3, 0.760696041e3], # w ] - - R3 = numpy.zeros((6, 3)) - for i in range(0, 3): - R3[0][i] = Region3.p3_rhoT(rho[i], T[i]) - R3[1][i] = Region3.h3_rhoT(rho[i], T[i]) - R3[2][i] = Region3.u3_rhoT(rho[i], T[i]) - R3[3][i] = Region3.s3_rhoT(rho[i], T[i]) - R3[4][i] = Region3.Cp3_rhoT(rho[i], T[i]) - R3[5][i] = Region3.w3_rhoT(rho[i], T[i]) - - # print R3 - # print IF97 - Region3_error = numpy.sum(numpy.absolute((R3 - IF97) / IF97)) - self.assertLess( - Region3_error, - self.maxMatrixError, - "Test of rhoT Function for Region 3 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": Region3_error, "max": self.maxMatrixError}, - ) + res = numpy.zeros((6, 3)) + for i, (rho, T) in enumerate(zip(in_rho, in_T)): + res[0][i] = Region3.p3_rhoT(rho, T) + res[1][i] = Region3.h3_rhoT(rho, T) + res[2][i] = Region3.u3_rhoT(rho, T) + res[3][i] = Region3.s3_rhoT(rho, T) + res[4][i] = Region3.Cp3_rhoT(rho, T) + res[5][i] = Region3.w3_rhoT(rho, T) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_MATRIX_ERROR, "Test of *(rho,T) Function for Region 3 failed") def test_T_ph_function(self): - """Tests to verify all temperature functions with the Parameters p and h of Region 3""" - # % T3_ph - p = [20.0, 50.0, 100.0, 20.0, 50.0, 100.0] - h = [1700.0, 2000.0, 2100.0, 2500.0, 2400.0, 2700.0] - IF97 = [ - 629.3083892, - 690.5718338, - 733.6163014, - 641.8418053, - 735.1848618, - 842.0460876, - ] - R3 = numpy.zeros(6) - for i in range(0, 6): - R3[i] = Region3.T3_ph(p[i], h[i]) - T3_ph_error = numpy.sum(numpy.absolute((R3 - IF97) / IF97)) - self.assertLess( - T3_ph_error, - self.maxError, - "Test of T(p,h) Function for Region 3 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": T3_ph_error, "max": self.maxError}, - ) + """SR3-03(2014) Tests to verify T functions with the Parameters p and h of region 3""" + # Table 5 + in_p = [20.0, 50.0, 100.0, 20.0, 50.0, 100.0] + in_h = [1700.0, 2000.0, 2100.0, 2500.0, 2400.0, 2700.0] + ref = [6.293083892e2, 6.905718338e2, 7.336163014e2, 6.418418053e2, 7.351848618e2, 8.420460876e2] + res = numpy.zeros(6) + for i, (p, h) in enumerate(zip(in_p, in_h)): + res[i] = Region3.T3_ph(p, h) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_ERROR, "Test of T(p,h) Function for Region 3 failed") def test_v_ph_function(self): - """Tests to verify all v functions with the Parameters p and h of Region 3""" - # % v3_ph - p = [20.0, 50.0, 100.0, 20.0, 50.0, 100.0] - h = [1700.0, 2000.0, 2100.0, 2500.0, 2400.0, 2700.0] - IF97 = [ - 0.001749903962, - 0.001908139035, - 0.001676229776, - 0.006670547043, - 0.0028012445, - 0.002404234998, - ] - R3 = numpy.zeros(6) - for i in range(0, 6): - R3[i] = Region3.v3_ph(p[i], h[i]) - v3_ph_error = numpy.sum(numpy.absolute((R3 - IF97) / IF97)) - self.assertLess( - v3_ph_error, - 1e-7, - "Test of v(p,h) Function for Region 3 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": v3_ph_error, "max": 1e-7}, - ) + """SR3-03(2014) Tests to verify v functions with the Parameters p and h of region 3""" + # Table 8 + in_p = [20.0, 50.0, 100.0, 20.0, 50.0, 100.0] + in_h = [1700.0, 2000.0, 2100.0, 2500.0, 2400.0, 2700.0] + ref = [1.749903962e-3, 1.908139035e-3, 1.676229776e-3, 6.670547043e-3, 2.801244590e-3, 2.404234998e-3] + res = numpy.zeros(6) + for i, (p, h) in enumerate(zip(in_p, in_h)): + res[i] = Region3.v3_ph(p, h) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_ERROR, "Test of v(p,h) Function for Region 3 failed") def test_T_ps_function(self): - """Tests to verify all T functions with the Parameters p and s of Region 3""" - # % T3_ps - p = [20.0, 50.0, 100.0, 20.0, 50.0, 100.0] - s = [3.7, 3.5, 4, 5, 4.5, 5.0] - IF97 = [ - 620.8841563, - 618.1549029, - 705.6880237, - 640.1176443, - 716.3687517, - 847.4332825, - ] - R3 = numpy.zeros(6) - for i in range(0, 6): - R3[i] = Region3.T3_ps(p[i], s[i]) - T3_ps_error = numpy.sum(numpy.absolute((R3 - IF97) / IF97)) - self.assertLess( - T3_ps_error, - self.maxError, - "Test of T(p,s) Function for Region 3 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": T3_ps_error, "max": self.maxError}, - ) + """SR3-03(2014) Tests to verify T functions with the Parameters p and s of region 3""" + # Table 12 + # FIXME this function used different values from those found in SR3-03! + in_p = [20.0, 50.0, 100.0, 20.0, 50.0, 100.0] + # in_s = [3.7, 3.5, 4, 5, 4.5, 5.0] + in_s = [3.8, 3.6, 4.0, 5.0, 4.5, 5.0] + # ref = [620.8841563, 618.1549029, 705.6880237, 640.1176443, 716.3687517, 847.4332825] + ref = [6.282959869e2, 6.297158726e2, 7.056880237e2, 6.401176443e2, 7.163687517e2, 8.474332825e2] + res = numpy.zeros(6) + for i, (p, s) in enumerate(zip(in_p, in_s)): + res[i] = Region3.T3_ps(p, s) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_ERROR, "Test of T(p,s) Function for Region 3 failed") def test_v_ps_function(self): - """Tests to verify all v functions with the Parameters p and s of Region 3""" - # % v3_ps - p = [20.0, 50.0, 100.0, 20.0, 50.0, 100.0] - s = [3.7, 3.5, 4.0, 5.0, 4.5, 5.0] - IF97 = [ - 0.001639890984, - 0.001423030205, - 0.001555893131, - 0.006262101987, - 0.002332634294, - 0.002449610757, - ] - R3 = numpy.zeros(6) - for i in range(0, 6): - R3[i] = Region3.v3_ps(p[i], s[i]) - v3_ps_error = numpy.sum(numpy.absolute((R3 - IF97) / IF97)) - self.assertLess( - v3_ps_error, - self.maxError, - "Test of v(p,s) Function for Region 3 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": v3_ps_error, "max": self.maxError}, - ) + """SR3-03(2014) Tests to verify all v functions with the Parameters p and s of Region 3""" + # Table 15 + # FIXME this function used different values from those found in SR3-03! + in_p = [20.0, 50.0, 100.0, 20.0, 50.0, 100.0] + # in_s = [3.7, 3.5, 4.0, 5.0, 4.5, 5.0] + in_s = [3.8, 3.6, 4.0, 5.0, 4.5, 5.0] + # ref = [0.001639890984, 0.001423030205, 0.001555893131, 0.006262101987, 0.002332634294, 0.002449610757] + ref = [1.733791463e-3, 1.469680170e-3, 1.555893131e-3, 6.262101987e-3, 2.332634294e-3, 2.449610757e-3] + res = numpy.zeros(6) + for i, (p, s) in enumerate(zip(in_p, in_s)): + res[i] = Region3.v3_ps(p, s) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_ERROR, "Test of v(p,s) Function for Region 3 failed") + + def test_psat_h_function(self): + """SR3-03(2014) Tests to verify p_3sat function with the parameter h of Region 3""" + # Table 18 + in_h = [1700.0, 2000.0, 2400.0] + ref = [1.724175718e1, 2.193442957e1, 2.018090839e1] + res = numpy.zeros(3) + for i, h in enumerate(in_h): + res[i] = Region3.psat3_h(h) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_ERROR, "Test of psat(h) function for Region 3 failed") + + def test_psat_s_function(self): + """SR3-03(2014) Tests to verify p_3sat function with the parameter s of Region 3""" + # Table 20 + in_s = [3.8, 4.2, 5.2] + ref = [1.687755057e1, 2.164451789e1, 1.668968482e1] + res = numpy.zeros(3) + for i, s in enumerate(in_s): + res[i] = Region3.psat3_s(s) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_ERROR, "Test of psat(s) function for Region 3 failed") def test_hs_function(self): - """Tests to verify all functions with the Parameters h and s of Region 3""" - # % p3_hs - h = [1700.0, 2000.0, 2100.0, 2500.0, 2400.0, 2700.0] - s = [3.8, 4.2, 4.3, 5.1, 4.7, 5.0] - IF97 = [ - 25.55703246, - 45.40873468, - 60.7812334, - 17.20612413, - 63.63924887, - 88.39043281, - ] - R3 = numpy.zeros(6) - for i in range(0, 6): - R3[i] = Region3.p3_hs(h[i], s[i]) - p3_hs_error = numpy.sum(numpy.absolute((R3 - IF97) / IF97)) - self.assertLess( - p3_hs_error, - self.maxError, - "Test of p(h,s) Function for Region 3 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": p3_hs_error, "max": self.maxError}, - ) + """SR4-04(2014) Tests to verify p function with the parameters h and s of Region 3""" + # Table 5 + in_h = [1700.0, 2000.0, 2100.0, 2500.0, 2400.0, 2700.0] + in_s = [3.8, 4.2, 4.3, 5.1, 4.7, 5.0] + ref = [2.555703246e1, 4.540873468e1, 6.078123340e1, 1.720612413e1, 6.363924887e1, 8.839043281e1] + res = numpy.zeros(6) + for i, (h, s) in enumerate(zip(in_h, in_s)): + res[i] = Region3.p3_hs(h, s) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_ERROR, "Test of p(h,s) Function for Region 3 failed") def test_pT_function(self): - """Tests to verify all functions with the Parameters p and T of Region 3""" - # % h3_pT (Iteration) - p = [25.583702, 22.293064, 78.309564] - T = [650.0, 650.0, 750.0] - IF97 = [1863.271389, 2375.696155, 2258.626582] - R3 = numpy.zeros(3) - for i in range(0, 3): - R3[i] = Region3.h3_pT(p[i], T[i]) - h3_pT_error = numpy.sum(numpy.absolute((R3 - IF97) / IF97)) - self.assertLess( - h3_pT_error, - 1e-6, - "Test of h(p,T) Function for Region 3 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": h3_pT_error, "max": 1e-6}, - ) + """(source unknown) Tests to verify all functions with the Parameters p and T of Region 3""" + # TODO + in_p = [25.583702, 22.293064, 78.309564] + in_T = [650.0, 650.0, 750.0] + ref = [1863.271389, 2375.696155, 2258.626582] + res = numpy.zeros(3) + for i, (p, T) in enumerate(zip(in_p, in_T)): + res[i] = Region3.h3_pT(p, T) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, 1.7e-7, "Test of h(p,T) Function for Region 3 failed") class Region4Tester(unittest.TestCase): + """tests for functions in region 4""" + def setUp(self): - self.maxError = 1e-7 - self.maxMatrixError = 2e-8 # The accumulated Error is bigger than the error of each single function + pass def tearDown(self): pass def test_T_function(self): - """Tests to verify all functions with the Parameter T of Region 4 by comparing the Results to IF-97 Page 34 Table 35""" - # %Saturation pressure, If97, Table 35, Page 34 - T = [300.0, 500.0, 600.0] - IF97 = [0.00353658941, 2.63889776, 12.3443146] - R4 = numpy.zeros(3) - for i in range(0, 3): - R4[i] = Region4.p4_T(T[i]) - p4_t_error = numpy.sum(numpy.absolute((R4 - IF97) / IF97)) - self.assertLess( - p4_t_error, - self.maxError, - "Test of p(T) Function for Region 4 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": p4_t_error, "max": self.maxError}, - ) + """R7-97(2012) Tests to verify all functions with the Parameters T of region 4""" + # Table 35 + in_T = [300.0, 500.0, 600.0] + ref = [0.353658941e-2, 0.263889776e1, 0.123443146e2] + res = numpy.zeros(3) + for i, T in enumerate(in_T): + res[i] = Region4.p4_T(T) + + p4_t_error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(p4_t_error, REGION_ERROR, "Test of p(T) Function for Region 4 failed") def test_p_functions(self): - """Tests to verify all functions with the Parameters p of Region 4""" - p = [0.1, 1.0, 10.0] - IF97 = [372.755919, 453.035632, 584.149488] - R4 = numpy.zeros(3) - for i in range(0, 3): - R4[i] = Region4.T4_p(p[i]) - T4_p_error = numpy.sum(numpy.absolute((R4 - IF97) / IF97)) - self.assertLess( - T4_p_error, - self.maxError, - "Test of T(p) Function for Region 4 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": T4_p_error, "max": self.maxError}, - ) - - def test_s_functions(self): - """Tests to verify all functions with the Parameters s of Region 4""" - s = [1.0, 2.0, 3.0, 3.8, 4.0, 4.2, 7.0, 8.0, 9.0, 5.5, 5.0, 4.5] - IF97 = [ - 308.5509647, - 700.6304472, - 1198.359754, - 1685.025565, - 1816.891476, - 1949.352563, - 2723.729985, - 2599.04721, - 2511.861477, - 2687.69385, - 2451.623609, - 2144.360448, + """R7-97(2012) Tests to verify all functions with the Parameters p of region 4""" + in_p = [0.1, 1.0, 10.0] + ref = [0.372755919e3, 0.453035632e3, 0.584149488e3] + res = numpy.zeros(3) + for i, p in enumerate(in_p): + res[i] = Region4.T4_p(p) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_ERROR, "Test of T(p) Function for Region 4 failed") + + def test_SR4_04_h_boundary(self): + """SR4-04(2014): computer-program verification for boundary functions for h""" + # Table 11 and Table 18 + in_s = [1.0, 2.0, 3.0, 3.8, 4.0, 4.2, 7.0, 8.0, 9.0, 5.5, 5.0, 4.5] + ref = [ + 3.085509647e2, # h'_1 + 7.006304472e2, # h'_1 + 1.198359754e3, # h'_1 + 1.685025565e3, # h'_3a + 1.816891476e3, # h'_3a + 1.949352563e3, # h'_3a + 2.723729985e3, # h"_2ab + 2.599047210e3, # h"_2ab + 2.511861477e3, # h"_2ab + 2.687693850e3, # h"_2c3b + 2.451623609e3, # h"_2c3b + 2.144360448e3, # h"_2c3b ] - R4 = numpy.zeros(12) - for i in range(0, 12): - R4[i] = Region4.h4_s(s[i]) - h4_s_error = numpy.sum(numpy.absolute((R4 - IF97) / IF97)) - self.assertLess( - h4_s_error, - self.maxError, - "Test of h(s) Function for Region 4 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": h4_s_error, "max": self.maxError}, - ) + res = numpy.zeros(12) + for i, s in enumerate(in_s): + res[i] = Region4.h4_s(s) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_ERROR, "Test of h(s) Function for Region 4 failed") + + def test_Tsat_function(self): + """SR4-04(2014): computer-program verification for Tsat functions (Eq 9) for h and s""" + # Table 29 + + # FIXME + error = abs(Region4.T4_hs(1800.0, 5.3) - 3.468476498e2) / 3.468476498e2 + self.assertLess(error, 3e-7, "Error for T4_hs(s) to big") + + error = abs(Region4.T4_hs(2400.0, 6.0) - 4.251373305e2) / 4.251373305e2 + self.assertLess(error, REGION_ERROR, "Error for T4_hs(s) to big") + + error = abs(Region4.T4_hs(2500.0, 5.5) - 5.225579013e2) / 5.225579013e2 + self.assertLess(error, REGION_ERROR, "Error for T4_hs(s) to big") class Region5Tester(unittest.TestCase): + """tests for functions in region 5""" + def setUp(self): - self.maxError = 1e-8 - self.maxMatrixError = 2e-8 # The accumulated Error is bigger than the error of each single function + pass def tearDown(self): pass def test_pT_function(self): - """Tests to verify all functions with the Parameters p and T of Region 5 by comparing the Results to IF-97 Page 39 Table 42""" - # % IF-97 Table 42, Page 39 - T = [1500.0, 1500.0, 2000.0] - p = [0.5, 8.0, 8.0] - IF97 = [ - [1.38455354, 0.0865156616, 0.115743146], - [5219.76332, 5206.09634, 6583.80291], - [4527.48654, 4513.97105, 5657.85774], - [9.65408431, 8.36546724, 9.15671044], - [2.61610228, 2.64453866, 2.8530675], - [917.071933, 919.708859, 1054.35806], - ] - R5 = numpy.zeros((6, 3)) - for i in range(0, 3): - R5[0][i] = Region5.v5_pT(p[i], T[i]) - R5[1][i] = Region5.h5_pT(p[i], T[i]) - R5[2][i] = Region5.u5_pT(p[i], T[i]) - R5[3][i] = Region5.s5_pT(p[i], T[i]) - R5[4][i] = Region5.Cp5_pT(p[i], T[i]) - R5[5][i] = Region5.w5_pT(p[i], T[i]) - - Region5_error = numpy.sum(numpy.absolute((R5 - IF97) / IF97)) - self.assertLess( - Region5_error, - self.maxMatrixError, - "Test of p,T Function for Region 5 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": Region5_error, "max": self.maxMatrixError}, - ) + """R7-97(2012) Tests to verify all functions with the Parameters rhpo and T of region 5""" + # FIXME this test does not work! the values found in R7-97 do not match with the values found here! + # Table 42 + # in_p = [0.5, 30.0, 30.0] # Table 42 + in_p = [0.5, 8.0, 8.0] # mod + in_T = [1500.0, 1500.0, 2000.0] + # ref = [ + # [0.138455090e1, 0.230761299e-1, 0.311385219e-1], # v + # [0.521976855e4, 0.516723514e4, 0.657122604e4], # h + # [0.452749310e4, 0.447495124e4, 0.563707038e4], # u + # [0.965408875e1, 0.772970133e1, 0.853640523e1], # s + # [0.261609445e1, 0.272724317e1, 0.288569882e1], # cp + # [0.917068690e3, 0.928548002e3, 0.106736948e4], # w + # ] # Table 42 + ref = [ + [1.38455354, 0.0865156616, 0.115743146], # v + [5219.76332, 5206.09634, 6583.80291], # h + [4527.48654, 4513.97105, 5657.85774], # u + [9.65408431, 8.36546724, 9.15671044], # s + [2.61610228, 2.64453866, 2.8530675], # cp + [917.071933, 919.708859, 1054.35806], # w + ] # mod + res = numpy.zeros((6, 3)) + for i, (p, T) in enumerate(zip(in_p, in_T)): + res[0][i] = Region5.v5_pT(p, T) + res[1][i] = Region5.h5_pT(p, T) + res[2][i] = Region5.u5_pT(p, T) + res[3][i] = Region5.s5_pT(p, T) + res[4][i] = Region5.Cp5_pT(p, T) + res[5][i] = Region5.w5_pT(p, T) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_MATRIX_ERROR, "Test of *(p,T) Function for Region 5 failed") def test_ph_function(self): - """Tests to verify all functions with the Parameters p and h of Region 5""" - # %T5_ph (Iteration) - p = [0.5, 8.0, 8.0] - h = [5219.76331549428, 5206.09634477373, 6583.80290533381] - IF97 = [1500.0, 1500.0, 2000.0] - R5 = numpy.zeros(3) - for i in range(0, 3): - R5[i] = Region5.T5_ph(p[i], h[i]) - T5_ph_error = numpy.sum(numpy.absolute((R5 - IF97) / IF97)) - self.assertLess( - T5_ph_error, - self.maxError, - "Test of T(p,h) Function for Region 5 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": T5_ph_error, "max": self.maxError}, - ) + """(source unknown) Tests to verify all functions with the Parameters p and h of Region 5""" + # TODO + in_p = [0.5, 8.0, 8.0] + in_h = [5219.76331549428, 5206.09634477373, 6583.80290533381] + ref = [1500.0, 1500.0, 2000.0] + res = numpy.zeros(3) + for i in range(3): + res[i] = Region5.T5_ph(in_p[i], in_h[i]) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, REGION_ERROR, "Test of T(p,h) Function for Region 5 failed") def test_ps_function(self): - """Tests to verify all functions with the Parameters p and s of Region 5""" - # %T5_ps (Iteration) - p = [0.5, 8.0, 8.0] - s = [9.65408430982588, 8.36546724495503, 9.15671044273249] - IF97 = [1500.0, 1500.0, 2000.0] - R5 = numpy.zeros(3) - for i in range(0, 3): - R5[i] = Region5.T5_ps(p[i], s[i]) - T5_ps_error = numpy.sum(numpy.absolute((R5 - IF97) / IF97)) - self.assertLess( - T5_ps_error, - 1e-4, - "Test of T(p,s) Function for Region 5 failed. Error was %(error)e allowed:" - " %(max)e" % {"error": T5_ps_error, "max": 1e-4}, - ) + """(source unknown) Tests to verify all functions with the Parameters p and s of Region 5""" + # TODO + in_p = [0.5, 8.0, 8.0] + in_s = [9.65408430982588, 8.36546724495503, 9.15671044273249] + ref = [1500.0, 1500.0, 2000.0] + res = numpy.zeros(3) + for i, (p, s) in enumerate(zip(in_p, in_s)): + res[i] = Region5.T5_ps(p, s) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, 1.1e-5, "Test of T(p,s) Function for Region 5 failed") diff --git a/tests/test_TransportProperties.py b/tests/test_TransportProperties.py new file mode 100644 index 0000000..29edea6 --- /dev/null +++ b/tests/test_TransportProperties.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- + +import math +import numpy +import unittest + +from pyXSteam.TransportProperties import surface_tension_T +from pyXSteam.Constants import TRIPLE_POINT_TEMPERATURE, CRITICAL_TEMPERATURE + + +class TransportTester(unittest.TestCase): + """tests for functions in Transport Properties""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_R1_surface_tension(self): + """R1-76(2014) test calculation of surface tension from T""" + # selected values from Table 1 + in_T = [0.011, 30.0, 55.0, 80.0, 105.0, 130.0, 155.0, 180.0, 205.0, 230.0, 255.0, 280.0, 305.0, 330.0, 355.0, 370.0] # in °C + in_T = [t + TRIPLE_POINT_TEMPERATURE for t in in_T] # # quick convert to Klevin + ref = [75.65, 71.19, 67.10, 62.67, 57.94, 52.93, 47.67, 42.19, 36.53, 30.74, 24.87, 18.99, 13.22, 7.70, 2.74, 0.39] + res = numpy.zeros(len(ref)) + + for i, t in enumerate(in_T): + res[i] = surface_tension_T(t) + + error = numpy.sum(numpy.absolute((res - ref) / ref)) + self.assertLess(error, 1e-2, "Test of st(t) failed") + + assert math.isnan(surface_tension_T(TRIPLE_POINT_TEMPERATURE - 0.01)) + + assert math.isnan(surface_tension_T(CRITICAL_TEMPERATURE + 0.01)) diff --git a/tests/test_UnitConverter.py b/tests/test_UnitConverter.py index eac521b..c41e551 100644 --- a/tests/test_UnitConverter.py +++ b/tests/test_UnitConverter.py @@ -4,347 +4,166 @@ """ import unittest -from pyXSteam.XSteam import XSteam -from pyXSteam.UnitConverter import UnitConverter +from pyXSteam import UnitSystem, UnitConverter class UnitConverter_MKS_FunctionTester(unittest.TestCase): def setUp(self): - self.maxError = 1e-8 - self.uc = UnitConverter(XSteam.UNIT_SYSTEM_MKS) + self.maxError = 1e-12 + self.uc = UnitConverter(UnitSystem.MKS) def tearDown(self): pass def test_toSIunit_p_1_MKS(self): - error = self.uc.toSIunit_p(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_p for MKS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = abs(self.uc.toSIunit_p(1.0) - 0.1) + self.assertLess(error, self.maxError, "Test of toSIunit_p for MKS failed") def test_toSIunit_p_2_MKS(self): error = self.uc.toSIunit_p(100.0) - 991.0 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_p for MKS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_p for MKS failed") def test_fromSIunit_p_1_MKS(self): error = self.uc.fromSIunit_p(1.0) - 10.0 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_p for MKS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_p for MKS failed") def test_fromSIunit_p_2_MKS(self): error = self.uc.fromSIunit_p(100.0) - 1000.0 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_p for MKS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_p for MKS failed") def test_toSIunit_T_1_MKS(self): error = self.uc.toSIunit_T(1.0) - 274.15 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_T for MKS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_T for MKS failed") def test_toSIunit_T_2_MKS(self): error = self.uc.toSIunit_T(1.0) - 274.15 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_T for MKS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_T for MKS failed") def test_fromSIunit_T_1_MKS(self): error = self.uc.fromSIunit_T(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_T for MKS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_T for MKS failed") def test_fromSIunit_T_2_MKS(self): error = self.uc.fromSIunit_T(42.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_T for MKS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_T for MKS failed") class UnitConverter_FLS_FunctionTester(unittest.TestCase): def setUp(self): self.maxError = 1e-8 - self.uc = UnitConverter(XSteam.UNIT_SYSTEM_FLS) + self.uc = UnitConverter(UnitSystem.FLS) def tearDown(self): pass def test_toSIunit_p_FLS(self): error = self.uc.toSIunit_p(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_p for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_p for FLS failed") def test_fromSIunit_p_FLS(self): error = self.uc.fromSIunit_p(1.0) - 145.0377377968587 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_p for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_p for FLS failed") def test_toSIunit_T_FLS(self): error = self.uc.toSIunit_T(1.0) - 274.15 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_T for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_T for FLS failed") def test_fromSIunit_T_FLS(self): error = self.uc.fromSIunit_T(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_T for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_T for FLS failed") def test_toSIunit_h_FLS(self): error = self.uc.toSIunit_h(1.0) - 2.326 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_h for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_h for FLS failed") def test_fromSIunit_h_FLS(self): error = self.uc.fromSIunit_h(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_h for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_h for FLS failed") def test_toSIunit_v_FLS(self): error = self.uc.toSIunit_v(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_v for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_v for FLS failed") def test_fromSIunit_v_FLS(self): error = self.uc.fromSIunit_v(1.0) - 16.018463367839058 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_v for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_v for FLS failed") def test_toSIunit_s_FLS(self): error = self.uc.toSIunit_s(1.0) - 4.1868000000086933 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_s for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_s for FLS failed") def test_fromSIunit_s_FLS(self): error = self.uc.fromSIunit_s(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_s for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_s for FLS failed") def test_toSIunit_u_FLS(self): error = self.uc.toSIunit_u(1.0) - 2.326 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_u for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_u for FLS failed") def test_fromSIunit_u_FLS(self): error = self.uc.fromSIunit_u(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_u for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_u for FLS failed") def test_toSIunit_Cp_FLS(self): error = self.uc.toSIunit_Cp(1.0) - 4.1867981879537446 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_Cp for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_Cp for FLS failed") def test_fromSIunit_Cp_FLS(self): error = self.uc.fromSIunit_Cp(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_Cp for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_Cp for FLS failed") def test_toSIunit_Cv_FLS(self): error = self.uc.toSIunit_Cv(1.0) - 4.1867981879537446 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_Cv for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_Cv for FLS failed") def test_fromSIunit_Cv_FLS(self): error = self.uc.fromSIunit_Cv(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_Cv for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_Cv for FLS failed") def test_toSIunit_w_FLS(self): error = self.uc.toSIunit_w(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_w for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_w for FLS failed") def test_fromSIunit_w_FLS(self): error = self.uc.fromSIunit_w(1.0) - 3.280839895013123 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_w for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_w for FLS failed") def test_toSIunit_tc_FLS(self): error = self.uc.toSIunit_tc(1.0) - 1.7307356145582558 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_tc for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_tc for FLS failed") def test_fromSIunit_tc_FLS(self): error = self.uc.fromSIunit_tc(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_tc for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_tc for FLS failed") def test_toSIunit_st_FLS(self): error = self.uc.toSIunit_st(1.0) - 14.593902906705587 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_st for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_st for FLS failed") def test_fromSIunit_st_FLS(self): error = self.uc.fromSIunit_st(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_st for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_st for FLS failed") def test_toSIunit_x_FLS(self): error = self.uc.toSIunit_x(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_x for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_x for FLS failed") def test_fromSIunit_x_FLS(self): error = self.uc.fromSIunit_x(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_x for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_x for FLS failed") def test_toSIunit_vx_FLS(self): error = self.uc.toSIunit_vx(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_vx for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_vx for FLS failed") def test_fromSIunit_vx_FLS(self): error = self.uc.fromSIunit_vx(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_vx for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_vx for FLS failed") def test_toSIunit_my_FLS(self): error = self.uc.toSIunit_my(1.0) - 1.0 - self.assertLess( - error, - self.maxError, - "Test of toSIunit_my for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of toSIunit_my for FLS failed") def test_fromSIunit_my_FLS(self): error = self.uc.fromSIunit_my(1.0) - 2419.088311 - self.assertLess( - error, - self.maxError, - "Test of fromSIunit_my for FLS failed. Error was %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + self.assertLess(error, self.maxError, "Test of fromSIunit_my for FLS failed") diff --git a/tests/test_fixedbugs.py b/tests/test_fixedbugs.py index 58171bb..57d7aeb 100644 --- a/tests/test_fixedbugs.py +++ b/tests/test_fixedbugs.py @@ -1,64 +1,51 @@ # -*- coding: utf-8 -*- """ +This module tests the situations that where reported directly via github issues or +via bug reports in related projects """ import unittest from pyXSteam.XSteam import XSteam -class FixedBugs_Tester(unittest.TestCase): +class FixedBugsTester(unittest.TestCase): + """Test for all issues and bug reports""" + def setUp(self): - self.maxError = 1e-6 - self.steamTable = XSteam(XSteam.UNIT_SYSTEM_MKS) + self.max_error = 1e-6 + self.steam_table = XSteam(XSteam.UNIT_SYSTEM_MKS) def tearDown(self): pass def test_inf_loop_h_pt(self): - # Bug: calling XSteam('h_pt',800,554) creates an infinite loop. - # reported by Miika Wallius on 3 Jul 2020 - # https://www.mathworks.com/matlabcentral/fileexchange/9817-x-steam-thermodynamic-properties-of-water-and-steam + """Bug: calling XSteam('h_pt',800,554) creates an infinite loop. + reported by Miika Wallius on 3 Jul 2020 + https://www.mathworks.com/matlabcentral/fileexchange/9817-x-steam-thermodynamic-properties-of-water-and-steam + """ - error = self.steamTable.h_pt(800.0, 554.0) - 2733.6986817 - self.assertLess( - error, - self.maxError, - "h_pt not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = self.steam_table.h_pt(800.0, 554.0) - 2733.6986817 + self.assertLess(error, self.max_error, "h_pt not passed") def test_inf_loop_rho_pt(self): - # Bug: pyXSteam hangs - # reported by @annhak as issue #10 - # https://github.com/drunsinn/pyXSteam/issues/10 + """Bug: pyXSteam hangs + reported by @annhak as issue #10 + https://github.com/drunsinn/pyXSteam/issues/10 + """ - error = self.steamTable.rho_pt(167.11, 351.73) - 113.6761489 - self.assertLess( - error, - self.maxError, - "rho_pt not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = self.steam_table.rho_pt(167.11, 351.73) - 113.6761489 + self.assertLess(error, self.max_error, "rho_pt not passed") def test_missing_unit_conversion_h_xx(self): - # Bug: missing unit conversion in h_px for FLS units - # reported by Grayson Gall on 29 Jan 2022 - # https://www.mathworks.com/matlabcentral/fileexchange/9817-x-steam-thermodynamic-properties-of-water-and-steam + """Bug: missing unit conversion in h_px for FLS units + reported by Grayson Gall on 29 Jan 2022 + https://www.mathworks.com/matlabcentral/fileexchange/9817-x-steam-thermodynamic-properties-of-water-and-steam + """ - self.steamTable._unit_converter.set_unitSystem(XSteam.UNIT_SYSTEM_FLS) + self.steam_table._unit_converter.set_unitSystem(XSteam.UNIT_SYSTEM_FLS) - error = self.steamTable.h_px(160, 0.5) - 765.8069264 - self.assertLess( - error, - self.maxError, - " not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = self.steam_table.h_px(160, 0.5) - 765.8069264 + self.assertLess(error, self.max_error, " not passed") - error = self.steamTable.h_tx(160, 0.5) - 628.905695 - self.assertLess( - error, - self.maxError, - " not passed Error %(error)e allowed: %(max)e" - % {"error": error, "max": self.maxError}, - ) + error = self.steam_table.h_tx(160, 0.5) - 628.905695 + self.assertLess(error, self.max_error, " not passed")